Webpack 用于编译 JavaScript 模块。一旦安装,你可以通过其命令行界面 (CLI) 或 API 与 webpack 进行交互。如果你刚接触 webpack,请阅读核心概念和此比较,了解为何你可能更愿意使用它而不是社区中的其他工具。
首先,让我们创建一个目录,初始化 npm,本地安装 webpack,并安装 webpack-cli
(用于在命令行运行 webpack 的工具)
mkdir webpack-demo
cd webpack-demo
npm init -y
npm install webpack webpack-cli --save-dev
在整个指南中,我们将使用 **diff
** 块来展示我们对目录、文件和代码所做的更改。例如:
+ this is a new line you shall copy into your code
- and this is a line to be removed from your code
and this is a line not to touch.
现在我们将创建以下目录结构、文件及其内容
项目
webpack-demo
|- package.json
|- package-lock.json
+ |- index.html
+ |- /src
+ |- index.js
src/index.js
function component() {
const element = document.createElement('div');
// Lodash, currently included via a script, is required for this line to work
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
return element;
}
document.body.appendChild(component());
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Getting Started</title>
<script src="https://unpkg.com/lodash@4.17.20"></script>
</head>
<body>
<script src="./src/index.js"></script>
</body>
</html>
我们还需要调整 package.json
文件,以确保将我们的包标记为 private
,并删除 main
入口。这样做是为了防止你的代码意外发布。
package.json
{
"name": "webpack-demo",
"version": "1.0.0",
"description": "",
- "main": "index.js",
+ "private": true,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "MIT",
"devDependencies": {
"webpack": "^5.38.1",
"webpack-cli": "^4.7.2"
}
}
在此示例中,<script>
标签之间存在隐式依赖。我们的 index.js
文件依赖于 lodash
在运行前被包含在页面中。这是因为 index.js
从未明确声明对 lodash
的需求;它假设全局变量 _
存在。
以这种方式管理 JavaScript 项目存在一些问题
让我们转而使用 webpack 来管理这些脚本。
首先,我们将稍微调整目录结构,将“源代码”(./src
) 与我们的“分发代码”(./dist
) 分开。“源代码”是我们编写和编辑的代码。“分发代码”是构建过程的最小化和优化后的 output
,最终将被加载到浏览器中。调整目录结构如下:
项目
webpack-demo
|- package.json
|- package-lock.json
+ |- /dist
+ |- index.html
- |- index.html
|- /src
|- index.js
为了将 lodash
依赖与 index.js
打包在一起,我们需要本地安装该库
npm install --save lodash
现在,让我们在脚本中导入 lodash
src/index.js
+import _ from 'lodash';
+
function component() {
const element = document.createElement('div');
- // Lodash, currently included via a script, is required for this line to work
+ // Lodash, now imported by this script
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
return element;
}
document.body.appendChild(component());
现在,由于我们将打包脚本,我们必须更新 index.html
文件。让我们移除 lodash 的 <script>
标签,因为我们现在 import
它,并修改另一个 <script>
标签来加载打包文件,而不是原始的 ./src
文件
dist/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Getting Started</title>
- <script src="https://unpkg.com/lodash@4.17.20"></script>
</head>
<body>
- <script src="./src/index.js"></script>
+ <script src="main.js"></script>
</body>
</html>
在此设置中,index.js
明确要求 lodash
存在,并将其绑定为 _
(没有全局作用域污染)。通过声明模块所需的依赖项,webpack 可以利用这些信息构建依赖图。然后它使用该图生成一个优化的 bundle,其中脚本将按正确的顺序执行。
话虽如此,让我们运行 npx webpack
,它将把 src/index.js
处的脚本作为入口点,并生成 dist/main.js
作为输出。npx
命令(Node 8.2/npm 5.2.0 或更高版本自带)会运行我们最初安装的 webpack 包的 webpack 二进制文件 (./node_modules/.bin/webpack
)
$ npx webpack
[webpack-cli] Compilation finished
asset main.js 69.3 KiB [emitted] [minimized] (name: main) 1 related asset
runtime modules 1000 bytes 5 modules
cacheable modules 530 KiB
./src/index.js 257 bytes [built] [code generated]
./node_modules/lodash/lodash.js 530 KiB [built] [code generated]
webpack 5.4.0 compiled successfully in 1851 ms
在浏览器中打开 dist
目录下的 index.html
,如果一切顺利,你应该会看到以下文本:'Hello webpack'
。
import
和 export
语句已在 ES2015 中标准化。目前它们在大多数浏览器中都受支持,但也有一些浏览器不识别新语法。但别担心,webpack 开箱即用地支持它们。
在幕后,webpack 实际上会“转译”代码,以便旧版浏览器也能运行它。如果你检查 dist/main.js
,你可能会看到 webpack 是如何做到这一点的,这非常巧妙!除了 import
和 export
,webpack 还支持各种其他模块语法,详情请参阅模块 API。
请注意,webpack 不会更改除 import
和 export
语句之外的任何代码。如果你正在使用其他 ES2015 特性,请确保通过 webpack 的加载器系统使用转译器,例如 Babel。
从版本 4 开始,webpack 不需要任何配置,但大多数项目都需要更复杂的设置,这就是 webpack 支持配置文件的原因。这比在终端中手动输入大量命令要高效得多,所以让我们创建一个:
项目
webpack-demo
|- package.json
|- package-lock.json
+ |- webpack.config.js
|- /dist
|- index.html
|- /src
|- index.js
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
},
};
现在,让我们再次运行构建,但这次使用我们的新配置文件
$ npx webpack --config webpack.config.js
[webpack-cli] Compilation finished
asset main.js 69.3 KiB [compared for emit] [minimized] (name: main) 1 related asset
runtime modules 1000 bytes 5 modules
cacheable modules 530 KiB
./src/index.js 257 bytes [built] [code generated]
./node_modules/lodash/lodash.js 530 KiB [built] [code generated]
webpack 5.4.0 compiled successfully in 1934 ms
配置文件比命令行界面 (CLI) 的使用方式提供了更大的灵活性。通过这种方式,我们可以指定加载器规则、插件、解析选项以及许多其他增强功能。参阅配置文档了解更多信息。
鉴于从命令行界面 (CLI) 运行本地 webpack 副本并不那么方便,我们可以设置一个快捷方式。让我们通过添加一个 npm 脚本来调整我们的 package.json。
package.json
{
"name": "webpack-demo",
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "build": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^5.4.0",
"webpack-cli": "^4.2.0"
},
"dependencies": {
"lodash": "^4.17.20"
}
}
现在 npm run build
命令可以替代我们之前使用的 npx
命令。请注意,在 scripts
中,我们可以像使用 npx
那样按名称引用本地安装的 npm 包。这种约定在大多数基于 npm 的项目中都是标准做法,因为它允许所有贡献者使用同一套通用脚本。
现在运行以下命令,看看你的脚本别名是否有效
$ npm run build
...
[webpack-cli] Compilation finished
asset main.js 69.3 KiB [compared for emit] [minimized] (name: main) 1 related asset
runtime modules 1000 bytes 5 modules
cacheable modules 530 KiB
./src/index.js 257 bytes [built] [code generated]
./node_modules/lodash/lodash.js 530 KiB [built] [code generated]
webpack 5.4.0 compiled successfully in 1940 ms
既然你已经完成了一个基础构建,那么你应该继续阅读下一篇指南资源管理
,了解如何使用 webpack 管理图片和字体等资源。此时,你的项目结构应如下所示:
项目
webpack-demo
|- package.json
|- package-lock.json
|- webpack.config.js
|- /dist
|- main.js
|- index.html
|- /src
|- index.js
|- /node_modules
如果你想了解更多关于 webpack 的设计,可以查看基本概念和配置页面。此外,API 部分深入探讨了 webpack 提供的各种接口。