没有其它模块了,因此合并输出一个文件名字 vendors~main.chunk.js ,其中 verdors 是策略的名字,~ 波浪线是 automaticNameDelimiter 的配置, main 是 entry 入口文件的名字, chunk.js 是 filename 中设置的后缀。
异步模块打包:
import(/* webpackChunkName: "lodash" */"lodash").then(({default:_})=>{ console.log(_.join(["a","b"],"-")); }) import(/* webpackChunkName: "jquery" */"jquery").then(({default:$})=>{ $(function () { console.log("jquery 已经加载完成"); }) })分析:
首先模块为了满足懒加载需求会根据魔法注释 webpackChunkName 打包成单独的模块如 jquery.bundle.js 和 lodash.bundle.js
同样它会去 cacheGroups 中查找是否匹配相应的策略,此时发现 vendors 匹配不了, default 策略可以匹配,但是 default 中有一个配置是 reuseExistingChunk: true 表示会去已经打包好模块中查找,如果已经被打包了就输出。把它改为 false 后,则会把 jquery.bundle.js 根据策略重新命名为 default~jquery.bundle.js 由于它是异步加载的,首页两个模块不会被合并,分别输出。
cacheGroups 中的策略可以根据项目自行添加,因此而且 webpack 提供了各种回调方法使得配置更加灵活。
CSS 文件代码分割随着项目的增大 css 文件是非常的多,如果都打包到 js 中,势必是的 js 文件过于臃肿,影响加载速度,因此我们要把 css 分离打包。
MiniCssExtractPlugin 它会帮助我们创建一个新的 css 文件
OptimizeCSSAssetsPlugin 它会帮助我们合并压缩 css 文件
我们来看看具体配置:
... const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); module.exports = { mode: 'production', // 只有在production的模式下,才会去执行minimizer里面的配置 optimization: { ... minimizer: [ new OptimizeCSSAssetsPlugin({}) ] }, module:{ rules:[ { test:/\.css$/, use:[ MiniCssExtractPlugin.loader, // 这里要使用 MiniCssExtractPlugin 提供的 loader 'css-loader' ] } ] }, plugins: [ ... new MiniCssExtractPlugin({ // 在插件中初始化MiniCssExtractPlugin,并且配置好独立出来的CSS文件的命名规则 filename: "[name].css", chunkFilename: "[id].chunk.css" }) ] }还有一个重点要记得,就是生产环境下,我们默认开启了 Tree Shaking ,因此需要配置 package.json 中的 sideEffects ,否则 css 文件会被 Tree Shaking 掉。
"sideEffects": ["*.css"] // 所有 .css 的文件都不进行 tree shaking配置好后执行打包命令发现可以单独分离出 css 文件并且 css 文件是经过压缩的。
配置 CSS cacheGroups splitChunks: { ... cacheGroups: { ... styles: { name: 'styles', test: /\.css$/, chunks: 'all', enforce: true, }, ... } }增加一条 styles 策略,这样打包输出的名字为 styles.css 就是这条策略的名字 enforce: true 表示 styles 策略忽略 splitChunks 的其它参数配置。
模块懒加载模块懒加载不需要我们再去做 webpack 的配置,而是使用 ES6 提供的 import() 语法来支持
我们来对比下面两段业务代码:
document.addEventListener("click",()=>{ import(/* webpackChunkName: "lodash" */"lodash").then(({default:_})=>{ console.log(_.join(["a","b"],"-")); }); },false); import { join } from "lodash"; document.addEventListener("click",()=>{ console.log(_.join(["a","b"],"-")); },false);第一段代码表示:点击 document 后去异步加载 lodash 模块,当模块加载成功后输出一个字符串。
第二段代码表示:进入界面先加载 lodash 模块,当点击页面后输出字符串。
显然第一段代码是一个异步加载方式,如果用户没有去点击页面就不必要去加载相应的模块,节省资源。这就是异步加载,只需要 webpack 配置 babel 支持 ES6 语法即可。
Preload and Prefetch我们看一张这样的业务场景:
用户点击登录,弹出登录框。这个登录弹框模块其实没有必要在最开始就加载完成的,因为它是属于交互性质的内容,是必须在用户看到首页后才会进行的动作,也就意味着这个模块可以在首页加载完成之后再去加载。
如何去实现这一的效果呢?浏览器给我们提供了资源加载的方式:
<link href="http://www.likecs.com/loginModule.js" as="script"> <link href="http://www.likecs.com/loginModule.js" as="script">preload 会以并行方式开始加载;
prefetch 会在首页模块加载完成之后,再去加载。