当前位置: 首页 > 后端技术 > Node.js

从0搭建你自己的webpack开发环境(5)

时间:2023-04-03 16:14:46 Node.js

过往回顾:从0搭建你自己的webpack开发环境(1)从0搭建你自己的webpack开发环境(2)从0搭建你自己的webpack开发环境(3))从0开始搭建自己的webpack开发环境(四)前四篇,我们已经掌握了webpack的各种常用配置。在这篇文章中,我们就来看看如何在webpack中实现优化。我们先写最基本的webpack配置,然后在里面依次实现各种优化。constMiniCssExtractPlugin=require("mini-css-extract-plugin");constHtmlWebpackPlugin=require("html-webpack-plugin");constpath=require("path");module.exports=mode=>{返回{模式:模式,条目:“./src/main.js”,输出:{文件名:“bundle.js”,路径:path.resolve(__dirname,“dist”)},模块:{规则:[{测试:/\.(png|jpg|gif)$/,use:"file-loader"},{test:/\.js$/,use:"babel-loader"//.babelrc已配置支持react},{测试:/\.css$/,使用:[mode!=="development"?MiniCssExtractPlugin.loader:“style-loader”,“css-loader”]}]},插件:[newPurgecssPlugin({paths:glob.sync(`${path.join(__dirname,"src")}/**/*`,{nodir:true})//不匹配目录,只匹配文件}),mode!=="development"&&newMiniCssExtractPlugin({filename:"css/[name].css"}),newHtmlWebpackPlugin({template:"./src/template.html",filename:"index.html"})].filter(Boolean)};};.babelrc配置文件{"presets":["@babel/preset-env","@babel/preset-react"]}1.删除无用的css样式我们看一下写好的代码import'./style.css'从'react'导入React;从'react-dom'导入ReactDOM;ReactDOM.render(

hello
,document.getElementById('root'));body{背景:红色}.class1{背景:red}这里的.class1显然是没有用的,我们可以搜索src目录下的文件,删除无用的样式constglob=require('glob');constPurgecssPlugin=require('purgecss-webpack-plugin');//这里需要配合mini-css-extract-plugin插件模式!=="development"&&newPurgecssPlugin({paths:glob.sync(`${path.join(__dirname,"src")}/**/*`,{nodir:true})//不匹配目录,只匹配文件}),2.图片压缩插件优化打包图片npminstallimage-webpack-loader--save-dev在文件之前使用压缩图片-loader插件加载器:“image-webpack-loader”,选项:{mozjpeg:{progressive:true,quality:65},//optipng.enabled:false将禁用optipngoptipng:{enabled:false,},pngquant:{quality:[0.90,0.95],speed:4},gifsicle:{interlaced:false,},//webp选项会启用WEBPwebp:{quality:75}}可以看到图片大小是否有明显变化3.CDN加载文件我们希望通过CDN导入资源constAddAssetHtmlCdnPlugin=require('add-asset-html-cdn-webpack-plugin')newAddAssetHtmlCdnPlugin(true,{'jquery':'https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js'})但在代码中我也希望引入jquery得到一个提示import$from'jquery'console.log('$',$),但是打包externals的时候还是会打包jquery:{'jquery':'$'}在配置中标记jqueryfile为External,这样打包的时候jquery就不会打包了。4.Tree-shaking&&Scope-Hoisting4.1Tree-shaking,顾名思义,就是把没用的内容抖掉。我们看代码:main.jsimport{minus}from"./calc";console.log(minus(1,1));calc.jsimport{test}from'./test';exportconstsum=(a,b)=>{returna+b+'sum';};exportconstminus=(a,b)=>{returna-b+'minus';};test.jsexportconsttest=()=>{console.log('你好')}console.log(test());观察上面的代码,我们会发现我们主要使用的是minus方法,而test.js的代码其实是有副作用的!默认mode:production时,会自动tree-shaking,但打包后还是会打印'hello'。这时候我们就需要进行配置,避免产生副作用!在package.json中配置"sideEffects":false。如果这样设置,默认不会导入css文件,因为我们也是通过import'./style.css'导入css;重点来了,tree-shaking主要针对es6模块,我们可以使用require语法导入css,但是用起来有点不合适,所以我们配置无副作用的css文件"sideEffects":["**/*.css"]defaulttree-在开发环境中Shaking不会生效,可以配置logo提示。optimization:{usedExports:true}4.2ScopeHoistingscopeimprovementcanreducecodesizeandsavememoryleta=1;letb=2;letc=3;letd=a+b+c;exportdefaultd;//引入从'./d'导入d;控制台日志(d);最终打包结果会变成console.log(6)代码量明显减少减少多个函数后,内存占用也会减少5.DllPlugin&&每次构建DllReferencePlugin,都需要重新构建第三方模块,这会消耗大量的性能。我们可以先把第三方库打包成动态链接库,以后构建的时候只需要找到构建好的库,这样可以节省很多构建时间。importReactfrom'react';importReactDOMfrom'react-dom';ReactDOM.render(

hello

,document.getElementById('root'))5.1DllPlugin这里我们可以先将react,react-dom单独封装创建webpack.dll.jsconstpath=require('path');constDllPlugin=require('webpack/lib/DllPlugin');module.exports={entry:['react','react-dom'],mode:'production',output:{filename:'react.dll.js',path:path.resolve(__dirname,'dll'),library:'react'},plugins:[newDllPlugin({name:'react',path:path.resolve(__dirname,'dll/manifest.json')})]}执行"webpack--configwebpack.dll.js命令,可以看到dll目录下分别创建了两个文件的关系manifest.json和react.dll.js之间就是这个酱料,然后我们将使用manifest.json找到react.dll.js文件中的模块并加载它们。5.2DllReferencePlugin可以引用我们项目中刚刚打包的动态链接库constDllReferencePlugin=require('webpack/lib/DllReferencePlugin');constAddAssetHtmlWebpackPlugin=require('add-asset-html-webpack-plugin');//内容构建时会引用动态链接库的newDllReferencePlugin({manifest:path.resolve(__dirname,'dll/manifest.json')}),//需要手动导入react.dll.jsnewAddAssetHtmlWebpackPlugin({filepath:path.resolve(__dirname,'dll/react.dll.js')})使用DllPlugin可以大大提高构建速度6.动态加载实现点击后动态加载文件letbtn=document.createElement('button');btn。innerHTML='点击加载视频';btn.addEventListener('click',()=>{import('./video').then(res=>{console.log(res.default);});});文档。body.appendChild(btn);为动态导入的文件添加名称output:{chunkFilename:'[name].min.js'}import(/*webpackChunkName:"video"*/'./video').then(res=>{console.log(res.default);})这样打包后的最终文件是video.min.js7。包文件分析工具安装webpack-bundle-analyzer插件npminstall--save-devwebpack-bundle-安装分析器后使用插件const{BundleAnalyzerPlugin}=require('webpack-bundle-analyzer');mode!=="development"&&newBundleAnalyzerPlugin()默认会显示当前应用的分析图。,公共模块首先配置项目为多入口文件入口:{a:'./src/a.js',b:'./src/b.js'}让a和b两个模块同时引用jquery时候,别忘了这里为了去掉之前的externals配置,这里配置SplitChunks插件的默认配置,我们一一说明含义splitChunks:{chunks:'async',//拆分异步模块minSize:30000,//最小分割文件大小maxSize:0,minChunks:1,//引用数maxAsyncRequests:5,//最大异步请求数maxInitialRequests:3,//最大初始化数requestsautomaticNameDelimiter:'~',//提取的名称分隔符automaticNameMaxLength:30,//名称的最大长度name:true,cacheGroups:{//缓存组vendors:{//先提取第三方测试:/[\\/]node_modules[\\/]/,priority:-10},default:{minChunks:2,priority:-20,//PriorityreuseExistingChunk:true}}}我们将async改为initial我们正在动态导入lodash每个文件的library,改成asyncimport('lodash')为每个entry引入c.js,并转换配置文件splitChunks:{chunks:'all',name:true,cacheGroups:{vendors:{test:/[\\/]node_modules[\\/]/,priority:-10},default:{minSize:1,//不是第三方模块,引入两次就会拉掉。minChunks:2,priority:-20,}}}这样依次看chunks的参数是不是就一目了然了?9.热更新(非林更新新)模块热替换(HMR-HotModuleReplacement)是webpack提供的最有用的功能之一。它允许在运行时替换、添加、删除各种模块,而无需进行完全刷新和重新加载整个页面。保留在整页重新加载时丢失的应用程序状态;仅更新更改以节省开发时间;调整样式要快得多,几乎等同于直接在浏览器调试器中更改样式。启用热更新,默认样式可以支持热更新,如果不支持热更新,可以使用强制刷新。devServer:{hot:true}newwebpack.NamedModulesPlugin(),让js支持热更新importsumfrom'./sum';console.log(sum(1,2));if(module.hot){//if支持热更新module.hot.accept();//入口文件改变后重新执行当前入口文件}10.IgnorePlugin配置忽略import和requiresyntaxnewwebpack.IgnorePlugin(/^\.\/locale$/,/moment$/)11.耗时分析可以计算出每一步的运行速度;12.noParsemodule.noParse,对于像jq这样的依赖库,内部不会引用其他库,所以我们打包的时候不需要解析,可以提高打包率。没有解析:/jquery/13。resolresolve:{extensions:[".js",".jsx",".json",".css"],别名:{},modules:['node_modules']},14.Include/exclude在使用loader时,可以指定哪些文件不通过loader,或者指定哪些文件必须通过loader。{test:/\.js$/,use:"babel-loader",//include:path.resolve(__dirname,'src'),exclude:/node_modules/},15.happypack多线程打包,我们可以pack将不同的逻辑交给不同的线程处理。npminstall--save-devhappypack使用插件constHappyPack=require('happypack');rules:[{test:/\.js$/,use:'happypack/loader?id=jsx'},{test:/\.less$/,使用:'happypack/loader?id=styles'},]newHappyPack({id:'jsx',threads:4,loaders:['babel-loader']}),newHappyPack({id:'styles',threads:2,loaders:['style-loader','css-loader','less-loader']})16.至此,我们的五连载《从0搭建自己的webpack开发环境》告一段落,希望你能通过这些文章对webpack有一个全新的认识,对你的工作更有帮助。如果你有什么想了解的前端知识,欢迎关注留言!感谢您的支持!