什么是 Webpack?
本质上是一种前端资源编译、打包工具。
- 多份资源文件打包成一个 Bundle
- 支持 Babel、Eslint、TS、CoffeScript、Less、Sass
- 支持模块化处理 css、图片等资源文件
- 支持 HMT + 开发服务器
- 支持持续监听、持续构建
- 支持代码分离
- 支持 Tree-shaking
- 支持 Sourcemap
- ...
使用 Webpack
-
安装
npm i -D webpack webpack-cli -
编辑配置文件
// webpack.config.js module.exports = { entry: 'main.js', // 入口文件 output: { // 输出目录 filename: "[name].js", path: path.join(__dirname, "./dist"), }, module: { rules: [{ test: /.less$/i, use: ['style-loader', 'css-loader', 'less-loader'] }] } } -
执行编译命令
npx webpack
关于 Webpack 的使用方法,基本都围绕 “配置” 展开,而这些配置大致可划分为两类:
- 流程类:作用于流程中某个 or 若干个环节,直接影响打包效果的配置项
- 工具类:主流程之外,提供更多工程化能力的配置项
配置总览
按使用频率:
- entry / output
- module / plugins
- mode
- watch / devServer / devtool
流程类配置
-
Get Start(entry)
输入:
- entry
- context
-
Dependencies Lookup(require、import)
模块解析:
- resolve
- externals
-
Transform(module)
模块转译:
- module
-
Combine Assets(output)
后处理:
- optimization
- mode
- target
处理 CSS
-
安装 Loader
npm add css-loader style-loader -
添加 module 处理 css 文件
// webpack.config.js module.exports = { module: { // css 处理器 rules: [{ test: /.css/i, use: [ "style-loader", "css-loader" ], }], }, }
接入 Babel
-
安装依赖
npm i -D @babel/core @babel/preset0env babel-loader -
添加 module 转译 js 文件
// webpack.config.js module.exports = { module: { rules: [{ test: /.js$/, use: [{ loader: 'babel-loader', options: { presets: [ ['@babel/preset-env'], ], }, }], }], }, }
生成 HTML
-
安装依赖
npm i -D html-webpack-plugin -
配置 plugin
// webpack.config.js module.exports = { plugins: [new HtmlWebpackPlugin()] }
工具类配置
HMR
Hot Module Replacement:模块热替换。
-
开启 HMR
// webpack.config.js module.exports = { devServer: { hot: true } } -
启动
npx webpack serve
Tree-Shaking
Tree-Shaking:树摇,用于删除 Dead Code。
- 模块导出了,但未被其他模块使用
Dead Code:
- 代码没有被用到,不可到达
- 代码的执行结果不会被用到
- 代码只读不写
- ...
-
修改 mode
// webpack.config.js module.exports = { mode: 'production' } -
配置 optimization
// webpack.config.js module.exports = { optimization: { usedExports: true } }
PS:对工具类库如 Lodash 有奇效。
其他
- 缓存
- Sourcemap
- 性能监控
- 日志
- 代码压缩
- 分包
- ...
Webpack 打包核心流程
- 入口处理(Get Start):从 entry 文件开始,启动编译流程
- 依赖解析(Dependencies Lookup):从 entry 文件开始,根据 require 或 import 等语句找到依赖资源
- 资源解析(Transform):根据 module 配置,调用资源转移器,将 png、css 等非标准 JS 资源转译为 JS 内容
- 资源合并打包(Combine Assets):将转译后的资源内容合并打包为可直接在浏览器运行的 JS 文件
递归调用 2、3,直到所有资源处理完毕。
模块化 + 一致性
- 多个文件资源合并成一个,减少 http 请求数
- 支持模块化开发
- 支持高级 JS 特性
- 支持 TypeScript、CoffeeScript 方言
- 统一图片、CSS、字体等其他资源的处理模型
- ...
Loader
由于 Webpack 只认识 JS,为了处理非标准 JS 资源,设计出资源翻译模块——Loader。
作用:用于将资源翻译为标准 JS。
-
安装 Loader
npm add -D css-loader style-loader less-loader -
配置 module
// webpack.config.js module.exports = { module: { rules: [ { test: /.less$/i, use: [ "style-loader", // 将 CSS 模块包进 require 语句,并在运行时调用 injectStyle 等函数将内容注入到页面的 style 标签 "css-loader", // 将 CSS 包装成类似 module.exports = "${css}" 的内容,包装后的内容符合 JavaScript 语法 "less-loader", // 实现 less => css 的转换 ], }, ], }, };
特性
- 链式执行
- 支持异步执行
- 分 normal、pitch 两种模式
编写 Loader
// myLoader.js
module.exports = function(source, sourceMap?, data?) {
// source 为 loader 的输入
// 可能是文件内容,也可能是上一个 loader 处理结果
return source;
}
在 Loader 中 debug
在 npx 前面加上 ndb。
ndb npx webpack
常见 Loader
-
JavaScript
- babel-loader
- eslint-loader
- ts-loader
- buble-loader
- vue-loader
- angular2-template-loader
-
CSS
- css-loader
- style-loader
- less-loader
- sass-loader
- stylus-loader
- postcss-loader
-
HTML
- html-loader
- pug-loader
- posthtml-loader
-
Assets
- file-loader
- val-loader
- url-loader
- json5-loader
Plugin
DashboardPlugin
作用:美化终端数据展示。
-
安装
npm i -D webpack-dashboard -
引入并配置 plugins
// webpack.config.js const DashboardPlugin = require('webpack-dashboard/plugin'); module.exports = { plugins: [new DashboardPlugin()] }
如何编写 Plugin
钩子的核心信息:
- 时机:编译过程的特定节点,Webpack 会以钩子形式通知插件此刻正在发生什么事情
- 上下文:通过 tapable 提供的回调机制,以参数方式传递上下文信息
- 交互:在上下文参数对象中附带了很多存在 side effect 的交互接口,插件可以通过这些接口改变
总共有 239 个钩子。
class EntryPlugin {
apply(compiler) {
// 时机
compiler.hooks.compilation.tap(
"EntryPlugin",
// 参数
(compilation, { normalModuleFactory }) => {
// 交互
compilation.dependencyFactories.set(
EntryDependency,
normalModuleFactory
)
}
)
}
}
如何学习 Webpack
入门应用
- 理解打包流程
- 熟练掌握常用配置项、Loader、插件的使用方法,能够灵活搭建集成 Vue、React、Babel、Eslint、Less、Sass、图片处理等工具的 Webpack 环境
- 掌握常见脚手架工具的用法,例如:Vue-cli、create-react-app、@angular/cli
进阶
- 理解 Loader、Plugin 机制,能够自行开发 Webpack 组件
- 理解常见性能优化手段,并能用于解决实际问题
- 理解前端工程化概念与生态现状
大师级
阅读源码,理解 Webpack 编译、打包原理,甚至能够参与共建。