关于webpack的优化,通常我们是划分为开发体验和输出代码质量两方面来考虑的
( 一 )优化开发体验通常是从优化构建速度和使用体验
【开发环境】缩小文件的搜索范围 (loader配置include\exclude、module.noParse忽略对部分没有采用的模块化的文件递归解析,resolve modules直接指定第三方模块的路径)自动刷新 (设置watch:true,但是会制动刷新浏览器)热更新 (网页不刷新,状态不会丢失module.hot)DllPlugin (对于依赖的第三方库打包成动态链接库)【生产环境】优化bable-loader (开启缓存)IgnorePluginnoParsehappyPack (多线程打包)ParallelUglifyPlugin (多线程打包prepack (编译代码是提前将计算结果放到编译后的代码中,再直接运行结果输出)简析相关原理自动刷新让webpack 开启文件监听模式,只需要把wacth:true,wacthOptions可以设置不监听的文件
文件监听原理文件监听原理,是定时获取这个文件最后编辑的时间,每次都存下最新的最后编辑时间,如果发现当前获取和最后一次保存的编辑时间不一致,认为文件发生了变化多个文件的监听,webpack会从入口文件出发,递归所有依赖文件,将这些依赖文件都加入到监听列表中保存文件和最后的编辑时间占内存,减少监听文件数量和降低检测频率自动刷新的原理借助浏览器拓展去通过浏览器提供的接口刷新向开发的网页注入代理客户端代码,通过代理客户端去刷新正个页面热更新优势实时预览不刷新浏览器,可以保留当前网页的运行状态原理在项目中注入一个代理客户端来连接DevServer和项目DevServer在每次修改文件后,会生成一个用于替换老模板的补丁文件hot-update.js结尾,同时浏览器开发者工具也可以看到请求这个补丁包但在编辑main.js的时候会发现整个网页刷新了,原因是在子模块发生更新的时候,更新事件会一层层向上传递,到最外层没有文件接收它,则会刷新网页css文件没有地方接收,但是修改所有的css文件都会触发热更新,原因是在于style-loader会注入接收css的代码DllPlugin对于依赖的第三方库,比如vue,vuex等这些不会修改的依赖,我们可以让它和我们自己编写的代码分开打包,这样做的好处是每次更改我本地代码的文件的时候,webpack只需要打包我项目本身的文件代码,而不会再去编译第三方库,那么第三方库在第一次打包的时候只打包一次,以后只要我们不升级第三方包的时候,那么webpack就不会对这些库去打包,这样的可以快速的提高打包的速度
将项目依赖的基础模块抽离出来,打包到一个个单独的动态链接库中当需要导入的模块存在于某个动态链接库中,这个模块不能再被打包,直接再动态链接库中获取项目依赖的所有动态链接库都需要被加载bable-loader作用是识别es6+ 的语法通过js词法解析器进行解析,得到AST,然后进行遍历通过EStree规范生成新的AST,然后通过生成器转换es5代码部分新增的原型方法(peoxy,set)babel是不会转译的需要引入 polyfil解决cacheDirectory,开启缓存,避免之后的每次执行,可能产生的、高性能消耗的Bable重新编译过程happyPack(多进程构建,减少总构建时间)在webpack和loader之间多加了一层,webpack到了需要编译某个类型的资源模块之后,将该资源任务处理交给了HappyPack,由它在内部线程池中进行任务调度,分配一个线程调用处理改类型资源的Loader来处理这个资源
如果js和css文件的化,直接再module,rules,use['happyPack/loader?id=css']也可以在 plugins里配置,new HappyPack({id:css}),id标识文件类型默认进程是3个,threads可以设置webpack-parallel-uglify-plugin并行处理多个子任务,多个子任务完成后,再将结果发到主进程中,会开启多个子进程,对多个js文件压缩工作分舵多个子进程去完成,可以删除所有的注释,console.log,提取出现多次,但是没有定义成变量的应用静态值
uglifyJS原理,将代码解析成AST语法树,再用各种规则去处理它在pulfgins里new一个 parallel-uglify,uglifyJS配置输出紧凑,和删除所有注释,compress删除console.log一次用到的变量等Tree-shaking本质上是消除项目中不必要的代码,摇掉没有使用的模块称为DCE,达到删除无用的代码目的,依赖ES6的模块特性
DCEdead code eliminatiom代码不会被执行,不可到达代码执行的结果不会用到代码只会影响变量(只写不读)ES6模块的特点只能作为模块顶层的预计出现import的模块名只能是字符串常量对模块的引入是静态分析的,所以可以在编译的时候判断到底加载了什么代码,分析程序流,判断那些变量为被使用和引用,进而删除代码缺点只对ES6+的模块化语法生效,要在babelrc里关闭babel的模块转换功能js文件里,import 一个资源,然后函数没有被使用,import不会去掉提取公共代码原因:相同的资源重复加载,浪费用户的流量和服务器成本,资源态度导致首加载屏缓慢好处:减少网络传输量,降低服务器成本 怎么提取所有的页面需要用到的基础库,提取到一个独立的base.js文件(长缓存,静态文件名会附加文件内容计算处理的Hash值,通常不)再找到所有页面依赖的公共部分的代码,提取到common.js中为每个网页都生成独立的文件,不包含以上部分,各个页面单独需要的部分代码webpack内置了commonschunkPlugin懒加载(按需加载)将整个网站划分为一个个小功能每个类合并为一个chunk,按需加载对应的chunk不需要加载的用户首次打开网站是需要看到的画面对应的功能,将其放在执行入口所在的chunk中,减少用户感知的网页加载时间let TaskBtn = () => import(/ webpackChunkName: 'task-btn' / '@/components/TaskBtn.vue');开启 Scope Hoisting让webpack打包出来的代码文件更小,运行更快
代码体积更小,函数声明语句会产生大量的代码代码在运行时创建的函数作用域变少,内存开销也变小原理:分析模块之间的依赖关系,尽可能将打散的模块合并到一个函数中,但前提是不能造成冗余的代码,只有引用了一次的模块才能被合并CDN加速内容分发,加速网络传输,加快资源获取的速度静态资源的文件名需要带上由文件内容算出来的Hash值,以防被缓存不同类型的资源放到不同的域名cdn服务上,以防资源并行加载被阻塞