假如文件中引入了异步模块,异步模块修改后会影响编译输出的js文件的chunkhash吗?现在入口文件中引入异步模块a.js,a.js文件又异步引入b.js,b.js同步引入c模块
//entry.js 'use strict'; import './saveCarInfo.js'; window.onload = function(){//懒加载 require.ensure(['./a.js'],function(require){ var moduleA = require('./a.js'); },'a'); };
//a.js 'use strict' console.log("a"); setTimeout(function(){ require.ensure([],function(require){ require('./b.js'); },'b'); },10000); module.exports = "moduleA";
//b.js import fn_c from './c.js'; console.log('b'); module.exports = 'moduleB';
//c.js console.log("c"); module.exports = "moduleC";
运行npm run deploy,编译输出如下,我们看到除了入口文件、css文件、html文件被输出外,异步加载的模块a.js、b.js也被当做独立模块输出。
此时修改a.js文件中的代码,经编译后,a.[chunkhash].js的chunkhash会改变,而生成的主文件app.[chunkhash].js的chunkhash值并没有改变。原因是webpack-md5-hash的这种计算方式把异步模块的内容忽略掉了,这会造成一个问题:异步模块的修改并未影响主文件的chunkhash值。解决办法是将输出的主文件采用[hash],而非[chunkhash]
output:{ path:path.resolve(__dirname, 'dist'), publicPath:'../',//生成的html里的引用路径用 publicPath filename: 'js/[name].[hash:8].js', //异步加载的模块是要以文件形式加载,生成的文件名是以chunkFilename配置的 chunkFilename: 'js/[name].[chunkhash:8].js' },
这种做法也存在缺陷,如果项目中存在不止一个主js文件,修改任意js代码会影响所有最终主文件的[hash]值。例如上面的项目配置中会生成两个带[hash]的主文件:app.[hash].js, mobile.[hash].js。无论是修改entry.js代码还是异步模块a.js,或b.js的代码,app.[hash].js和mobile.[hash].js的[hash]都会改变。
补充:npm提供了webpack-split-hash插件代替webpack-md5-hash,该插件可以获取到各异步模块的hash值,然后将这些hash值与主文件的代码内容一同作为计算hash的参数,这样就能保证主文件的hash值会跟随异步模块的修改而修改。但我验证后没有实现。。。
4.使用html-webpack-plugin动态生成html
配置文件中的输出文件都带了[chunkhash]作为版本号,在style或js文件改变时,其值都会随之改变。利用html-webpack-plugin在webpack完成前端资源打包以后,自动将打包后的资源路径和版本号写入HTML中,达到自动化的效果。
//webpack.production.config.js var HtmlWebpackPlugin = require('html-webpack-plugin'); ... var config = { ... plugins:[ ... new HtmlWebpackPlugin({ filename:'view/index.html', //生成的html存放路径,相对于 path template:'src/view/index.html', //html模板路径 inject:true, //允许插件修改哪些内容,true/'head'https://www.jb51.net/'body'/false, chunks:['vendors','app'],//加载指定模块中的文件,否则页面会加载所有文件 hash:false, //为静态资源生成hash值 minify:{ //压缩HTML文件 removeComments:false, //移除HTML中的注释 collapseWhitespace:false //删除空白符与换行符 } }), new HtmlWebpackPlugin({ filename:'view/mobile.html', //生成的html存放路径,相对于 path template:'src/view/mobile.html', //html模板路径 inject:true, //允许插件修改哪些内容,true/'head'https://www.jb51.net/'body'/false, chunks:['vendors','mobile'],//加载指定模块中的文件,否则页面会加载所有文件 hash:false, //为静态资源生成hash值 minify:{ //压缩HTML文件 removeComments:false, //移除HTML中的注释 collapseWhitespace:false //删除空白符与换行符 } }) ]}