webpack构建速度优化基本优化完毕,接下来要考虑的是:在线代码质量优化,即如何使用webpack构建高质量代码webpack构建过程:初始化配置参数->绑定事件钩子回调->确定Entry逐一遍历->使用loader编译文件->输出文件概述本次优化构建代码质量的基本技术:reactRouter按需加载;公共代码提取和代码压缩;CDN连接输入;启用gzip压缩;接入treeShaking,剔除无用代码并启用ScopeHoisting(生产环境代码构建)实时查看每次配置后的代码构建状态,使用webpack监控文件避免每次手动构建,启用webpack-jarvis,实时要查看构建分析,npmi-Dwebpack-jarvis。启用监控模式watch:true,watchOptions:{ignored:/node_modules/,//忽略监控文件aggregateTimeout:300,//文件变化后多久发起构建poll:1000,//每秒查询次数,越小越好}一、react-router4实现了单页应用的按需加载。按需加载的一般原则:1、把网站分成小的功能,根据每个功能的相关性,分成几类;2.将每个category合并成一个chunk,按需加载对应的代码;3、需要在屏幕上看到的相应功能块不能在用户进入网站时按需加载;在已经操作或即将操作相应功能时加载相应的代码(默认使用react-router按需加载的触发条件是路由的变化)实现条件:1.使用插件:npm我可以反应加载;2、配合bable插件npmi@babel/plugin-syntax-dynamic-import;代码示例://.bablerc{"plugins":["@babel/plugin-syntax-dynamic-import"]}//示例代码Loadable({loader:()=>import('./component'),//按需加载组件loading:Loading,//组件加载的过程加载、错误等delay:300//延迟加载,避免加载的闪烁问题});//加载组件自定义//接受三个props,其中pastDelay:等待时触发;timedOut:超时超过延迟时触发;错误:错误触发器默认为200msconstLoading=({pastDelay,timedOut,error})=>{if(pastDelay){return}elseif(timedOut){return<自旋旋转tip="Takingalongtime...">}elseif(error){returnError!
;}returnnull;};2.提取公共代码webpack.optimizationoptimization:{splitChunks:{chunks:"all",cacheGroups:{vendors:{test:/node_modules/,name:'vendors',minSize:0,minChunks:1,chunks:'initial',priority:2//这个配置项是设置处理的优先级,值越大优先级越高},commons:{name:"comomns",test:resolve("src/components"),//可自定义扩展规则minChunks:2,//最小分享次数minSize:0,//最小的代码有多大,提取priority:1,//这个配置项是设置处理的优先级,值越大,高优先级}}}3.压缩文件js\css使用npmi-Dwebpack-parallel-uglify-plugin开启多线程并行压缩JSoptimization:{minimizer:[newParallelUglifyPlugin({cacheDir:'.cache/',//缓存压缩,默认不缓存,设置存储位置开启test:/.js$/,//匹配需要压缩的文件,默认为/.js$/同Loader配置//include:[],使用正则模式选择需要压缩的文件,同Loader配置//exclude:[],使用regex去除不需要压缩的文件,同Loader配置//workerCount:2,开启多个子进程并发压缩//sourceMap:false,是否输出sourceMap,开启会导致压缩变慢//uglifyJS:{},用于压缩ES6代码不能与uglifyJS同时使用uglifyJS:{//CompressES5codeoutput:{//是否输出更具可读性的代码,会保留保留空格和制表符,默认是输出,为了达到更好的压缩效果,可以设置为falsebeautify:false,//是否保留代码中的注释,默认保留,以达到更好的压缩效果压缩效果,可以设置为falsecomments:false},compress:{//UglifyJS删除无用代码时是否输出警告信息,默认输出warnings:false,//是否删除代码中所有控制台语句,默认不删除,开启后,会删除所有控制台语句drop_console:true,//是否嵌入定义过但只使用一次的变量,比如将varx=1;y=x转换为y=1,defaultisnocollapse_vars:true,//提取多次出现但未定义为变量的静态值引用reduce_vars:true}},}),]},提取并压缩css1.使用插件:optimize-css-assets-webpack-plugin,mini-css-extract-plugin2.使用示例://ExtractcsstoaseparatefileconstMiniCssExtractPlugin=require("mini-css-extract-plugin");//optimizeCssPluginCSS文件压缩插件constoptimizeCssPlugin=require('optimize-css-assets-webpack-plugin');constextractSCSS=newMiniCssExtractPlugin({filename:'css/[name].[contenthash:8].css',chunkFilename:'css/[name]_[contenthash:8].css',fallback:'style-loader'});......插件:[newoptimizeCssPlugin({assetNameRegExp:/\.css$/g,cssProcessor:require('cssnano'),cssProcessorOptions:{discardComments:{removeAll:true}},canPrint:true}),]webpack配置访问CDNCDN网站访问CDN时,需要将网页的静态资源上传到CDN服务器,使用CDN地址访问;使用CDN可以解决资源并行下载的限制,解决携带同域名静态资源cookie的问题;CDN缓存和回源需要合理设置静态资源的hash。访问CDN会引入多个域名,增加域名解析时间,预解析域名。webpack实现访问输出.publicPath设置JavaScript地址css-loader.publicPath设置CSS导入资源地址WebPlugin.stylePublicPath设置Css文件地址//JavaScriptoutput:{publicPath:'//js.cdn.com/js/',path:path.join(__dirname,'../docs/dist'),//打包文件存放的地方//使用`chunkhash`作为输出的JavaScript文件名加上Hash值(chunkhash:根据模块内容变化;hash:根据每个Build随机变化)filename:"js/[name].[chunkhash:8].js",chunkFilename:"js/[name]-[id].[chunkhash:8].js",},启用gzip压缩插件:npmi-Dcompression-webpack-plugin;webpack配置constCompressionPlugin=require("compression-webpack-plugin");plugins:[newCompressionPlugin({filename:'[path].gz[query]',//targetresource名称[file]会被替换成原来的资源.[path]会替换成原来的资源路径,[query]会替换成原来的查询字符串algorithm:'gzip',//algorithmtest:/\.(js|css)$/,//compressjsandcssthreshold:10240,//只处理大于这个值的资源。以字节为单位计算minRatio:0.8//只有压缩比小于这个值的资源才会被处理})]后台开启使用koaconststaticCache=require('koa-static-cache');importconfigfrom'./configs';constapp=newKoa();app.use(staticCache(path.resolve(__dirname,"../dist"),{maxAge:7*24*60*60,gzip:true,//打开dynamic:true,}))输入treeShaking去除无用代码TreeShaking可用于在JavaScript中找到有用的代码并去除无用的死代码;但是依赖ES6静态花模块语法import\exportwebpack访问修改的导入导出。babelrc保留了ES6注意新版本的babel-preset-env已经预设了babel-preset-es2015。babel推荐使用babel-preset-env而不是babel-preset-es2015,继续使用babel-preset-es2015会发出警告信息。{"presets":[["env",{"modules":false}]],"plugins":["syntax-dynamic-import"]}webpack--display-used-exportsrunbuildwith--display-used-exports可以跟踪TreeShaking的工作;webpack只能正确解析如何去除死代码,需要接入UglifyJs处理去除(配置见上)并开启ScopeHoistion范围提升,即作用域提升;在构建过程中,Webpack会利用ES6模块化的静态特性来判断模块的依赖关系,将bundle中的静态依赖提升到最顶层。(所以需要像接入treeShaking一样配置Babel开启ES6模块化)原理:分析模块之间的依赖关系,尽可能将分散的模块合并为一个函数。前提不能造成代码冗余,所以只引用一个模块就可以合并。访问的好处:1.减少代码量2.减少代码的内存开销,因为在运行时创建的函数范围更少。');plugins:[newModuleConcatPlugin(),//开启scopeHoisting],