Webpack 自学

说明

学习资源来自 b 站教学视频,尚硅谷

介绍

  • Webpack 是一种前端资源构建工具(把一些小的工具打包成大的工具),一个静态模块打包器
  • 在 Webpack 看来,前端的所有资源文件(js/json/css/img/less/...)都会作为模块处理。
  • 它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源bundle

核心概念

  • Entry:入口
  • Output:出口
  • Loader:这个 webpack 自身只理解 javascript,loader 相当于翻译官,把 css,img 这些内容进行 webpack 能识别的
  • Plugins:插件
  • Mode:模块

Hello Webpack

  1. 首先我们在文件夹下,用 shell 输入npm init,生成package.json文件(这个文件就是包管理文件,用来记录你都用了那些的包)
  2. 新建一个名为bulid的文件夹(用来导出打包好的文件)
  3. 新建一个名为src的文件夹(它的下面放将要打包的文件),并在此文件夹下新建index.js(入口文件),在里面写点东西(写个输出函数之类的方便测试)
    在这里插入图片描述
  4. 刚开始都要安装以下两个包webpackwebpack-cli ,我们通过 shell 命令安装即可: npm install webpack webpack-cli-g
  5. 然后在项目文件夹下,输入webpack ./src/index.js -o ./build/built.js --mode=development
    在这里插入图片描述
    生成打包文件bulit.js
  6. 可以在写一个html,然后引用这个打包好的 js 来检测
    在这里插入图片描述
  7. 一个比较简单的 webpack 流程就是这样啦

打包 CSS

推理是否能直接打包 CSS

  • 我们可以做个测试:webpack 是否能直接打包 CSS 等文件呢?
  • 首先我新建一个css文件
  • 在入口 js 文件中引入 css 文件
  • 尝试 bash 打包:报错
    在这里插入图片描述
  • 然而它也可以处理 json 文件,证明如下
    在这里插入图片描述

结论

  1. webpack 能处理js/json,不能处理css/img等其他资源
  2. 生产环境和开发环境能将 ES6 模块化编译成浏览器能识别的模块化
  3. 生产环境比开发环境多一个压缩 js 代码

如何处理 CSS 等文件打包?

所需插件

  • 此时我们需要一个翻译官css-loaderstyle-loader

插件工作过程

  1. 首先css-loader这个插件(通过 npm),将 css 文件变成 commonjs 模块加载到 js 中,里面内容是样式字符串
  2. 然后style-loader这个插件,创建 style 标签,将 js 中的样式资源插入进去,添加到 head 中生效

实际操作

  1. 首先我们在项目里新建一个名为webpack.config.js的文件
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/* 
webpack.config.js webpack的配置文件
作用: 指示webpack干那些活,当你运行webpack 指令时,会加载里面的配置
所有构建工具都是基于node平台运行的,模块化默认采用commonjs
*/
// 解构赋值,resolve 用来 拼接 绝对路径的方法
const { resolve } = require("path");

module.exports = {
// webpack配置:入口起点
entry: "./src/index.js",

// 输出
output: {
// 输出文件名
filename: "built.js",
// 输出路径
// __dirname是nodejs 的变量,代表当前文件的目录的绝对路径
path: resolve(__dirname, "build"),
},

// node找包特点:这个文件夹下没有,找它的父亲文件夹
// 所以可以在父级下载所需的包

// loader的配置
module: {
rules: [
// 详细loader配置
// 不同文件格式必须配置不同loader处理
{
// 匹配那些文件
test: /\.css$/,
// 使用那些loader进行处理
use: [
// use 数组中loader 执行顺序:从右到左,从下到上,
// 先执行css-loader,然后执行style-loader

// 1. 创建style标签,将js中的样式资源插入进去,添加到head中生效
"style-loader",

// 2. 将css文件变成commonjs模块加载到js中,里面内容是样式字符串
"css-loader",
],
},
{
test: /\.less$/,
use: [
"style-loader",
"css-loader",

// 将less编译成css模型
"less-loader",
],
},
],
},

// pulgins的插件
plugins: [
// 详细plugins的配置
],

// 模式
mode: "development", // 测试模式,开发模式
};
  1. 然后再当前项目下,打开终端,输入webpack进行打包

你需要注意:

  • loader的配置中,不同文件格式必须配置不同loader处理,其中use 数组中插件的执行顺序:从右到左,从下到上,以这个为例,先执行css-loader,然后执行style-loader

打包 HTML

  • 打包 HTML 需要一个名为html-webpack-pluginplugin
  • 首先创建并编写在webpack.config.js文件
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
/*
webpack.config.js
loader:
1下载
2.使用 配置loader
plugins:
1. 下载 在文件夹下打开终端 npm i html-webpack-plugin -D
2. 引入
3. 使用
*/
const { resolve } = require("path");

// 这是一个构造函数
const HtmlWebpaclPlugin = require("html-webpack-plugin");

module.exports = {
entry: "./src/index.js",
output: {
filename: "bulit.js",
path: resolve(__dirname, "build"),
},
module: {
rules: [
// loader 的配置
],
},
plugins: [
// 默认会创建一个空的html,自动引入打包输出的所有资源
// 所以就不需要自己手动引入了,手动引入反而出错
// 需求: 需要有结构的html问价
new HtmlWebpaclPlugin({
// 复制 ./src/index.html 文件
template: "./src/index.html",
}),
],
mode: "development",
};

打包图片文件

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
38
39
40
41
42
43
44
45
46
47
48
49
// webpack.config.js
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/index.js",
output: {
filename: "bulit.js",
path: resolve(__dirname, "build"),
},
module: {
rules: [
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
// 问题:处理不了 html中的图片
test: /\.(jpg|png|gif)$/,

// 需要下载两个包 url-loader file-loader
// cnpm i url-loader file-loader
// 如果用到一个loader可以这么写,前面并不是use
loader: "url-loader",
options: {
// 图片大小小于8kb,就会被base64处理
// 优点: 减少请求数量(减轻服务器压力)
// 缺点: 图片体积会更大(文件请求速度更慢)
limit: 8 * 1024,
esModule: false,
// 给图片进行重命名
// 取图片hash值的前十位
// ext取图片的原扩展名
name: "[hash:10].[ext]",
},
},
{
test: /\.html$/,
// html-loader是 专门处理html 中的 img的
loader: "html-loader",
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: `./src/index.html`,
}),
],
mode: "development",
};

打包其他资源

  • 打包其他的资源需要把 处理完的格式给排除掉exclude
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
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
entry: "./src/index.js",
output: {
filename: "built.js",
path: resolve(__dirname, "build"),
},
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
// 打包其他资源(除了html/js/css资源以外的资源)
{
// 排除css/js/html资源
exclude: /\.(css|js|html|less)$/,
loader: "file-loader",
options: {
name: "[hash:10].[ext]",
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html",
}),
],
mode: "development",
};

devServer 热打包

  • 实时打包
  • 开发服务器 devServer:用来自动化编译
  • 需要先安装包 cnpm i webpack-dev-server -D
  • 然后在启动命令npx webpack-dev-server
  • 特点:只会在内存中编译打包,不会有任何输出,就是没有bulid
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
38
39
40
41
42
43
44
45
46
47
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
entry: "./src/index.js",
output: {
filename: "built.js",
path: resolve(__dirname, "build"),
},
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
// 打包其他资源(除了html/js/css资源以外的资源)
{
// 排除css/js/html资源
exclude: /\.(css|js|html|less)$/,
loader: "file-loader",
options: {
name: "[hash:10].[ext]",
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html",
}),
],
mode: "development",

// 开发服务器 devServer:用来自动化(自动编译,自动打开浏览器,自动刷新浏览器~~)
// 特点:只会在内存中编译打包,不会有任何输出
// 启动devServer指令为:npx webpack-dev-server
devServer: {
// 项目构建后路径
contentBase: resolve(__dirname, "build"),
// 启动gzip压缩
compress: true,
// 端口号
port: 3000,
// 自动打开浏览器
open: true,
},
};

开发环境配置

  • 所有资源的总处理
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/*
开发环境配置:能让代码运行
运行项目指令:
webpack 会将打包结果输出出去
npx webpack-dev-server 只会在内存中编译打包,没有输出
*/

const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
entry: "./src/js/index.js",
output: {
filename: "js/built.js",
path: resolve(__dirname, "build"),
},
module: {
rules: [
// loader的配置
{
// 处理less资源
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
// 处理css资源
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
// 处理图片资源
test: /\.(jpg|png|gif)$/,
loader: "url-loader",
options: {
limit: 8 * 1024,
name: "[hash:10].[ext]",
// 关闭es6模块化
esModule: false,
outputPath: "imgs",
},
},
{
// 处理html中img资源
test: /\.html$/,
loader: "html-loader",
},
{
// 处理其他资源
exclude: /\.(html|js|css|less|jpg|png|gif)/,
loader: "file-loader",
options: {
name: "[hash:10].[ext]",
outputPath: "media",
},
},
],
},
plugins: [
// plugins的配置
new HtmlWebpackPlugin({
template: "./src/index.html",
}),
],
mode: "development",
devServer: {
contentBase: resolve(__dirname, "build"),
compress: true,
port: 3000,
open: true,
},
};

我遇到的错误排查

M1:配置文件的名字

  • 配置文件的名字叫webpack.config.js,我写成了webpack-config.js,中间那个是点,不是-,报如下的错误
1
2
3
4
5
6
7
8
9
10
11
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

ERROR in ./src/index.css 1:9
Module parse failed: Unexpected token (1:9)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> html,body{
| margin: 0;
| padding: 0;
@ ./src/index.js 2:0-20

use 中插件的顺序

  • use 中插件的使用顺序是从下到上,从右往左
  • 使用的顺序错误会报如下的错误
1
2
3
4
5
6
7
8
9
10
11
12
ERROR in ./src/index.css
Module build failed (from ../node_modules/[email protected]@css-loader/dist/cjs.js):
CssSyntaxError

(1:1) Unknown word

> 1 | var api = require("!../../node_modules/[email protected]@style-loader/dist/runtime/injectStylesIntoStyleTag.js");
| ^
2 | var content = require("!!./index.css");
3 |

@ ./src/index.js 2:0-20