Webpack 是一个静态资源打包工具。 它会以一个或多个文件作为打包的入口,将我们整个项目所有文件编译组合成一个或多个文件输出出去。Webpack 本身功能比较少,只能处理 js 资源,一旦遇到 css 等其他资源就会报错。需要通过loader和plugin来扩展其功能,帮助我们打包各种类型的文件以及在打包过程中做一些其他的事情。
常用的loader
处理样式文件
- css-loader: 负责将 Css 文件编译成commonjs模块 (Webpack 能识别的模块)到js中。将css资源打包到js中。
- style-loader:会动态创建一个 Style 标签,里面放置 Webpack 中 Css 模块内容,将标签添加到html文件中生效。
- less-loader:负责将 Less 文件编译成 css 文件
- sass-loader:负责将 Sass 文件编译成 css 文件
- stylus-loader:负责将 Styl 文件编译成 css 文件
执行顺序:less-loader(sass-loader,stylus-loader),css-loader先执行,style-loader后执行。
- file-loader、url-loader:Webpack4 时,图片资源通过这两个loader进行处理。Webpack5 已经将两个 loader 功能内置到 Webpack 里。
file-loader:把⽂件输出到⼀个⽂件夹中,在代码中通过相对 URL去引⽤输出的⽂件。url-loader:和 file-loader 类似,但是能在⽂件很⼩的情况下以base64 的⽅式把⽂件内容注⼊到代码中去。 - babel-loader:把 ES6 转换成 ES5。
- postcss-loader:解决样式兼容性问题。
常用的plugin
- eslint-webpack-plugin:检查是否符合eslint规范。
- html-webpack-plugin:创建html文件并自动引入打包生成的js等资源。
- mini-css-extract-plugin:会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,在html中通过link标签加载。并且支持 CSS 和 SourceMaps 的按需加载。(
production) - css-minimizer-webpack-plugin: css压缩。(
production)
webpack优化
1. 提升开发体验
SourceMap
SourceMap(源代码映射)是一个用来生成源代码与构建后代码一一映射的文件的方案。
它会生成一个 xxx.map 文件,里面包含源代码和构建后代码每一行、每一列的映射关系。当构建后代码出错了,会通过 xxx.map 文件,从构建后代码出错位置找到映射后源代码出错位置,从而让浏览器提示源代码文件出错位置,帮助我们更快的找到错误根源。
- cheap-module-source-map: 打包编译速度快,只包含行映射 (development)
- source-map:包含行/列映射 (production)
2. 提升打包构建速度
HMR
HotModuleReplacement(HMR/热模块替换):在程序运行中,替换、添加或删除模块,而无需重新加载整个页面。可以做到修改某个模块代码,就只有这个模块代码需要重新打包编译,其他模块不变,这样打包速度就能很快。(在webpack5 dev-server中默认配置开启)
- style-loader
- vue-loader
- react-hot-loader
OneOf
打包时每个文件都会经过所有 loader 处理,配置OneOf可以让文件 匹配上一个 loader后, 剩下的就不匹配了。
Include/Exclude
第三方的库或插件,不需要编译可以直接使用。可以配置loader和plugin的exclude和include来排除一些文件。
Cache
配置loader和plugin对 Eslint 检查 和 Babel 编译结果进行缓存。这样第二次打包时速度就会更快了。
Thread
提升打包速度,其实就是要提升 js 的打包速度,因为其他文件都比较少。 而对 js 文件处理主要就是 eslint 、babel、Terser(压缩jsvascript) 三个工具,所以我们要提升它们的运行速度。 多进程打包:开启电脑的多个进程同时干一件事,速度更快。
需要注意:请仅在特别耗时的操作中使用,因为每个进程启动就有大约为 600ms 左右开销。
- thread-loader
- terser-webpack-plugin(webpack5 自带)
3. 减少代码体积
Tree Shaking
Tree Shaking 是一个术语,通常用于描述移除 JavaScript 中的没有使用上的代码。
例如引用第三方工具函数库或组件库,不会打包整个库,只会打包我们引用的函数。
注意:它依赖 ES Module。
Webpack 已经默认开启了这个功能,无需其他配置。
Babel
Babel 为编译的每个文件都插入了辅助代码,使代码体积过大!
对一些公共方法使用了非常小的辅助代码,比如 _extend。
你可以将这些辅助代码作为一个独立模块,来避免重复引入。
Image Minimizer
本地项目静态图片压缩
- image-minimizer-webpack-plugin
4. 优化代码运行性能
Code Split
代码分割(Code Split)主要做了两件事:
- 分割文件:将打包生成的文件进行分割,生成多个 js 文件。
- 按需加载:需要哪个文件就加载哪个文件。
为什么需要Code Split:
打包代码时会将所有 js 文件打包到一个文件中,体积太大了。我们如果只要渲染首页,就应该只加载首页的 js 文件,其他文件不应该加载。
所以我们需要将打包生成的文件进行代码分割,生成多个 js 文件,渲染哪个页面就只加载某个 js 文件,这样加载的资源就少,速度就更快。
Preload Prefetch
使用 import 动态导入语法来进行代码按需加载(我们也叫懒加载,比如路由懒加载就是这样实现的)。 但是加载速度还不够好,比如:是用户点击按钮时才加载这个资源的,如果资源体积很大,那么用户会感觉到明显卡顿效果。
在浏览器空闲时间,加载后续需要使用的资源。我们就需要用上 Preload 或 Prefetch 技术。
Preload:告诉浏览器立即加载资源。Prefetch:告诉浏览器在空闲时才开始加载资源。
Network Cache
浏览器可以对同名的文件进行缓存。打包时应尽量对只有内容变化的文件更改文件名。保证项目正确更新,且合理利用缓存。
- fullhash
- chunkhash
- contenthast
配置optimization.runtimeChunk,额外生成runtime文件,文件只保存文件的 hash 值和它们与文件关系,使引用变化文件的文件名称不改变。
Core js
core-js 是专门用来做 ES6 以及以上 API 的 polyfill。解决js 兼容性问题。例如async 函数、promise 对象、数组的一些方法(includes)等(低版本浏览器会直接报错)。
自动按需加载,使用到的core-js的包。
// babel.config.js
module.exports = {
// 智能预设:能够编译ES6语法
presets: [
[
"@babel/preset-env",
// 按需加载core-js的polyfill
{ useBuiltIns: "usage", corejs: { version: "3", proposals: true } },
],
],
};
webpack-dev-server
提供了一个基本的 web server,并具有实时重新加载的功能。
budle, chunk, module是什么
bundle:是由 webpack 打包出来的⽂件;
chunk:代码块,⼀个 chunk 由多个模块组合⽽成,⽤于代码的合并和分割;
module:是开发中的单个模块,在 webpack 的世界,⼀切皆模块,⼀个模块对应⼀个⽂件, webpack 会从配置的 entry 中递归开始找出所有依赖的模块。
以上内容均是 由尚硅谷 Web 前端之Webpack5教程总结,列了大纲,方便梳理。 教程地址:yk2012.github.io/sgg_webpack…