Webpack 入门 2

也不能总是只搞 js 吧,我三剑客另两位呢?Webpack 其之二


点我下载本章代码

HTML 插件

首先先搞一个能看的页面出来

那当然是选择我们的 HTML

因为 webpack 只能把资源处理成 js,所以要想得到 HTML,我们就要使用 plugin

在官方文档的 plugin 中找到 html,发现有这么一个插件

html-webpack-plugin

点开之后可以得到其引导,让我们先安装它

1
npm install --save-dev html-webpack-plugin

该插件将为你生成一个 HTML5 文件, 其中包括使用 script 标签的 body 中的所有 webpack 包。

向 module.exports 写入字段 plugins,大致变为如下模样

1
2
3
4
5
6
7
8
9
10
11
12
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js'
},
plugins: [new HtmlWebpackPlugin()]
};

然后试试构建!

可以发现 dist 目录下产生了新的 js 和一个 html,并为这个 html 自动绑定了 js

但是这个页面也太白板了,能不能指定一些个性化设置呢

查看 插件文档 可以发现有这么一段代码

1
2
3
4
5
6
plugins: [
new HtmlWebpackPlugin({
title: 'My App',
filename: 'assets/admin.html'
})
]

抄进来试试构建!

发现 dist 目标文件夹变成了这样

可以看到 title 被我们成功定制了,但是路径错了?!为什么多了一个 assets??

我们发现配置中有 assets 的部分是 filename 字段,想到之前配置中的 output 也有 filename 字段,是指示输出的文件名用的,所以结合构建结果来看插件中的配置应该也同理

但是这样还是太单薄了,能不能再丰富一点?

HTML 模板

答案是可以!

继续查看插件文档,有一个地方的代码引起了我们的注意

1
2
3
4
5
6
7
plugins: [
new HtmlWebpackPlugin(), // Generates default index.html
new HtmlWebpackPlugin({ // Also generate a test.html
filename: 'test.html',
template: 'src/assets/test.html'
})
]

注释是说,如果配置了两个 HtmlWebpackPlugin 实例,那么两个实例都会被构建

其中第二个实例指定了一个新字段,template,翻译是模板,那我们可以猜测这个东西是指示入口 html 文件的

正好我们目录下有个 index.html,个性化一下先

然后指定 template 的路径到这个 html

1
2
3
4
5
6
7
plugins: [
new HtmlWebpackPlugin({
title: 'My App',
filename: 'index.html',
template: 'index.html'
})
]

然后再构建一下,发现 dist 结果现在变成了这样

虽然构建成功了,自动使用我们提供的模板,并引入了 main.js

但是我们配置的 title 没有覆盖模板的 title,并且里面自带的 index.js 还留着

可以猜测配置多余的 title 是没用的,并且不应该自带 js

现在去掉模板里的 title 和 js 引用再试试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang="zh">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>

<body>
<div id="app">
<ol>
<li>1</li>
<li>2</li>
</ol>
</div>
</body>

</html>

构建!

得到的新 dist 变成这样

虽然 js 确实自动插进去了,但是……我的 title 呢!!!

怎么办怎么办,看看插件文档吧

正好下一节就提出了一个类似 jsp 的语法

<%= htmlWebpackPlugin.options.title %>

将这个语句写在模板中,可以在构建的时候自动获取配置中的 title

来试试

构建!

发现成功插入了新的 title!可以推知其它配置也可以采用类似的方法

css loader

但是这样的页面好丑……我要加 CSS

看看插件文档怎么说的

直接在插件文档中搜 css

发现官方文档里这么说

If you have any CSS assets in webpack’s output (for example, CSS extracted with the mini-css-extract-plugin) then these will be included with <link> tags in the HTML head.

意思就是如果要 CSS,你去用 mini-css-extract-plugin 吧

这也太麻烦了,我想简单点,回头看看 webpack 文档

在指南中的 加载 CSS 章节发现了这么一段

先安装,然后把配置抄过来看看

然后加个 style.css

1
2
3
ol{
background-color: red;
}

在 index.js 中引入这个 css

1
2
3
4
![webpack-2-8](https://pic.ringoer.com/webpack-2-8.png)import './style.css'

let string = 'hello'
console.log(string)

试试构建,完成后用 file 协议打开 index.html 看看

发现成功引入了 css,而且自动化作 style 标签插在了 document.head 中

此时的 main.xxx.js 变成了复杂的一大串 js 代码,这其实就是 loader 的效果——将其它内容转换为 js

查看配置,发现用到了两个 loader,根据名称,我们可以推测,任何以 .css 结尾的文件,都会通过 test 的测试,然后从后向前依次调用 loader处理

先调用 css-loader 将 css 内容转化为 webpack 能理解的 js 内容,再调用 style-loader 将 js 内容中的样式部分化作 style 标签插入到 document.head 上

那如果我有多个 css 呢?试试看!

新建一个 style2.css

1
2
3
ol{
color: white;
}

然后在 index.js 中引入它

1
2
3
4
5
import './style.css'
import './style2.css'

let string = 'hello'
console.log(string)

然后构建!刷新页面发现变成了这样

多个 css 文件会化作多个 style 标签被插入

css 抽取

但是如果我 css 多了,插作 style 标签的话,不方便管理,也会加大页面代码冗余

能不能抽成 css 文件呢?可以!

我们知道 webpack 基本功能是提取内容变为 js,刚才的 loader 也是这个功能,那现在要提取作非 js 的 css 文件了,肯定需要的是 plugin

想起刚才 html 的时候,他让我们去用 mini-css-extract-plugin,那我们就去看看

先安装这个插件

npm install --save-dev mini-css-extract-plugin

然后我们发现了这么一段代码

1
2
3
4
5
6
7
8
9
10
11
12
13
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
plugins: [new MiniCssExtractPlugin()],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-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
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js'
},
plugins: [
new HtmlWebpackPlugin({
title: 'My App',
filename: 'index.html',
template: 'index.html'
}),
new MiniCssExtractPlugin()
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
}
]
}
};

然后好像没说什么别的了,试试构建吧

构建之后发现!!js 文件变简单了,css 也自动抽成了 main.css,还自动在 index.html 中引入了

不过为什么仅仅是 main.css?我的哈希呢?

根据之前猜测的 filename 指示输出文件名,来试试修改配置

将 plugins 中的 filename 改成如下模样,再试试构建

1
2
3
4
5
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css'
})
]

得到了如下结果

现在我们的 CSS 也有每次不同的文件名了!并且也不再依赖于 js 的引入

下集预告

更多其它的内容怎么办呢?只有三剑客可不足以撑起现代互联网!

点我查看下集


感谢阅读

--It's the end.Thanks for your read.--