Webpack入门

5/8/2021 Webpack

# 序言

之前一直对webpack都是拿来即用,从来没去了解一些基本概念,Getting Started也没看过。

所以今天看了一下文档,了解了一下基本概念,就简单做个记录。

该文章仅介绍一些基础概念和入门案例,更多请查看官方文档:英文原版 (opens new window)中文版 (opens new window)

# 什么是webpack

本质上,webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部构建一个 依赖图(dependency graph),此依赖图对应映射到项目所需的每个模块,并生成一个或多个 bundle

# 一些核心概念

主要是以下几个keywords

  • Entry
  • Output
  • Loaders
  • Plugins
  • Mode
  • Browser Compatibility

# Entry

用于指定一个入口js文件作为依赖图的开始。

module.exports = {
  entry: './path/to/my/entry/file.js',
};
1
2
3

# Output

告诉 webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。

主要输出文件的默认值是 ./dist/main.js,其他生成文件默认放置在 ./dist 文件夹中。

const path = require('path');

module.exports = {
  entry: './path/to/my/entry/file.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js',
  },
};
1
2
3
4
5
6
7
8
9

# loader

让 webpack 能够去处理其他类型的文件,并将它们转换为有效模块,并将其添加到依赖图。

默认可处理JavaScript 和 JSON 文件。

loader由两个属性组成:

  1. test 属性,识别出哪些文件会被转换。
  2. use 属性,定义出在进行转换时,应该使用哪个 loader。
const path = require('path');

module.exports = {
  output: {
    filename: 'my-first-webpack.bundle.js',
  },
  module: {
    rules: [{ test: /\.txt$/, use: 'raw-loader' }],
  },
};
1
2
3
4
5
6
7
8
9
10

以上配置中,对一个单独的 module 对象定义了 rules 属性,里面包含两个必须属性:testuse。这告诉 webpack 编译器(compiler) 如下信息:

“嘿,webpack 编译器,当你碰到「在 require()/import 语句中被解析为 '.txt' 的路径」时,在你对它打包之前,先 use(使用) raw-loader 转换一下。”

# Plugin

插件可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量。

想要使用一个插件,你只需要 require() 它,然后把它添加到 plugins 数组中。多数插件可以通过选项(option)自定义。你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new 操作符来创建一个插件实例。

const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装
const webpack = require('webpack'); // 用于访问内置插件

module.exports = {
  module: {
    rules: [{ test: /\.txt$/, use: 'raw-loader' }],
  },
  plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })],
};
1
2
3
4
5
6
7
8
9

在上面的示例中,html-webpack-plugin 为应用程序生成一个 HTML 文件,并自动注入所有生成的 bundle。

# Mode

通过选择 development, productionnone 之中的一个,来设置 mode 参数,你可以启用 webpack 内置在相应环境下的优化。其默认值为 production

module.exports = {
  mode: 'production',
};
1
2
3

# Browser Compatibility

webpack 支持所有符合 ES5 标准 (opens new window) 的浏览器(不支持 IE8 及以下版本)。webpack 的 import()require.ensure() 需要 Promise。如果你想要支持旧版本浏览器,在使用这些表达式之前,还需要 提前加载 polyfill (opens new window)

# Getting Started

# 基本安装

执行以下命令

mkdir webpack-demo
cd webpack-demo
npm init -y
npm install webpack webpack-cli --save-dev
1
2
3
4

创建以下目录结构

project

  webpack-demo
  |- package.json
+ |- index.html
+ |- /src
+   |- index.js
1
2
3
4
5

src/index.js

function component() {
  const element = document.createElement('div');

  // lodash(目前通过一个 script 引入)对于执行这一行是必需的
  element.innerHTML = _.join(['Hello', 'webpack'], ' ');

  return element;
}

document.body.appendChild(component());
1
2
3
4
5
6
7
8
9
10

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>起步</title>
    <script src="https://unpkg.com/lodash@4.17.20"></script>
  </head>
  <body>
    <script src="./src/index.js"></script>
  </body>
</html>
1
2
3
4
5
6
7
8
9
10
11

Lodash (opens new window) 是一个一致性、模块化、高性能的 JavaScript 实用工具库。

我们还需要调整 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": "ISC",
   "devDependencies": {
     "webpack": "^5.4.0",
     "webpack-cli": "^4.2.0"
   }
 }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 创建一个 bundle

修改目录结构

  webpack-demo
  |- package.json
+ |- /dist
+   |- index.html
- |- index.html
  |- /src
    |- index.js
1
2
3
4
5
6
7

本地安装lodash

npm install --save lodash
1

在安装一个 要打包到生产环境 bundle 中的package时,,你应该使用 npm install --save。如果你在安装一个用于开发环境的 package 时(例如,linter, 测试库等),你应该使用 npm install --save-dev。更多信息请查看 npm 文档 (opens new window)

现在,在我们的 script 中 import lodash

src/index.js

+import _ from 'lodash';
+
 function component() {
   const element = document.createElement('div');

-  // lodash(目前通过一个 script 引入)对于执行这一行是必需的
+  // lodash 在当前 script 中使用 import 引入
   element.innerHTML = _.join(['Hello', 'webpack'], ' ');

   return element;
 }

 document.body.appendChild(component());
1
2
3
4
5
6
7
8
9
10
11
12
13

现在,我们将会打包所有脚本,我们必须更新 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/lodash@4.17.20"></script>
   </head>
   <body>
-    <script src="./src/index.js"></script>
+    <script src="main.js"></script>
   </body>
 </html>
1
2
3
4
5
6
7
8
9
10
11
12

执行 npx webpack,然后打开dist/index.html,应该就能看到hello webpack了。说明import的js也被打包进去了。

直接运行html出现main.js语法错误,使用vscode open with live server却发现一切正常

初步怀疑是js等级问题,后来f12查看js,发现出现乱码,查看html编码,果然有问题,不知道为什么是utf-16,而js编码为utf-8,遂修改html编码为utf-8,问题解决

# 模块

ES2015(ES6的第一个版本)的importexport已十分常见,但是很多浏览器却不能支持,所以webpack默认会将一些模块的语法转换成浏览器可以兼容的方式。除了exportimport,webpack还支持更多信息查看模块API (opens new window)

webpack 不会更改代码中除 importexport 语句以外的部分。如果你在使用其它 ES2015 特性 (opens new window),请确保你在 webpack loader 系统 (opens new window) 中使用了一个像是 Babel (opens new window)Bublé (opens new window)transpiler(转译器) (opens new window)

# 使用一个配置文件

在以下目录创建配置文件,webpack.config.js

 webpack-demo
  |- package.json
+ |- webpack.config.js
  |- /dist
    |- index.html
  |- /src
    |- index.js
1
2
3
4
5
6
7
const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist'),
  },
};
1
2
3
4
5
6
7
8
9

执行npx webpack --config webpack.config.js,成功构建。

--config只是表明可以指定配置文件,缺省值为webpack.config.js,也就是以上的--config可以被省略

# npm scripts

一般情况,我们会将webpack的脚本配置到npm的script中。

package.json

"scripts": {
     "test": "echo \"Error: no test specified\" && exit 1",
+    "build": "webpack"
   },
1
2
3
4

现在,我们就可以直接执行npm run build来进行打包了。

可以通过在 npm run build 命令与参数之间添加两个连接符的方式向 webpack 传递自定义参数,例如:npm run build -- --color。

也可以在build script中webpack后加上自定义参数

# 管理资源

为了在 JavaScript 模块中 import 一个 CSS 文件,你需要安装 style-loader 和 css-loader,并在 module 配置 中添加这些 loader:

npm install --save-dev style-loader css-loader
1

同时配置webpack.config.js

 const path = require('path');

 module.exports = {
   entry: './src/index.js',
   output: {
     filename: 'bundle.js',
     path: path.resolve(__dirname, 'dist'),
   },
+  module: {
+    rules: [
+      {
+        test: /\.css$/i,
+        use: ['style-loader', 'css-loader'],
+      },
+    ],
+  },
 };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

这样,项目依赖的CSS将会被打包。

更多资源类型参考官方文档-管理资源 (opens new window)

# 最后

至此,webpack的入门可以告一段落了,有些这些基本概念和使用方式,相信已经能够让初学者初步使用webpack了。