Webpack 基本介绍
介绍
什么是 Webpack?
Webpack 如何提供帮助?
安装 Webpack
配置文件
运行 Webpack
Webpack 开发服务器
结论
介绍
在本文中,我将以实用易懂的方式介绍 Webpack 的核心概念。我将讲解如何从头开始设置 Webpack 配置文件,以及入口点、CSS、加载器、插件等每个配置的含义。
许多人可能没有意识到,当你使用 angular-cli 或 create-react-app 引导 Angular 或 React 项目时,Webpack 就在后台运行。
我写这篇文章是为了跟进。你可以从Github 仓库获取文中描述的 webpack starter 的完整代码。
什么是 Webpack?
Webpack 是一个用于现代 JavaScript 应用程序的静态模块打包器。当 Webpack 处理你的应用程序时,它会在内部构建一个依赖关系图,该图会映射项目所需的每个模块,并生成一个或多个打包文件。
下面的插图可以更简单地解释 Webpack 实际的作用。
Webpack 如何提供帮助?
让我们以任意 Web 应用程序为例。它通常包含一个 index.html 文件,其中包含许多脚本标签,如下所示。
<body>
...
<script src='src/blog.js'></script>
<script src='src/about.js'></script>
<script src='src/contact.js'></script>
<script src='src/index.js'></script>
</body>
虽然上述在 HTML 页面中包含脚本标签的方式有效,但它也带来了一些挑战,例如:
- 脚本标签需要按特定顺序加载。这是必要的,这样,引用其他脚本中函数的脚本会先于自身加载。在上面的例子中,about.js、contact.js 和 blog.js 必须在 index.js 之前加载到浏览器中,因为 index.js 很可能引用了其他脚本中的函数。
- 此外,上述方法容易出现拼写错误。
Webpack 恰恰解决了这个问题,通过使用捆绑器,您不必担心在 index.html 中包含每个脚本标签,当然也不必担心顺序。
<body>
...
<script src='dist/index_bundle.js'></script>
</body>
模块打包只是 Webpack 解决的一个方面。但是,它在将 HTML、CSS 和 JS 文件引入打包器之前进行转换的能力无疑要强大得多。让我们直接开始学习如何安装和设置 Webpack。
安装 Webpack
首先,您需要安装以下两个包才能使用 Webpack。
//Create a new folder
$ mkdir webpack-example
//Initialize a new NPM projects (Creates a package.json with default values)
> webpack-example$npm init -y
//Include the packages webpack and webpack-cli as dev dependencies
> webpack-example$npm install webpack webpack-cli --save-dev
注意事项:
- 如果您想继续操作,请创建一个新文件夹。打开终端,进入新文件夹并运行上述命令。
- 选项“—save-dev”会将软件包作为 dev 依赖项添加到你的 package.json 中。这意味着这些软件包不会包含在你的最终生产版本中。
配置文件
webpack.config.js 文件是大多数操作发生的主要位置。在这里,您将向“Webpack”提供一组指令,让它知道如何处理您的项目文件,以及如何以您希望使用的方式打包它们。
注意:根据 Webpack 官方文档,从 Webpack 4.0.0 开始,你无需配置文件即可设置打包器。然而,配置文件可能是 Webpack 中最重要的部分,你需要根据项目需求进行自定义。
我们将介绍配置文件的以下核心概念:
- 入口
- 装载机
- 输出
- 插件
- 模式
在我们开始研究概念之前,首先在项目的根结构中创建 webpack.config.js。
> webpack-example$ touch webpack.config.js
Webpack 按指定顺序执行以下操作:
- 如何找到需要打包的文件?或者如何选择应用转换?
- 访问这些文件后我需要做什么?我需要进行任何特定的转换吗?
- 我需要将我生成的捆绑包输出(保存)到哪里?
入口点
启动一切的单个文件通常是 Webpack 的入口点。它通常是“index.js”或“app.js”。
您可以将下面显示的导入结构可视化,就像 Webpack 如何创建依赖关系图一样。
index.js
imports about.js
imports contact.js
imports blog.js
imports util.js
imports api.js
让我们在应用程序文件夹中创建“index.js”。
> webpack-example$ mkdir app
> webpack-example$ cd app
> webpack-example$ touch index.js
让我们将入口点添加到 webpack.config.js
module.exports {
entry: './app/index.js'
}
装载机
现在我们已经设置了入口点,接下来要告诉 Webpack 应该如何处理项目中的文件。换句话说,需要对我们的文件应用什么样的转换。
为此,我们引入了一个叫做“加载器”的东西。默认情况下,Webpack 会查看所有 JSON 和 JS 文件来构建如上所示的依赖关系图。
import contact from './app/config' // 👍
import config from './utils/config.json' // 👍
import './css/app.css' // ❌
在上面的例子中,CSS 导入会被 Webpack 忽略,而 Loaders 正是我们在这里所需要的,它可以协助 Webpack 处理除 JS 和 JSON 之外的文件。
让我们看看如何按照以下步骤添加 CSS 加载器。
> webpack-example$ npm install css-loader --save-dev
我们需要在“modules.rules”属性数组中添加加载器。Webpack 将查找规则数组,以确定加载器的设置以及每种文件类型的相关规则。
module.exports = {
entry: './app/index.js',
module: {
rules: []
}
}
我们需要在规则数组中指定加载器属性。每个加载器都有两个需要定义的属性:
- use——加载器的名称。
- 测试——匹配文件路径的正则表达式。
module.exports = {
entry: './app/index.js',
module: {
rules: [
{ test: /\\.css$/, use: 'css-loader' }
]
}
}
现在,如果我们在项目中的任何地方使用 CSS,Webpack 都会通过加载器识别它,并将其导入到项目中。基本上,上面那个带有 ❌ 的 CSS 导入语句现在会变成 👍。
import contact from './app/config' // 👍
import config from './utils/config.json' // 👍
import './css/app.css' // 👍
DOM注入
虽然我们已经成功使用 webpack 配置导入了 CSS 文件,但还有一件事要做。我们需要将样式元素注入到 DOM 中。
简单来说,CSS 样式需要作为“样式”标签包含在 HTML 中。
为了帮助我们实现这一点,我们需要使用“style-loader”。
> webpack-example$ npm install style-loader --save-dev
并修改 webpack.config.js 以将 'style-loader' 添加到 modules.rule 数组中。
module.exports = {
entry: './app/index.js',
module: {
rules: [
{ test: /\\.css$/, use: [ 'style-loader', 'css-loader' ] }
]
}
}
注意事项:
- 由于“use”属性中需要使用 2 个变量,我们将其更改为数组。
- 加载器的引用顺序很重要,因为 webpack 会以相反的顺序处理它们。因此,css-loader 会先解释 import 命令,然后 style-loader 会将 CSS 注入到 DOM 中。
加载器可以做的事情还有很多,一个很常见的例子就是使用 Babel。Babel 根据 webpack.config.js 中指定的配置,将每个 JavaScript 文件转换为适当的 ES 语法。
您可以在此处查看完整的加载器列表。
输出
顾名思义,这个配置参数只是告诉 Webpack 在哪里输出它创建的包。
//Import 'path' to resolve the file path
const path = require('path');
//Add this configuration after module.rules config
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index_bundle.js'
}
注意事项:
- 我们正在导入“路径”包来帮助解析文件路径。
- 输出配置需要 path 参数来告知 webpack 打包文件的保存位置。此外,使用 filename 参数可以指定生成的打包文件的名称。
快速回顾
到目前为止,我们已经了解了入口、加载器和输出配置。组合所有配置后,webpack.config.js 如下所示:
//Import 'path' to resolve the file path
const path = require('path')
module.exports = {
entry: './app/index.js',
module: {
rules: [
{ test: /\\.css$/, use: [ 'style-loader', 'css-loader' ] }
]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index_bundle.js'
}
}
快速回顾:
- Webpack 找到位于的入口点
./app/index.js
。 - 它检查项目中的所有
import
和 语句并创建依赖关系图。require
- 然后它开始创建一个包,每当它遇到我们有加载器的路径时,它就会根据该加载器转换代码,然后将其添加到包中。
- 最后,它将其捆绑并输出到配置中提到的位置,即
dist/index_bundle.js
。
希望您能跟上到这里。我们还有两个配置“插件”和“模式”需要介绍。所以,请耐心等待,我们很快就完成了。
插件
虽然加载器用于转换某些类型的模块,但插件可以用来执行更广泛的任务,如捆绑优化、资产管理和环境变量注入。
插件允许你在创建 bundle 后执行某些任务。因此,这些任务可以放在 bundle 本身,也可以直接应用到源代码库中。
让我们看两个这样的插件的例子:
HtmlWebpack插件
之前我们看到,webpack 的主要好处是它会为我们生成一个单独的包,然后我们可以在主页中引用它 index.html
。
它的作用 HtmlWebpackPlugin
是,为我们生成页面,将 index.html
其粘贴到放置捆绑包的同一目录中,并自动包含 <script>
引用新生成的捆绑包的标签。
与往常一样,第一步是从 npm 下载插件。
> webpack-example$ npm install html-webpack-plugin --save-dev
接下来,我们向 webpack 配置中添加一个 plugins 属性,它是一个数组。
//Import the HtmlWebpackPlugin
const HtmlWebpackPlugin = require('html-webpack-plugin')
//Add this to the module.exports configuration
plugins: [
new HtmlWebpackPlugin()
]
现在你的整个 webpack.config.js 将如下所示:
//Import 'path' to resolve the file path
const path = require('path')
//Import the HtmlWebpackPlugin
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './app/index.js',
module: {
rules: [
{ test: /\\.css$/, use: [ 'style-loader', 'css-loader' ] }
]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index_bundle.js'
},
plugins: [
new HtmlWebpackPlugin()
]
}
HtmlWebpackPlugin 是最基本的插件之一,您可以在这里查看 Webpack 提供的其他插件。
MiniCssExtract插件
MiniCssExtractPlugin 是我们将要介绍的第二个插件示例。如果您还记得之前的示例,我们使用了 Style-loader,但使用这个插件,我们可以完全分离 CSS 文件,而不是仅仅插入 CSS 的样式元素。
与往常一样,我们将从安装依赖项作为第一步开始:
> webpack-example$ npm install --save-dev mini-css-extract-plugin
将以下内容添加到 webpack.config.js 文件:
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
plugins: [
new MiniCssExtractPlugin(),
],
最后但并非最不重要的一点是,我们将用 MiniCssExtractPlugin.loader 替换 style-loader:
{
test: /\\.css$/,
use: [
MiniCssExtractPlugin.loader, // instead of style-loader
'css-loader'
]
}
现在,当您运行 webpack 时,它将在 dist 文件夹中输出 main.css 文件,并将使用链接头从 index.html 文件引用。
模式
使用 mode 参数,您可以根据值“development”、“production”或“none”启用 webpack 的内置优化。默认值为“production”。
mode: 'production' //Other values include 'development' or 'none'
当模式设置为“生产”时,Webpack 会执行构建优化的一个例子是,它会压缩代码并删除警告。有关后台运行的详细优化列表,您可以在此处阅读。
运行 Webpack
如果你一直跟着做,那么此时你的 webpack.config.js 应该如下所示:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './app/index.js',
module: {
rules: [{ test: /\\.css$/, use: ['style-loader', 'css-loader'] }],
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index_bundle.js',
},
plugins: [new HtmlWebpackPlugin()],
mode: 'production',
};
现在让我们继续运行 Webpack。首先,我们需要在 package.json 中添加以下配置。
"scripts": {
"build": "webpack"
}
现在从命令终端运行以下命令。
> webpack-example$ npm run build
Webpack 将执行并创建一个名为 index_bundle.js 的优化包并将其放入 dist 目录中。
您应该会看到在“dist”文件夹中创建的最终的index.html。
Webpack 开发服务器
Webpack DevServer 是 webpack 的开发服务器,它会在内存中跟踪您的文件并通过本地服务器提供它们,而不是生成 dist 目录。
但最棒的是,它支持实时重新加载。这意味着,无论何时你修改代码,webpack-dev-server 都会快速重新编译代码,并使用这些更改重新加载浏览器。
我们需要从 npm 安装该包。
> webpack-example$ npm install webpack-dev-server --save-dev
然后我们需要更新 package.json 中的“scripts”属性来运行 webpack-dev-server。
"scripts": {
"start": "webpack-dev-server"
}
此外,如果环境变量中未指定“production”,我们将对 webpack.config.js 中的“mode”参数进行小幅更改,默认为“development”。
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development'
//If you’re on Windows, then the command is as follows:
"SET NODE_ENV='production' && webpack"
就是这样!如果你从终端运行“npm start”,那么你的项目将在http://localhost:8080上提供服务。
> webpack-example$ npm start
经过定制的完整项目可在以下Github 存储库中找到。
结论
虽然这篇文章很长,但说实话,我们仅仅触及了 Webpack 的表面以及它所支持的配置的无限可能性。
总而言之,我们在本文中涵盖了以下内容:
- 什么是 Webpack 以及它提供什么好处?
- Webpack 的核心组件:
- 入口点
- 装载机
- 输出
- 插件
- 模式
- 运行 Webpack - 本地和生产模式
希望这篇文章对您有所帮助。如果您觉得我的文章有趣,请不要忘记订阅我的新闻通讯。