1.背景目前网站项目采用多页面,开发和重构分离。在开发新页面时,由于重构开发,可能会经常添加样式文件或调整样式顺序,因此团队采用了如下开发模型。随着页面越来越多,依赖样式文件越来越多,gulp任务越来越多,打包编译速度慢的问题也逐渐暴露出来。该模式打包时间截图如下:可以看到gulp任务耗时30s左右,webpack任务耗时30s。加起来,第一次构建耗时1分多钟,第二次构建耗时8秒左右。想象一下,每次构建它时,这个场景都会在您的脑海中弹出。熊?可见已经到了(ren)必须(wu)必须(ke)改(ren)的地步了好吗?所以我决定修改当前的构建方式,分为以下几步进行1.去掉gulp修改后的方式如下图所示,其中绿色为Newprocess,与原来的process相比,gulp打包css进程去掉,交给webpack处理切换到该模式后,第一次打包时间约20s,增量编译约8s2,webpack构建速度优化2.1excludeinclude优化指定需要处理的文件和exclude在匹配规则中,缩小搜索处理文件的范围,保证尽可能少的编译文件,并根据项目情况添加相应的include和exclude配置。具体配置如下:[{test:/\.[jt]s$/,include:[path.resolve(process.cwd(),'src')],exclude:[/node_modules/,path.resolve(process.cwd(),'src/vendor')],},{test:/\.css$/,include:RESOURCES.CSS.cwd,}]添加以上配置后,第一次打包时间约为16s,增量编译是关于8s2.2thread-Loader和esbuild-loader使用多进程封装优化thread-loader。放置在线程加载器后面的加载器将在单独的工作池中运行。esbuild是Go开发的用于打包压缩ts和js的工具。特点包装速度非常快。与webpack、rollup、Parcel相比,github官方介绍快了数倍十倍甚至上百倍,但是esbuild还是不能支持css,而且没有插件机制,所以暂时不能替代webpack,但是有一个webpack的loader,即esbuild-loader,引入试试效果,Vite和Snowpack底层都用到了esbuild,参考thread-loader官方说明和esbuild-loader官方说明,关键配置如下constcpuNum=require('os').cpus()。长度;consttsWorkerPool={workers:6,poolTimeout:Infinity};constcssWorkerPool={workers:cpuNum-tsWorkerPool.workers,poolTimeout:Infinity};threadLoader.warmup(tsWorkerPool,['esbuild-loader']);threadLoader.warmup(cssWorkerPool,['css-loader']);模块:{规则:[{test:/\.[jt]s$/,使用:[{loader:'thread-loader',options:tsWorkerPool},{loader:'esbuild-loader',options:{loader:'ts',target:'es2015',tsconfigRaw:require('../tsconfig.json')},},{loader:path.resolve(__dirname,'loaders/importcss-loader.js'),options:{include:path.resolve(process.cwd(),'src/app'),}},],包括:[path.resolve(process.cwd(),'src')],排除:[/node_modules/,path.resolve(process.cwd(),'src/vendor')],},{test:/\.css$/,使用:[{loader:MiniCssExtractPlugin.loader,},{loader:'thread-loader',options:cssWorkerPool},{loader:'css-loader',options:{esModule:false,}},{loader:'esbuild-loader',options:{loader:'css',minify:true}}],include:RESOURCES.CSS.cwd,}],},经过测试,加入thread-loader后,第一次打包时间12s左右,增量编译3s左右,加上esbuild-loader后,第一次打包时间缩短到8s左右,增量编译2s左右。注意:https://esbuild.github.io/api/#target文档中提到,对于大部分语法,esbuild-loader只支持转es6,因此只适合在开发环境中使用。生产环境不建议使用2.3图片压缩,去除多余的css样式文件。图片压缩配置如下loader:'image-webpack-loader',options:{//生产环境启用压缩disable:process.env.NODE_ENV==='生产'?false:true,//压缩jpg/jpeg图像mozjpeg:{progressive:true,quality:80//压缩率},//压缩png图像pngquant:{quality:[0.65,0.90],speed:4}}去除冗余styles并使用purgecss插件,配置如下,需要配置newPurgecssPlugin({paths:glob.sync([path.resolve(__dirname,'../../server/views/**/*.html'),path.resolve(`${PATH.SRC}/**/*.vue`),]),safelist:[/data-v-.*/,//vue作用域样式保留/market-message/,//营销通知栏的背景颜色由配置决定,所以需要去掉style。/vip/的特殊处理,//动态渲染vip级别样式保留]})3.升级到webpack5webpack去年发布的webpack5带来了很多优化,主要有以下几点:1.默认启用持久缓存和cachedinmemory,而webpack4需要cache-loader和hard-source-webpack-plugin来做缓存2.NodeJS的polyfill脚本被移除,而在webpack4及之前的版本中,polyfill脚本会为大多数Node模块自动添加3.BetterTreeShaking经过以上优化,想进一步测试webpack5版本能带来的优化效果,将webpack包和相关依赖升级到最新版本,去掉不兼容的speed-measure后-webpack-plugin和hard-source-webpack-plugin不再需要的插件,处理了大约65个文件,第一次打包时间缩短为6.5s左右,增量编译时间为1.5s左右。可以看到时间进一步缩短了。4.webpack.dev.js热加载热更新添加如下配置devServer:{contentBase:path.join(PATH.DIST,'js'),inline:true,compress:true,port:5000,writeToDisk:true,host:'0.0.0.0',hot:true,disableHostCheck:true,headers:{'Access-Control-Allow-Origin':'https://www.midasbuy.com','Access-Control-Allow-Headers':'*','Access-Control-Allow-Methods':'*','Access-Control-Allow-Credentials':true,},},因为我们在开发的时候使用whistle代理来配合域名访问,当检测到文件更新时,通过websocket通知消息,所以需要在whistle中添加如下规则。第一个是建立websocket连接,第二个用于热更新时请求更新的内容。这里主要实现vue组件。js的热更新和js的热刷新,css的热更新暂时没有实现。https://www.midasbuy.com:5000http://127.0.0.1:5000/^https://www.midasbuy.com/oversea_web/static/***hot-update***http://127.0.0.1:5000/oversea_web/static/$1hot-update$2坑:测试热刷新的时候修改了文件页面刷新后出现如下错误,再次手动刷新。找了半天也没找到原因。曾经怀疑是whiteagent,后来怀疑是发送通知更新命令的时间过早,然后写了一个hack方法延迟发送更新命令,发现可以,但是具体原因不详直到我切换到服务器终端并更新文件后才发现。看了下面的打印,明白了我们的流程是客户端编译文件后,将文件复制到服务器文件夹中,提供给ejsinclude使用。服务端使用nodemon,当文件发生变化时,会复制文件并触发nodemon浏览器重启导致浏览器重载时请求失败,所以解决方法是在nodemon配置中忽略复制文件的目录文件,因为文案真正的内容是,之类的内容可以完全忽略。忽略后,改文件时服务器不会重启,问题解决。5.vuedevtools定位组件目录。对于vuedevtools,当你在浏览器中选择一个组件时,你可以直接打开编译器,点击它就可以打开该组件所在的源代码文件。作为参考,在webpack.dev.js=require('launch-editor-middleware')下添加如下配置constopenInEditor;devServer:{...before(app){app.use('/__open-in-editor',openInEditor('code',path.resolve(process.cwd(),'src')));},},添加一行规则whistlehttps://www.midasbuy.com/__open-in-editorhttp://127.0.0.1:5000/__open-in-editor如下图,当你点击圆圈location,会打开vscode编辑器,定位到组件对应的源文件代码。压缩前的尺寸结果如下。当处理大约65个文件时,可以看到编译时间大大缩短,js文件大小也变小了。但是由于部分图片经过base64编码后进入css,导致样式文件体积变大。方案第一次编译时间第二次编译时间buypage.jspropsOrder.jsbuypage.csspropsOrder.cssgulp+webpack460s8s178kb157kb17.58kb24.74kbwebpack56.5s1.5s123kb112kb28kb35kb