让我们向项目中再添加一个模块 print.js
:
project
webpack-demo|- package.json|- webpack.config.js|- /dist|- /src |- index.js+ |- print.js|- /node_modules
print.js
+ export default function print(text) {+ console.log(text);+ };
src/index.js
import _ from 'lodash';+ import Print from './print'; function component() { var element = document.createElement('div'); // lodash 是由当前 script 脚本 import 导入进来的 element.innerHTML = _.join(['Hello', 'webpack'], ' ');+ element.onClick = Print.bind(null, 'Hello webpack!'); return element; } document.body.appendChild(component());
再次运行构建,然后我们期望的是,只有 main
bundle 的 hash 发生变化,然而……
Hash: d38a06644fdbb898d795Version: webpack 3.3.0Time: 1445ms Asset Size Chunks Chunk Names vendor.a7561fb0e9a071baadb9.js 541 kB 0 [emitted] [big] vendor main.b746e3eb72875af2caa9.js 1.22 kB 1 [emitted] main runtime.1400d5af64fc1b7b3a45.js 5.85 kB 2 [emitted] runtime index.html 352 bytes [emitted] [1] ./src/index.js 421 bytes {1} [built] [2] (webpack)/buildin/global.js 509 bytes {0} [built] [3] (webpack)/buildin/module.js 517 bytes {0} [built] [4] ./src/print.js 62 bytes {1} [built] [5] multi lodash 28 bytes {0} [built] + 1 hidden module
……我们可以看到这三个文件的 hash 都变化了。这是因为每个 会基于默认的解析顺序(resolve order)进行增量。也就是说,当解析顺序发生变化,ID 也会随之改变。因此,简要概括:
main
bundle 会随着自身的新增内容的修改,而发生变化。vendor
bundle 会随着自身的module.id
的修改,而发生变化。runtime
bundle 会因为当前包含一个新模块的引用,而发生变化。
第一个和最后一个都是符合预期的行为 -- 而 vendor
的 hash 发生变化是我们要修复的。幸运的是,可以使用两个插件来解决这个问题。第一个插件是 ,将使用模块的路径,而不是数字标识符。虽然此插件有助于在开发过程中输出结果的可读性,然而执行时间会长一些。第二个选择是使用 ,推荐用于生产环境构建:
webpack.config.js
const path = require('path'); const webpack = require('webpack'); const CleanWebpackPlugin = require('clean-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: { main: './src/index.js', vendor: [ 'lodash' ] }, plugins: [ new CleanWebpackPlugin(['dist']), new HtmlWebpackPlugin({ title: 'Caching' }),+ new webpack.HashedModuleIdsPlugin(), new webpack.optimize.CommonsChunkPlugin({ name: 'vendor' }), new webpack.optimize.CommonsChunkPlugin({ name: 'runtime' }) ], output: { filename: '[name].[contenthash].js', path: path.resolve(__dirname, 'dist') } };
现在,不管再添加任何新的本地依赖,对于每次构建,vendor
hash 都应该保持一致:
Hash: 1f49b42afb9a5acfbaffVersion: webpack 3.3.0Time: 1372ms Asset Size Chunks Chunk Names vendor.eed6dcc3b30cfa138aaa.js 541 kB 0 [emitted] [big] vendor main.d103ac311788fcb7e329.js 1.22 kB 1 [emitted] main runtime.d2a6dc1ccece13f5a164.js 5.85 kB 2 [emitted] runtime index.html 352 bytes [emitted] [3Di9] ./src/print.js 62 bytes {1} [built] [3IRH] (webpack)/buildin/module.js 517 bytes {0} [built] [DuR2] (webpack)/buildin/global.js 509 bytes {0} [built] [0] multi lodash 28 bytes {0} [built] [lVK7] ./src/index.js 421 bytes {1} [built] + 1 hidden module
然后,修改我们的 src/index.js
,临时移除额外的依赖:
src/index.js
import _ from 'lodash';- import Print from './print';+ // import Print from './print'; function component() { var element = document.createElement('div'); // lodash 是由当前 script 脚本 import 导入进来的 element.innerHTML = _.join(['Hello', 'webpack'], ' ');- element.onClick = Print.bind(null, 'Hello webpack!');+ // element.onClick = Print.bind(null, 'Hello webpack!'); return element; } document.body.appendChild(component());
最后,再次运行我们的构建:
Hash: 37e1358f135c0b992f72Version: webpack 3.3.0Time: 1557ms Asset Size Chunks Chunk Names vendor.eed6dcc3b30cfa138aaa.js 541 kB 0 [emitted] [big] vendor main.fc7f38e648da79db2aba.js 891 bytes 1 [emitted] main runtime.bb5820632fb66c3fb357.js 5.85 kB 2 [emitted] runtime index.html 352 bytes [emitted] [3IRH] (webpack)/buildin/module.js 517 bytes {0} [built] [DuR2] (webpack)/buildin/global.js 509 bytes {0} [built] [0] multi lodash 28 bytes {0} [built] [lVK7] ./src/index.js 427 bytes {1} [built] + 1 hidden module
我们可以看到,这两次构建中,vendor
bundle 的文件名称,都是 eed6dcc3b30cfa138aaa
。