构建

webpack

热更新

1、启动node层的dev服务,并在web页面注入自己的entry脚本,用于启动websocket连接等

2、编译模块为立即执行函数,保留模块的文件hash和模块间依赖关系图,监听文件变化

3、文件变化时重新计算hash并对比,替换变化模块,重新执行模块函数以及其关联依赖

优化构建

体积优化

  • 懒加载:只加载当前界面需要的代码,可以结合预加载来优化等待时间,合理利用动态import。

  • 按需加载:只加载依赖库用到的模块,而非加载整个库,比如antd结合plugin-import、moment只加载需要的语言库等。

  • treeshaking:webpack内置优化,构建时丢弃模块未被使用的代码,但需要满足模块代码干净无副作用,比如加载第三方库时指定加载其es版本,更利于webpack做treeshaking优化。

  • 代码压缩:webpack已在生产模式内置,比如uglifyjs。

  • 分离CSS:把样式独立到css文件,或者异步加载,不阻塞js执行。

  • chunk粒度权衡:将多个异步模块共用的依赖提取出来,统一加载,就可以不必在每个异步模块中都重复打包这些共用依赖,但要考虑chunk粒度,太粗起不到优化效果,太细会拖慢主模块的加载,合理使用splitchunks配置。

速度优化

  • loader粒度精细:每一类文件只经过它必须的loader。

  • 多线程编译:webpack5内置的Terser plugin已开启parallel,或者手动使用happypack之类的plugin。

  • 编译缓存:webpack5已经内置了模块缓存策略,或者手动使用cache-loader、dll之类的工具。

  • (对于ts项目)类型检查放到异步:transpileOnly结合fork-ts-checker-webpack-plugin。

用户网络资源优化

  • 基于contenthash命名模块:模块内容改变文件名才会改变。

  • 提取公共依赖:将不常变动的第三方库从业务代码中独立成一个模块,这个模块的内容可以比较稳定。

rollup

更纯粹的打包工具,适合库而非应用(app)

gulp

流式任务

babel

和polyfill关系:babel只转语法,polyfill拓展原型和全局对象

原理:text => tokens => ast => ast(transformed) => text

babel如何直接运行于浏览器?

以此版本 https://unpkg.com/babel-standalone@6.26.0/babel.js 的babel为例:

  1. 监听DOMContentLoaded事件,事件触发后会选取所有typetext/jsxtext/babelscript存入jsxScripts数组。
  2. 遍历数组,将scriptEl.innerHTML作为源码调用babel核心方法编译为结果代码(带srcscript用ajax异步获取content作为源码,在回调中处理编译)。
  3. 编译完成后新建script元素,将scriptEl.text设置为结果代码,appendheadEl,此时浏览器会自动执行该script