webpack 用于编译 JavaScript 模块。一旦完成 安装,你就可以通过 webpack 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.
现在,我们将创建以下目录结构、文件和内容:
project
webpack-demo
|- package.json
|- package-lock.json
+ |- index.html
+ |- /src
+ |- index.js
src/index.js
function component() {
const element = document.createElement('div');
// lodash(目前通过一个 script 脚本引入)对于执行这一行是必需的
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
return element;
}
document.body.appendChild(component());
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>起步</title>
<script src="https://unpkg.com/[email protected]"></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 来管理这些脚本。
首先,我们稍微调整下目录结构,创建 ./dist
文件夹用于存放分发代码,而 ./src
文件夹仍存放源代码。源代码是指用于书写和编辑的代码;分发代码是指在构建过程中,经过最小化和优化后产生的输出结果,最终将在浏览器中加载。调整后目录结构如下:
project
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(目前通过一个 script 脚本引入)对于执行这一行是必需的
+ // lodash 现在使用 import 引入
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
return element;
}
document.body.appendChild(component());
现在,我们将会打包所有脚本,因此必须更新 index.html
文件。由于现在是通过 import
引入 lodash,所以应将 lodash <script>
删除;然后修改另一个 <script>
标签来加载 bundle,而不是原始的 ./src
文件:
dist/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>起步</title>
- <script src="https://unpkg.com/[email protected]"></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
作为 输出。Node 8.2/npm 5.2.0 及以上版本提供的 npx
命令,可以运行在最初安装的 webpack package 中的 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'
。
ES2015 中的 import
和 export
语句已经被标准化。虽然大多数浏览器还无法支持它们,但是 webpack 却能够提供开箱即用般的支持。
事实上,webpack 在幕后会将代码 “转译”,以便可以在旧版本浏览器中执行。如果你检查 dist/main.js
,你可以看到 webpack 具体是如何工作的,这是独创精巧的设计!除了 import
和 export
,webpack 还能够很好地支持多种其他模块语法,更多信息请查看 模块 API。
注意,webpack 不会更改代码中除 import
和 export
语句以外的部分。如果你在使用其它 ES2015 特性,请确保 webpack 的 loader 系统 中使用了像 Babel 一样的 transpiler(转译器)。
在 webpack v4 中,无须任何配置即可运行,然而大多数项目会需要很复杂的设置,这就是为什么 webpack 仍然要支持 配置文件。这比在 terminal(终端)中手动输入大量命令要更加高效,所以让我们创建一个配置文件:
project
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 这种简单直接的使用方式,配置文件更加灵活。我们可以在配置文件中指定 loader 规则、插件、resolve 选项,以及许多其他增强功能。更多详细信息请查看 配置文档。
考虑到用 CLI 这种方式来运行本地的 webpack 副本并不是特别方便,我们可以设置一个快捷方式。在 package.json 文件中添加一个 npm script:
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
命令。注意,使用 npm scripts
便可以像使用 npx
那样通过模块名引用本地安装的 npm packages。这是大多数基于 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 管理诸如图像、图标等资源。此刻你的项目目录看起来应该如下:
project
webpack-demo
|- package.json
|- package-lock.json
|- webpack.config.js
|- /dist
|- main.js
|- index.html
|- /src
|- index.js
|- /node_modules
如果想要了解 webpack 设计思想,可以查看 基本概念 和 配置 页面。此外,你能够在 API 章节深入了解 webpack 提供的各种接口。