这是我参与更文挑战的第18天,活动详情查看: 更文挑战
1, webpack 核心配置
entry: 一个可执行模块或库的入口文件。
chunk :多个文件组成的一个代码块,例如把一个可执行模块和它所有依赖的模块组合和一个 chunk 这体现了
webpack的打包机制。
loader :文件转换器,例如把es6转换为es5,scss转换为css。
plugin :插件,用于扩展webpack的功能,在webpack构建生命周期的节点上加入扩展hook为webpack加入功能。
2, 有哪些常见的Plugin?他们是解决什么问题的?
1, define-plugin:定义环境变量
2, commons-chunk-plugin:提取公共代码
3, uglifyjs-webpack-plugin:通过UglifyES压缩ES6代码
3, 为什么需要loader? 有哪些常见的Loader?他们是解决什么问题的?
webpack开箱即用只支持JS和JSON两种文件类型,但是比如css、less,还有目前市场上比较新的语法糖jsx,怎么处理呢?
通过Loaders去支持其他文件类型并且把它们转化为有效的模块,并且可以添加到依赖图中
1, file-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件
2,url-loader:和 file-loader 类似,但是能在文件很小的情况下以 base64 的方式把文件内容注入 到代码中去
3, source-map-loader:加载额外的 Source Map 文件,以方便断点调试
4, image-loader:加载并且压缩图片文件
5, babel-loader:把 ES6 转换成 ES5
6, css-loader:支持.css文件的加载和解析,转换成commonjs对象
7, style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS。
8, eslint-loader:通过 ESLint 检查 JavaScript 代码
9,thread-loader : 多进程打包js和css
4, webpack的构建流程是什么?从读取配置到输出文件这个过程尽量说全
Webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程
1,初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数
2,开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行
编译;
3,确定入口:根据配置中的 entry 找出所有的入口文件;
4,编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步
骤直到所有入口依赖的文件都经过了本步骤的处理;
5,完成模块编译:在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之
间的依赖关系;
6,输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一
个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会;
7,输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统
在以上过程中,Webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,
并且插件可以调用 Webpack 提供的 API 改变 Webpack 的运行结果。
5, webpack的热更新是如何做到的?说明其原理?
webpack的热更新又称热替换(Hot Module Replacement),缩写为HMR。 这个机制可以做到不用刷新浏览器而
将新变更的模块替换掉旧的模块
原理:
1,第一步,在 webpack 的 watch 模式下,文件系统中某一个文件发生修改,webpack 监听到文件变化,根据
配置文件对模块重新编译打包,并将打包后的代码通过简单的 JavaScript 对象保存在内存中
2,第二步是 webpack-dev-server 和 webpack 之间的接口交互,而在这一步,主要是 dev-server 的中间
件 webpack-dev-middleware 和 webpack 之间的交互,webpack-dev-middleware 调用 webpack 暴露
的 API对代码变化进行监控,并且告诉 webpack,将代码打包到内存中。
3,第三步是 webpack-dev-server 对文件变化的一个监控,这一步不同于第一步,并不是监控代码变化重新打
包。当我们在配置文件中配置了devServer.watchContentBase 为 true 的时候,Server 会监听这些配置文
件夹中静态文件的变化,变化后会通知浏览器端对应用进行 live reload。注意,这儿是浏览器刷新,和 HMR 是两个概念。
4,第四步也是 webpack-dev-server 代码的工作,该步骤主要是通过 sockjs(webpack-dev-server 的依
赖)在浏览器端和服务端之间建立一个 websocket 长连接,将 webpack 编译打包的各个阶段的状态信息告知浏
览器端,同时也包括第三步中 Server 监听静态文件变化的信息。浏览器端根据这些 socket 消息进行不同的操
作。当然服务端传递的最主要信息还是新模块的 hash 值,后面的步骤根据这一 hash 值来进行模块热替换。
5,webpack-dev-server/client 端并不能够请求更新的代码,也不会执行热更模块操作,而把这些工作又交回
给了 webpack,webpack/hot/dev-server 的工作就是根据 webpack-dev-server/client 传给它的信息
以及 dev-server 的配置决定是刷新浏览器呢还是进行模块热更新。当然如果仅仅是刷新浏览器,也就没有后面那
些步
6,HotModuleReplacement.runtime 是客户端 HMR 的中枢,它接收到上一步传递给他的新模块的 hash 值,
它通过 JsonpMainTemplate.runtime 向 server 端发送 Ajax 请求,服务端返回一个 json,该 json 包
含了所有要更新的模块的 hash 值,获取到更新列表后,该模块再次通过 jsonp 请求,获取到最新的模块代码
7,而第 10 步是决定 HMR 成功与否的关键步骤,在该步骤中,HotModulePlugin 将会对新旧模块进行对比,决
定是否更新模块,在决定更新模块后,检查模块之间的依赖关系,更新模块的同时更新模块间的依赖引用
8,最后一步,当 HMR 失败后,回退到 live reload 操作,也就是进行浏览器刷新来获取最新打包代码。
9, 如何利用webpack来优化前端性能?(提高性能和体验)
用webpack优化前端性能是指优化webpack的输出结果,让打包的最终结果在浏览器运行快速高效
6, 如何利用webpack来优化前端性能?(提高性能和体验)
1 ,压缩代码。删除多余的代码、注释、简化代码的写法等等方式。可以利用webpack的UglifyJsPlugin和
ParallelUglifyPlugin来压缩JS文件, 利用cssnano(css-loader?minimize)来压缩css
2,利用CDN加速。在构建过程中,将引用的静态资源路径修改为CDN上对应的路径。可以利用webpack对于output
参数和各loader的publicPath参数来修改资源路径
3,删除死代码(Tree Shaking)。将代码中永远不会走到的片段删除掉。可以通过在启动webpack时追加参数--
optimize-minimize来实现
4,提取公共代码。
7, 如何提高webpack的构建速度
1, 多入口情况下,使用CommonsChunkPlugin来提取公共代码
2, 通过externals配置来提取常用库
3, 利用DllPlugin和DllReferencePlugin预编译资源模块 通过DllPlugin来对那些我们引用但是绝对不会修
改的npm包来进行预编译,再通过DllReferencePlugin将预编译的模块加载进来
4, 使用Happypack 实现多线程加速编译
5, 使用webpack-uglify-parallel来提升uglifyPlugin的压缩速度。 原理上webpack-uglify-parallel
采用了多核并行压缩来提升压缩速度
6, 使用Tree-shaking和Scope Hoisting来剔除多余代码
8, 总结
webpack其实比较简单,用一句话概括本质:
webpack是一个打包模块化js的工具,可以通过loader转换文件,通过plugin扩展功能。