Space Cowboy

生死去来 棚头傀儡 一线断时 落落磊磊

0%

好耶!是 Webpack(一)———— 基础概念

简述

Webpack 是什么?官网是这样介绍的:

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

只要你从事前端开发,就不可能绕过 Webpack 这个工具。这篇文章基于 Webpack4,总结其核心概念及常规用法。

核心概念

Webpack 的核心概念分为四个:entryoutputloaderplugin
理解这些概念是更好的使用 Webpack 的保证。

入口 entry

关于入口,官方是这样定义的:

入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部 依赖图(dependency graph) 的开始。

换句话说,Webpack 会从入口开始遍历整棵依赖树。你可以理解为对二叉树的遍历。

单入口

一个简单的单文件入口示例是这样的,适用于一些简单场景中:

1
2
3
4
5
const { resolve } = require("path");

module.exports = {
entry: resolve(__dirname, "src/index.js"),
};

多入口

在复杂应用中,将文件打包为一个 bundle 会导致页面加载缓慢,所以我们需要做 Code Splitting
简单来说就是多入口、多出口、公共部分。
这种优化的前提就是多文件入口打包。

1
2
3
4
5
6
7
8
const { resolve } = require("path");

module.exports = {
entry: {
entry1: resolve(__dirname, "src/index.js"),
entry2: resolve(__dirname, "src/index2.js"),
},
};

出口 output

关于出口,官方是这样定义的:

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

输出的文件名可以写死,也可以根据入口文件动态配置。

1
2
3
4
5
6
7
8
9
const { resolve } = require("path");

module.exports = {
output: {
path: resolve(__dirname, "dist"),
// filename: "bundle.js"
filename: "[name]_[hash].js",
},
};

关于文件哈希值,有以下几种配置:

  • hash
  • chunkhash 同一个 chunk 同一个 hash
  • contenthash 一个文件一个 hash

loader

关于 loader,官方是这样定义的:

webpack 只能理解 JavaScript 和 JSON 文件。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中。

简单来说,你需要 loader 来转换诸如 css 文件等东西。

几个 loader 的常用配置

  • test loader 匹配规则
  • exclude 不需要匹配的文件
  • include 只匹配哪些文件
  • loader 使用单个 loader
  • use 使用多个 loader,是数组
  • options loader 的参数,参考对应 loader 的文档

注意 如果你使用多个 loader,它们是按照数组逆序的顺序运行的

loader 配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
module.exports = {
module: {
rules: [
{
// 处理 html 文件的 loader
test: /\.html$/,
exclude: /node_modules/,
include: /src/,
loader: "html-loader",
},
{
// 处理 css 文件的 loader
test: /\.css$/,
use: [
// 逆序执行
"style-loader",
"css-loader",
],
},
{
// 处理 js 文件的 loader
test: /\.js$/,
exclude: /node_modules/,
use: [
// 多线程打包
"thread-loader",
{
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
},
},
],
},
],
},
};

plugin

关于 plugin,官方是这样定义的:

插件可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量。
换句话说,插件主要是为了增强 webpack 在自动化构建方面的能力。

例子中使用 HtmlWebpackPlugin 自动创建打包后的 html 文件。使用 CleanWebpackPlugin 插件,在每次打包前,自动清理上一次打包的文件。

1
2
3
4
5
6
7
8
9
10
11
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

module.exports = {
plugins: [
new HtmlWebpackPlugin({
title: "Hello Webpack",
}),
new CleanWebpackPlugin(),
],
};

不过插件的配置没有什么规律可循,一切都得查阅对应插件的文档来配置。

常用 loader

下面总结一些常用的 loader,具体用法可以查阅对应的文档。

css 相关

  • style-loader
  • css-loader
  • postcss-loader
  • sass-loader
  • less-loader

js 相关

  • babel-loader
  • @babel/core
  • @babel/preset-env
  • @babel/polyfill

文件相关

  • url-loader
  • file-loader
  • html-loader

vue 相关

  • vue-loader
  • vue-style-loader