深入理解 webpack 文件打包机制(小结)(8)
可以看出,原本基于回调函数的方式已经变成基于 Promise 做异步处理,另外添加了 onScriptComplete 用于做脚本加载失败处理。
在 webpack1 的时候,如果由于网络原因当你加载脚本失败后,即使网络恢复了,你再次进行某种操作需要同个 chunk 时候都会无效,主要原因是失败之后没把 installedChunks[chunkId] = undefined; 导致之后不会再对该 chunk 文件发起异步请求。
而在 webpack2 中,当脚本请求超时了(2min)或者加载失败,会将 installedChunks[chunkId] 清空,当下次重新请求该 chunk 文件会重新加载,提高了页面的容错性。
这些是我在打包文件中看到主要的区别,难免有所遗漏,如果你有更多的见解,欢迎在评论区留言。
webpack2 如何做到 tree shaking?
什么是 tree shaking,即 webpack 在打包的过程中会将没用的代码进行清除(dead code)。一般 dead code 具有一下的特征:
- 代码不会被执行,不可到达
- 代码执行的结果不会被用到
- 代码只会影响死变量(只写不读)
是不是很神奇,那么需要怎么做才能使 tree shaking 生效呢?
首先,模块引入要基于 ES6 模块机制,不再使用 commonjs 规范,因为 es6 模块的依赖关系是确定的,和运行时的状态无关,可以进行可靠的静态分析,然后清除没用的代码。而 commonjs 的依赖关系是要到运行时候才能确定下来的。
其次,需要开启 UglifyJsPlugin 这个插件对代码进行压缩。
我们先写一个例子来说明:
// src/es6/pageA.js import { utilA, funcA, // 引入 funcA 但未使用, 故 funcA 会被清除 } from './js/utilA'; import utilB from './js/utilB'; // 引入 utilB(函数) 未使用,会被清除 import classC from './js/utilC'; // 引入 classC(类) 未使用,不会被清除 console.log(utilA); // src/es6/js/utilA.js export const utilA = 'util A'; export function funcA() { console.log('func A'); } // src/es6/js/utilB.js export default function() { console.log('func B'); } if(false) { // 被清除 console.log('never use'); } while(true) {} console.log('never use'); // src/es6/js/utilC.js const classC = function() {} // 类方法不会被清除 classC.prototype.saySomething = function() { console.log('class C'); } export default classC;
打包的配置也很简单:
const webpack = require('webpack'); const path = require('path') module.exports = { entry: { pageA: path.resolve(__dirname, '../src/es6/pageA.js'), }, output: { path: path.resolve(__dirname, '../dist'), filename: '[name].[chunkhash:8].js' }, plugins: [ new webpack.optimize.CommonsChunkPlugin({ name: 'manifest', minChunks: Infinity, }), new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }) ] }
内容版权声明:除非注明,否则皆为本站原创文章。