2020-09 前端技术汇总

2020/09/30 周三
#AMD、UMD、CommonJS、ES Modules的理解
在ES6之前,JS本身没有模块功能,社区出现了 CommonJS 和 AMD 等模块方案,ES6后, JS开始原生支持模块,一般称之为 ES Modules

CommonJS: 主要用于服务端,是 node 中使用的 require、module.exports。从 Node.js v13.2 版本开始,Node.js 已经默认打开了 ES6 模块支持。但需要采用 .mjs 后缀文件名。如果不希望将后缀名改成.mjs,可以在项目的package.json文件中,指定type字段为module。
AMD: Asynchronous Module Definition,异步模块定义,主要用于客户端(浏览器),以 RequireJS 为代表 define、require
UMD: Universal Module Definition,通用模块定义模式,主要用来解决 CommonJS 模式和 AMD 模式代码不能通用的问题,并同时还支持老式的全局变量规范。
ES Modules 是 ES 标准模块系统,import、export ,可以和 CommonJS混合使用
/*

  • bundle.js UMD webpack打包后的js

  • 判断define为函数,并且是否存在define.amd,来判断是否为AMD规范,

  • 判断module是否为一个对象,并且是否存在module.exports来判断是否为CommonJS规范

  • 如果以上两种都没有,设定为原始的代码规范。
    */
    (function (global, factory) {
    typeof exports === ‘object’ && typeof module !== ‘undefined’ ? module.exports = factory() :
    typeof define === ‘function’ && define.amd ? define(factory) :
    (global = global || self, global.myBundle = factory());
    }(this, (function () { ‘use strict’;

    var main = () => {
    return ‘hello world’;
    };

    return main;

})));
// index.html

区别:

CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。CommonJS一旦输出一个值,模块内部的变化就影响不到这个值。ES6 模块的运行机制与 CommonJS 不一样。JS 引擎对脚本静态分析的时候,遇到模块加载命令import,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。
CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。因为 CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。
CommonJS 模块的require()是同步加载模块,ES6 模块的import命令是异步加载,有一个独立的模块依赖的解析阶段。
// CommonJS模块
let { stat, exists, readfile } = require(‘fs’);

// 等同于
let _fs = require(‘fs’);
let stat = _fs.stat;
let exists = _fs.exists;
let readfile = _fs.readfile;

// ES6模块
import { stat, exists, readFile } from ‘fs’;
参考

《模块化系列》彻底理清 AMD,CommonJS,CMD,UMD,ES6(opens new window)
Module 的语法 | ES6入门(opens new window)
Module 的加载实现 | ES6入门(opens new window)
#Script error产生原因与解决方法、调试技巧
一般为了安全起见,如果当前页面引入了跨域的 js 文件,当这个 js 文件出现错误,监听错误会无法获取对应的行号、message。仅会将 message 设置为 Script error.

本地来做一个试验,重现该问题,用 koa 写两个服务,分别监听 5001/5002端口,同时开启服务

/**

  • index_a.js
  • index_b.js 代码和下面的基本一致,只是将 5001 改为 5002
    */
    const Koa = require(‘koa’)
    const app = new Koa()

app.use(require(‘koa-static’)(__dirname + ‘/public’))

app.listen(‘5001’, () => {
console.log(‘server listen on 5001 port’)
})
public/index.html 测试页面中,我们引入 5001端口的 a.js 或 5002 端口的 a.js,看具体 error 信息

点击

cross_origin_script_error.png

知道问题后,我们可以通过使用同域的方式引入 js。如果一定要使用跨域的,需要设置下面两点

script引入时加入 crossorigin=“anonymous”,anonymous 即不发送 Cookie 和 HTTP 认证信息
服务器对应的js,增加允许跨域
// html里
//
// index_b.js 5002端口增加允许跨域

const Koa = require(‘koa’)
const app = new Koa()
// 允许跨域
app.use(async (ctx, next) => {
ctx.set({
‘Access-Control-Allow-Origin’: ‘’,
‘Access-Control-Allow-Headers’: '
’,
‘Access-Control-Allow-Methods’: ‘*’,
‘Access-Control-Allow-Credentials’: ‘true’, // 允许携带cookie
‘Access-Control-Max-Age’: 3600 // 对于相同的请求,仅在第一次发送options预检请求,之后1小时内不需要预检请求
})
await next()
})
app.use(require(‘koa-static’)(__dirname + ‘/public’))
app.listen(‘5002’, () => {
console.log(‘server listen on 5002 port’)
})
设置好后,我们再测试就会发现可以正常显示跨域的信息了。如下图,完整demo参见 跨域Script_error测试demo | github(opens new window)

cross_origin_script_error_fix.png

参考:Script error.全面解析 | Fundebug(opens new window)

#2020/09/26 周六
#为什么会有回流/重排(Reflow)和重绘(Repaint)?怎么避免?

  1. 什么是回流或重绘

浏览器使用流式布局模型 (Flow Based Layout)
浏览器把 HTML 解析成 DOM,把 CSS 解析为 CSDOM,DOM 和 CSDOM 合并就产生了 Render Tree(渲染树)
根据Render Tree,计算各个元素在页面中的大小和位置,绘制到页面上。
回流/重排(Reflow):当 Render Tree 中部分或全部元素的尺寸、结构或位置发生改变时,浏览器会重新渲染部分或整个文档的过程就称为Reflow

重绘(RePaint): 当页面中元素样式的改变并不影响它在文档中的位置时,浏览器会重绘该区域,这个过程称为重绘

  1. 回流和重绘的比较

DOM、CSS style的改变会照成回流或者重绘,回流比重绘更消耗性能

回流:重新布局,会引起元素位置变化的就会reflow,比如修改 DOM 的宽高、字体大小、窗口大小改变、元素位置改变等
重绘:重新绘制区域,不改变元素位置,比如修改背景、颜色,visibility等
3. 如何避免回流或重绘

CSS:

尽可能在DOM树的最末端改变class
避免设置多层内联样式,将动画效果应用到 position 属性为 absolute 或 fixed 的元素上
避免使用CSS表达式(例如:calc())
JavaScript

避免频繁操作样式、DOM
在 documentFragment 或 display 为 none 的元素上进行 dom 操作不会引起回流或重绘
对复杂动画,使用绝对定位脱离文档流,避免整体回流
参考:

浏览器的回流与重绘 (Reflow & Repaint) | 掘金(opens new window)
使用chrome对页面重绘和回流做优化(opens new window)
#图片占位、懒加载、预览
使用占位图片有什么好处?

用户体验更好,标识此处有图片,但正在加载中的这一个状态,避免弱网或图片较大时,完全不显示的问题
不阻塞其他资源加载,更快的整体文档加载速度,不阻塞其他请求。占位图片一般会和图片懒加载一起使用,当滚动到该区域时再加载图片,减少不必要的并发网络请求
可以避免回流,让图片加载完成后不改变页面的整体布局,避免回流(重新布局),只需要重绘,注意: 需要占位图片与实际图片宽高不变
怎么实现图片懒加载

这里核心问题是怎么判断图片是否已滚动到当前视口。一般可以通过监听页面滚动事件,实时比较元素的 offsetTop 与页面的 scrollTop。另外还可以通过元素的 getBoundingClientRect() 获取当前元素距离视窗的距离,如果小于 window.innerHeight 就加载,下面来看一个简单的实现

我是占位文本
我是占位文本
图片预览

可以参考Element UI el-image组件实现,Element UI 大图预览 | el-image(opens new window)

参考资料与扩展

前端为什么要使用占位图 | segmentfault(opens new window)
图片懒加载和预加载 | 简书(opens new window)
如何判断元素是否进入可视区域viewport?| 掘金(opens new window)
#Chrome DevTools Network Waterfall各阶段详解
在Chrom调试工具Network tab下,每个请求都有一个Waterfal diagrams(瀑布图),点击具体接口,Timming(时序)位置会有具体描述。它记录了网络请求各个阶段的耗时,可以用于分析页面加载性能。

waterfall-hover.png

Timing breakdown phases explained(时序分解阶段明细)

Here’s more information about each of the phases you may see in the Timing tab:(下面是在Timing标签页中能看到的各个阶段的更多信息)

  1. Resource Scheduling(资源调度)

Queueing(排队). The browser queues requests when:(浏览器在以下情况会排队请求)
There are higher priority requests.(有更高优先级的请求)
There are already six TCP connections open for this origin, which is the limit. Applies to HTTP/1.0 and HT

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值