这段时间在忙碌着面试,复习了一下关于 webpack 的知识。下面做一个简单的总结(以下大部分摘录于网络,如有侵权,请联删)
文章目录
1. webpack与grunt、gulp的不同
2、Loader和Plugin的不同
- Loader在 module.rules中配置,作为模块的解析规则。数组类型,并且每一项规则均为对象。用于描述解析的目标文件,使用的加载器等。
- Plugin 在 plugin 中单独配置。数组类型。每一项作为相应 plugin 的实例化对象。参数通过构造函数传入。
3、webpack的构建流程是什么?
- 初始化参数:解析 shell 脚本(输入 webpack 操作后,操作系统都会去调用
./node_modules/.bin/webpack
这个 shell 脚本)与 config 中的配置项,并追加参数,读取并合并参数 - 开始编译:用参数初始化 Compiler 对象,加载所有的配置插件,并执行对象的 run 方法开始执行编译。
- 确定入口:根据配置文件找出所有的入口文件。
- 编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理
- 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会
- 输出完成:根据配置确定输出的路径和文件名。把文件内容写入文件系统。
4、编写loader或plugin的思路?
5、webpack的热更新是如何做到的?说明其原理?
- webpack的热更新又称热替换(Hot Module Replacement),缩写为HMR。 这个机制可以做到不用刷新浏览器而将新变更的模块替换掉旧的模块。
- 在 webpack 的 watch 模式下,文件系统中某一个文件发生修改,webpack 监听到文件变化,根据配置文件对模块重新编译打包,并将打包后的代码通过简单的 JavaScript 对象保存在内存中。
- webpack-dev-server 和 webpack 之间的接口交互,而在这一步,主要是 dev-server 的中间件 webpack-dev-middleware 和 webpack 之间的交互,webpack-dev-middleware 调用 webpack 暴露的 API对代码变化进行监控,并且告诉 webpack,将代码打包到内存中。
- webpack-dev-server 对文件变化的一个监控,这一步不同于第一步,并不是监控代码变化重新打包。当我们在配置文件中配置了devServer.watchContentBase 为 true 的时候,Server 会监听这些配置文件夹中静态文件的变化,变化后会通知浏览器端对应用进行 live reload。注意,这儿是浏览器刷新,和 HMR 是两个概念。
- webpack-dev-server 代码的工作,该步骤主要是通过 sockjs(webpack-dev-server 的依赖)在浏览器端和服务端之间建立一个 websocket 长连接,将 webpack 编译打包的各个阶段的状态信息告知浏览器端,同时也包括第三步中 Server 监听静态文件变化的信息。浏览器端根据这些 socket 消息进行不同的操作。当然服务端传递的最主要信息还是新模块的 hash 值,后面的步骤根据这一 hash 值来进行模块热替换。
- webpack-dev-server/client 端并不能够请求更新的代码,也不会执行热更模块操作,而把这些工作又交回给了 webpack,webpack/hot/dev-server 的工作就是根据 webpack-dev-server/client 传给它的信息以及 dev-server 的配置决定是刷新浏览器呢还是进行模块热更新。
- HotModuleReplacement.runtime 是客户端 HMR 的中枢,它接收到上一步传递给他的新模块的 hash 值,它通过 JsonpMainTemplate.runtime 向 server 端发送 Ajax 请求,服务端返回一个 json,该 json 包含了所有要更新的模块的 hash 值,获取到更新列表后,该模块再次通过 jsonp 请求,获取到最新的模块代码。
- HotModulePlugin 将会对新旧模块进行对比,决定是否更新模块,在决定更新模块后,检查模块之间的依赖关系,更新模块的同时更新模块间的依赖引用。
- 当 HMR 失败后,回退到 live reload 操作,也就是进行浏览器刷新来获取最新打包代码。
6、loader 与 plugin
- loader:加载器,为项目添加相应的匹配规则,用于解析非 JavaScript 文件。(webpack 默认只能解析 js 文件)。
- plugin:webpack 插件,对单一或批量文件做规则化处理(loader无法做到),或者可以扩展项目的功能,使 webpack 更加灵活。
7、webpack-dev-server和http服务器有什么区别?
- webpack-dev-server使用内存来存储webpack开发环境下的打包文件,并且可以使用模块热更新,他比传统的http服务对开发更加简单高效。
8、多线程优化
- 由于运行在 Node.js 之上的 Webpack 是单线程模型的,可以使用 HappyPack 将任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程。
- thread-loader 可以给多个loader 加多线程打包
9、性能优化(提高打包的速度)
- 压缩 js ,使用不同的插件(原:UglifyJs,新:ParallelUglify)
- 使用 CDN 加速。
- 去除不会触发的死代码。
- 提取公共代码。
- 使用多线程编译。(thread-loader , happypack)
10、webpack3.x 与 4.x区别
-
mode 配置选项
-
Loader 使用规则
3.x 支持 loaders 与 rules 写法,4.x 废弃了 loaders 写法,只支持 rules 。
vue-loader 15 必须使用VueLoaderPlugin插件
-
babel 命名规则
-
CommonsChunkPlugin:代码拆分插件
webpack 3.x 的代码拆分插件 webpack.optimize.CommonsChunkPlugin 已经从webpack 4.x 中移除,可使用 optimization.splitChunks 进行代码拆分(提取公共代码)
optimization: { splitChunks: { vendors: {} } }
-
mini-css-extract-plugin:css 代码分离插件
-
UglifyJsPlugin:js 代码压缩插件
现在只需要使用 optimization.minimize 为 true 就行,production mode 下面自动为 true,optimization.minimizer 可以进行个性化配置
optimization: { minimize: true, },
optimization: { // 定制个性化配置,覆盖默认压缩工具 minimizer: [], },
-
happyPack:多进程 loader 打包
参考文章:
3、优化打包速度