Webpack
前端代码为什么要构建和打包
- 体积更小(
Tree-Shaking、压缩、合并),加载更快 - 编译高级语言或语法(
TS、ES6+、模块化、SCSS) - 兼容性和错误检查(
polyfil、postcss、eslint) - 统一、高效的开发环境
- 统一的构建流程和产出标准
- 集成公司构建规范(提测、上线等)
webpack 构建流程
webpack 可以看做一条生产线, 通过 tapable 来组织打包流程,期间会广播事件,插件可以监听事件钩子,来改变打包的结果。大致步骤如下:
- 初始化阶段:从配置文件和
shell语句中读取与合并参数 - 编译构建流程:从
entry出发,分析模块间的依赖关系,针对每个module串行调用相对应的loader去编译文件内容,再找到module所依赖的module,递归的进行编译处理 - 输出:对编译后的
module组合成chunk,把chunk转换成 文件,输出到 目标出口
webpack 优化前端性能手段
JS代码压缩CSS代码压缩Html文件代码压缩- 文件大小压缩
- 图片压缩
Tree Shaking- 代码分离
- 内联
chunk
module、chunk、bundle 分别指什么,区别是什么
module即各个源文件,webpack中一切皆模块chunk多模块合成的,在webpack中流转的也称为chunk,如entry、import、splitChunk处理的文件可以称为chunkbundle最终输出的文件
loader 和 plugin 的区别
loader模块转换器- 在
webpack解析模块时,会根据模块类型,调用不同的loader对模块进行处理
- 在
plugin扩展插件- 插件订阅了
webpack打包过程中的各种钩子,在钩子触发时执行相应的插件函数,即发布订阅模式
- 插件订阅了
webpack 如何实现懒加载
import(),返回一个promisevue、react中也是基于import来做懒加载vue-router异步加载路由- 早期
webpack通过动态生成script标签来实现懒加载
webpack热模块更新总结
- 通过
webpack-dev-server创建两个服务器:提供静态资源的服务(express)和Socket服务 express server负责直接提供静态资源的服务(打包后的资源直接被浏览器请求和解析)socket server是一个websocket的长连接,双方可以通信- 当
socket server监听到对应的模块发生变化时,会生成两个文件.json(manifest文件)和.js文件(update chunk) - 通过长连接,
socket server可以直接将这两个文件主动发送给客户端(浏览器) - 浏览器拿到两个新的文件后,通过
HMR runtime机制,加载这两个文件,并且针对修改的模块进行更新
webpack proxy 工作原理
- 通过设置
webpack proxy实现代理请求后,相当于浏览器与服务端中添加一个代理者 - 当本地发送请求的时候,代理服务器响应该请求,并将请求转发到目标服务器,目标服务器响应数据后再将数据返回给代理服务器,最终再由代理服务器将数据响应给本地
- 在代理服务器传递数据给本地浏览器的过程中,两者同源,并不存在跨域行为,这时候浏览器就能正常接收数据
- 注意:服务器与服务器之间请求数据并不会存在跨域行为,跨域行为是浏览器安全策略限制
webpack 常见性能优化
babel-runtime 和 babel-polyfill 的区别
core-js和regenerator的集合 即babel-polyfill;Babel 7.4后推荐直接使用这两个库core-js是集成了es6的polyfillregenerator是支持generator语法的polyfill
babel-runtime不会污染全局环境变量
ES6 Module 和 Commonjs
ES6 Module静态引入,编译时引入Commonjs动态引入,执行时引入 只有ES6 Module才能静态分析,实现Tree-Shaking
webpack 多入口
- 配置
entry为对象;output 配置输出多个文件名;plugins需要生成多个html文件,并设置chunk配置加载哪个文件名。
webpack 抽离 css 文件
- 在
loader中通过MiniCssExtractPlugin.loader进行抽离css,在plugins中配置生成css文件名
webpack 抽离公共代码
splitChunks配置,抽离时需根据文件大小、引用次数设置
webpack 懒加载
- 通过
js的import来加载文件,返回一个promise
webpack 处理 vue
- 可以使用
babel处理,设置preset;或者vue-loader
webpack 性能优化
优化打包构建速度 - 开发体验和效率
- 优化
babel-loaderexclude排除不编译文件use中添加?cacheDirectory开启缓存
IgnorePlugin- 避免引入无用模块
noParse- 避免重复打包,例如引入
vue.min.js已经打包过的文件,跳过打包
- 避免重复打包,例如引入
- 自动刷新
- 开发环境下设置
devServer,watch会默认开启监听文件变化刷新浏览器,但页面刷新会导致数据状态丢失
- 开发环境下设置
- 热更新 - 开发环境
- 引入
HotModuleReplacementPlugin插件,devServe中设置hot: true
- 引入
DllPlugin- 动态链接库插件,常见的
vue、react较稳定,同一版本只需构建一次,不用每次都构建 webpack内置DllPlugin支持DllPlugin打包出dll文件DllReferencePlugin使用dll文件
- 动态链接库插件,常见的
优化产出代码 - 产品性能
目的
- 减小体积
- 合理分包,不重复加载
- 速度更快,内存更小
产出
- 小图片
base64编码,例如< 10kb bundle加hash- 懒加载
- 提取公共代码
IgnorePlugin- 使用
CDN加速,生产打包时配置externals,并在html中引入cdn地址 - 代码压缩
Scope HostingTree-shaking