什么是 webpack
是一个静态打包工具
核心思想是:静态分析模块之间的依赖关系,然后将这些模块按一定规则打包成一个或多个文件
解决了以下问题:
- 代码模块化和统一管理
- 自动处理各模块的依赖
- 热更新,提高开发效率
- 代码拆分、压缩等
构建流程
初始化配置 → 从 entry 开始分析模块依赖 → 通过 loader 进行各个文件的编译 → build 完成输出到 dist 目录
Loader
是什么:
Webpack 中的文件加载器,是一个函数。运行在打包文件之前。
作用:
Webpack 本身默认只能理解处理 .js
和 .json
文件,Loader 的作用是让 Webpack 能够处理其他类型的文件,通过链式调用对资源文件进行转换和处理
使用:
写在 module.rules 属性中,常见的有:
- css-loader:用于加载 css
- style-loader:用于将 css 添加到 DOM 中的
<style>
标签中 - sass-loader:处理 sass 文件
- file-loader:将文件打包到输出目录中
- url-loader:将文件转换为内联的 base64
Plugin
是什么:
Webpack 中的插件,是一个具有 apply 方法的函数。在整个编译周期都起作用。webpack 生命周期中的各个环节会提供钩子 (hook),可以在这些生命周期节点透过 Plugin 来做额外操作,进而拓展 webpack 的功能。
- 一个 JavaScript 命名函数
- 在插件函数的 prototype 上定义一个 apply 方法
- 指定一个绑定到 webpack 自身的事件钩子
- 处理 webpack 内部实例的特定数据
- 功能完成后调用 webpack 提供的回调
作用:
用于对 Webpack 的构建流程进行功能扩展
使用:
写在 plugins 属性中,常见的有:
- HtmlWebpackPlugin:打包结束后,⾃动生成⼀个 html 文件,并把打包生成的 js 模块引⼊到该 html 中
- CleanWebpackPlugin:构建前清理输出目录,避免旧文件残留
- TerserWebpackPlugin:压缩 JS 代码
Loader 和 Plugin 区别
特性 | Loader | Plugin |
---|---|---|
主要作用 | 转换文件内容(如转译、预处理) | 扩展构建流程(优化、资源管理、注入环境变量等) |
执行时机 | 在模块加载时(文件转换为模块时) | 在整个构建生命周期(从初始化到输出)的各个阶段 |
配置方式 | 通过 module.rules 数组配置 | 通过 plugins 数组配置(需要 new 实例化) |
典型场景 | 处理 JS/CSS/图片等文件转译 | 生成 HTML、压缩代码、提取 CSS 等全局操作 |
依赖关系 | 针对特定文件类型(如 .scss ) | 不依赖文件类型,可干预整个构建流程 |
tree-shaking
一种代码静态分析技术,用于消除 JavaScript 应用中的未使用代码(Dead Code)。通过移除这些未使用的代码,可以减少最终打包文件的体积,从而提高应用的加载速度和性能
原理
静态分析:依赖 ES6 Module 功能(不能是 CommonJS 因为是它动态的运行时加载)
开启步骤
- 关闭 babel 的模块语法转换
- 在 @babel/preset-env 配置中 modules 设置为 false,这样 babel 就不会将我们写的 es6 Module 的导入方式进行转换(tree-shaking 依赖 es6 的 Module 语法)
- 设置 mode 为 production
- 确保 usedExports 为 true(默认为 true)
- 必要的情况下指定 sideEffects
实践
usedExports
:开启后会标记哪些代码没有被使用,之后通过 Terser 来进行优化sideEffects
:在package.json
中配置哪些文件不进行优化,告诉 webpack 哪些模块有副作用(代码会执行一些特殊的逻辑如定义全局变量等,不能仅仅通过 export 来判断这段代码的使用),避免被错误删除
提高构建速度
- 给一些常用的路径起别名,减少查找过程
- 使用 SplitChunksPlugin 代码分割,将公共代码抽取出来,减少重复打包
- 使用缓存 cache
- 有一些多线程的配置,并行构建