这是我参与「第四届青训营 」笔记创作活动的的第16天
字节跳动青训营范文杰老师的课
一.什么是 Webpack
前端项目由各式各样的资源组成,包括 png,js,ts,jsx,vue,css,less 等等,早期项目需要手动通过 script,img 等标签来引入各种文件。
外部资源特别多时,我们需要手动管理,要考虑文件顺序等问题,特别容易出错。这样做影响了开发效率,限制了项目的规模。
为了解决这些问题,出现了很多工程化工具。正是因为这些工具的出现,有了前端工程化的概念。
Webpack 是前端资源的编译和打包工具。
编译是为了将图片、less、sass、ts 等非 JS 文件转变成标准的 JS 内容。之后将编译好的内容打包成一个文件 bundle。Webpack 刚出现的时候,浏览器不支持 ESM 模式,当时将资源放到浏览器运行需要逐个引入 script,使用 Webpack 打包好后只需要插入一个 script。
二.使用Webpack
示例
使用 Webpack 主要分三步:安装、编辑配置文件、执行编译命令。
- 安装
npm i -D webpack webpack-cli
- 编辑配置文件
// webpack.config.js
const path = require('path')
module.exports = {
// 打包的入口
entry: './src/index',
// 打包模式 development 和 production,默认为 production
mode: 'development',
devtool: false,
// 打包的出口
output: {
filename: '[name].js',
path: path.join(__dirname, './dist')
}
}
- 执行编译命令
npx webpack
待编译的文件:
// src/index.js
import bar from './bar'
console.log(`hello ${bar}`)
// src/bar.js
export default 'bar'
编译的结果:
// dist/main.js
// ...
__webpack_require__.r(__webpack_exports__);
// ...
const __WEBPACK_DEFAULT_EXPORT__ = ('bar')
// ...
console.log(`hello ${_bar__WEBPACK_IMPORTED_MODULE_0__["default"]}`)
打包后 import 语句会转为 webpack_require 语句,两个文件被合并为一个。
核心流程
资源解析就是调用 loader 的过程。
Webpack 主要做两件事情:模块化、一致性。
模块化是指将不同类型的文件都用 import 和 require 来管理,
一致性是指 Webpack 支持非 JS 语言,像 TypeScript,图片,CSS,字体等资源的合并打包。
(核心流程简化版)
怎么使用
配置分类
关于Webpack的使用方法,基本都围绕“配置”展开,而这些配置大致可划分为两类:
流程类:作用于流程中某个or若干个环节,直接影响打包效果的配置项
工具类:主流程之外,提供更多工程化能力的配置项
流程类配置图
配置总览
文件结构
1. 处理 CSS
1.安装 loader
npm add -D css-loader style-loader
2.添加 module 处理 CSS 文件
// webpack.config.js
const path = require('path')
module.exports = {
// ...
module: {
rules: [{
// 过滤条件,满足 test 规则的才使用 rule 处理
test: /.css$/,
// 用什么 loader 去处理满足 test 的文件
use: ["style-loader", "css-loader"]
}]
}
}
3.执行 npx webpack
待处理的文件:
// index.js
import styles from './index.css'
2. 接入 Babel
Babel 是代码转译工具,用于将 ES6 的代码编译成 ES5 的代码。
- 安装依赖
npm i -D @babel/core @babel/preset-env babel-loader
2.声明产物出口 output
const path = require("path");
module.exports = {
entry: "./src/index",
output: {
filename: " [ name].js",
path: path.join(__dirname, "./dist"),
},
module: {
rules: [{
test: /.js?$/,
use: [{
loader: ' babel-loader',
options: {
presets: [
// preset 是提前打包好的规则集
['@babel/preset-env']
]
}
}]
}],
},
};
3.执行 npx webpack
3. 生成 HTML
使用插件自动生成 HTML 文件。
1.安装依赖
npm i -D html-webpack-plugin
2.声明产物出口 output
const path = require("path");
const HtmlwebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: "./src/index",
output: {
filename: "[name].js",
path: path.join(__dirname, " ./dist"),
},
// 生成 HTML
plugins: [new HtmlwebpackPlugin()]
};
3.执行 npx webpack
4. HMR
HMR 是指 Hot Module Replacement 模块热替换,编写的代码可以立刻被更新到浏览器上,不需要刷新。
- 开启 HMR
module.exports = {
// ...
devServer: {
// 开启 HMR
hot: true
}
// webpack 持续监听文件的变化并持续构建
watch: true
};
2.启动 Webpack
npx webpack serve
5. Tree-Shaking
用于删除 dead code,也就是没有用到的代码。
module.exports = {
// ...
mode: "production"
optimization {
usedExports: true
}
};
理解 Loader
Webpack 只认识 JS,Loader 的作用是做内容的转换,它将非标准的 JS 资源翻译为标准 JS。
使用 Loader:处理 less 文件
- 安装 Loader
npm add -D css-loader style-loader less-loader
2.添加 module 处理 less 文件
module.exports = {
module: {
rules: [{
test: /.less$/i,
use: ["style-loader", "css-loader", "less-loader"],
}],
},
};
这三个 loader 符合链式调用的规则:
- less-loader:实现 less => CSS 的转换
- css-loader:将 CSS 包装成类似 module.exports = "${css]" 的内容,包装后的内容符合 JavaScript 语法
- style-loader:将 CSS 模块包进 require 语句,并在运行时调用 injectStyle 等函数将内容注入到页面的 style 标签
其他特性:
链式执行;支持异步执行;分 normal、pitch 两种模式。
执行阶段从数组的最后一位向前进行。
编写 Loader:
// loader.js
module.exports = function (source, sourceMap?, data?) {
// source 为 loader 的输入
//可能是文件内容,也可能是上一个 loader 处理结果
return source;
};
理解插件
使用插件的目的是提升应用的可扩展性,体现了对拓展开放、对修改关闭的思维。插件是在 Webpack 的整个生命周期都会生效的组件。
使用插件:Dashboard
// npm i -D webpack-dashboard
// Import the plugin:
const DashboardPlugin = require("webpack-dashboard/plugin");
// Add it to your webpack configuration plugins.
module.exports = {
// ...
plugins: [new DashboardPlugin()]
//...
};
编写插件的过程围绕钩子展开,包括钩子的时机、上下文、交互。
学习 Webpack
Webpack 入门的关键知识点: