webpack入门基础知识 webpack优化配置

webpack优化方向
关于webpack的优化 , 通常我们是划分为开发体验和输出代码质量两方面来考虑的( 一 )优化开发体验
通常是从优化构建速度和使用体验【开发环境】
缩小文件的搜索范围 (loader配置include\exclude、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会从入口文件出发 , 递归所有依赖文件 , 将这些依赖文件都加入到监听列表中
保存文件和最后的编辑时间占内存 , 减少监听文件数量和降低检测频率
自动刷新的原理
借助浏览器拓展去通过浏览器提供的接口刷新
向开发的网页注入代理客户端代码 , 通过代理客户端去刷新正个页面
【webpack入门基础知识 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服务上 , 以防资源并行加载被阻塞


    推荐阅读