webpack 优化方向
对于 webpack 的优化,通常咱们是划分为开发体验和输入代码品质两方面来思考的
(一)优化开发体验
通常是从优化构建速度和应用体验
【开发环境】
- 放大文件的搜寻范畴 (loader 配置 includeexclude、module.noParse 疏忽对局部没有采纳的模块话的文件递归解析,resolve modules 间接指定第三方模块的门路)
- 主动刷新 (设置 watch:true, 然而会制动刷新浏览器)
- 热更新 (网页不刷新,状态不会失落 module.hot)
- DllPlugin(对于依赖的第三方库打包成动态链接库)
【生产环境】
- 优化 bable-loader(开启缓存)
- IgnorePlugin
- noParse
- happyPack(多线程打包)
- ParallelUglifyPlugin(多线程打包)
(2)优化输入品质
【缩小用户能感知到的加载 工夫,也就是首屏加载工夫】
- 辨别环境
- 压缩代码 (js css 图片)
- tree-shaking (除去没有用到的代码)
- 提取公共代码 (多线程打包)
- 宰割代码按需加载 (多线程打包)
- CDN 减速
【晋升晦涩度,也就是晋升代码性能】
- Scope Hosting(让文件打包更小,运行更快)
- 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 的模块个性
DCE
- dead 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 服务上,以防资源并行加载被阻塞