引用字体图片和 svg 图片

字体图标和 svg 图片都可以通过 file-loader 来解析

1
2
3
4
5
6
7
8
9
10
module.exports = {
module: {
rules: [
{
test: /\.(eot|ttf|woff|svg)$/,
use: 'file-loader'
}
]
}
}

这样即使样式中引入了这类格式的图标或者图片都没有问题了,img 如果也引用 svg 格式的话,配合上面写好的 html-withimg-loader 就都没有问题了

添加 CSS3 前缀

通过 postcss 中的 autoprefixer 可以实现将 CSS3 中的一些需要兼容写法的属性添加响应的前缀,这样省去我们不少的时间

由于也是一个 loader 加载器,我们也需要先安装一下

1
npm i postcss-loader autoprefixer -D

安装后,我们还需要像 webpack 一样写一个 config 的配置文件,在项目根目录下创建一个 postcss.config.js 文件,配置如下:

1
2
3
module.exports = {
plugins: [require('autoprefixer')] // 引用该插件即可了
}

然后在 webpack 里配置 postcss-loader

1
2
3
4
5
6
7
8
9
10
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader', 'postcss-loader']
}
]
}
}

转义 ES6

在实际开发中,我们在大量的使用着 ES6 及之后的 api 去写代码,这样会提高我们写代码的速度,不过由于低版本浏览器的存在,不得不需要转换成兼容的代码,于是就有了常用的 Babel 了

Babel 会将 ES6 的代码转成 ES5 的代码

那么不再多说,既然要使用它,就先来安一下

1
npm i babel-core babel-loader babel-preset-env babel-preset-stage-0 -D

当把这些都安好后,我们就开始配置,由于要兼容的代码不仅仅包含 ES6 还有之后的版本和那些仅仅是草案的内容,所以我们可以通过一个.babelrc 文件来配置一下,对这些版本的支持

.babelrc

1
2
3
{
"presets": ["env", "stage-0"] // 从右向左解析
}

我们再在 webpack 里配置一下 babel-loader 既可以做到代码转成 ES5 了

1
2
3
4
5
6
7
8
9
10
11
12
module.exports = {
module: {
rules: [
{
test:/\.js$/,
use: 'babel-loader',
include: /src/, // 只转化 src 目录下的 js
exclude: /node_modules/ // 排除掉 node_modules,优化打包速度
}
]
}
}

在我们每次 npm run build 的时候都会在 dist 目录下创建很多打好的包,如果积累过多可能也会混乱, 所以应该在每次打包之前将 dist 目录下的文件都清空,然后再把打好包的文件放进去

这里提供一个 clean-webpack-plugin 插件

1
npm i clean-webpack-plugin -D

1
2
3
4
5
6
7
8
let CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
plugins: [
// 打包前先清空
new CleanWebpackPlugin('dist')
]
}

启动静态服务器

启动一个静态服务器,默认会自动刷新,就是说你对 html,css,js 文件做了修改并保存后,浏览器会默认刷新一次展现修改后的效果

正常情况下我们都是在开发环境中开发项目,所以之前配置的脚本”dev”可以派上用场了,在执行 npm run dev 命令后,会启动静态服务器,我们访问 localhost:3000 端口就可以看到开发的页面内容了

如果 devServer 里 open 设为 true 后,会自动打开浏览器

1
2
3
4
5
6
7
8
9
module.exports = {
devServer: {
contentBase: './dist',
host: 'localhost', // 默认是 localhost
port: 3000, // 端口
open: true, // 自动打开浏览器
hot: true // 开启热更新
}
}

当然在 npm run dev 命令下,打包的文件存在于内存中,并不会产生在 dist 目录下
热更新和自动刷新的区别

在配置 devServer 的时候,如果 hot 为 true,就代表开启了热更新,
But 这并没那么简单,因为热更新还需要配置一个 webpack 自带的插件并且还要在主要 js 文件里检查是否有 module.hot

下面就让我们直接看下代码是如何实现的

// webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
let webpack = require('webpack');

module.exports = {
plugins: [
// 热更新,热更新不是刷新
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './dist',
hot: true,
port: 3000
}
}

此时还没完虽然配置了插件和开启了热更新,但实际上并不会生效

1
2
3
4
5
6
7
8
9
10
// index.js
let a = 'hello world';
document.body.innerHTML = a;
console.log('这是 webpack 打包的入口文件');

// 还需要在主要的 js 文件里写入下面这段代码
if (module.hot) {
// 实现热更新
module.hot.accept();
}

以上 index.js 中的内容,如果将变量 a 的值进行修改保存后,会在不刷新页面的情况下直接修改掉,这样就实现了热更新

那么热更新从现在看来和自动刷新浏览器的区别也不是太大嘛!自动刷新也是可以接受的啊

其实不然,热更新的好处可能在 vue 或者 react 中有更大的发挥,其中某一个组件被修改的时候就会针对这个组件进行热更新了,这里用到 vue 或 react 的同学去实际体验一下吧

resolve 解析

在 webpack 的配置中,resolve 我们常用来配置别名和省略后缀名

1
2
3
4
5
6
7
8
9
10
module.exports = {
resolve: {
// 别名
alias: {
$: './src/jquery.js'
},
// 省略后缀
extensions: ['.js', '.json', '.css']
},
}

这个配置在 webpack 中比较简单,我们也就不再叙述了,下面来看点干货

提取公共代码

在 webpack4 之前,提取公共代码都是通过一个叫 CommonsChunkPlugin 的插件来办到的。到了 4 以后,内置了一个一模一样的功能,而且起了一个好听的名字叫“优化”

下面我们就来看看如何提取公共代码
// 假设 a.js 和 b.js 都同时引入了 jquery.js 和一个写好的 utils.js
// a.js 和 b.js

1
2
import $ from 'jquery';
import {sum} from 'utils';

那么他们两个 js 中其中公共部分的代码就是 jquery 和 utils 里的代码了
可以针对第三方插件和写好的公共文件

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
module.exports = {
entry: {
a: './src/a.js',
b: './src/b.js'
},
output: {
filename: '[name].js',
path: path.resolve('dust')
},
// 提取公共代码
optimization: {
splitChunks: {
cacheGroups: {
vendor: { // 抽离第三方插件
test: /node_modules/, // 指定是 node_modules 下的第三方包
chunks: 'initial',
name: 'vendor', // 打包后的文件名,任意命名
// 设置优先级,防止和自定义的公共代码提取时被覆盖,不进行打包
priority: 10
},
utils: { // 抽离自己写的公共代码,utils 这个名字可以随意起
chunks: 'initial',
name: 'utils', // 任意命名
minSize: 0 // 只要超出 0 字节就生成一个新包
}
}
}
},
plugins: [
new HtmlWebpackPlugin({
filename: 'a.html',
template: './src/index.html', // 以 index.html 为模板
chunks: ['vendor', 'a']
}),
new HtmlWebpackPlugin({
filename: 'b.html',
template: './src/index.html', // 以 index.html 为模板
chunks: ['vendor', 'b']
})]
}

通过以上配置,可以把引入到 a.js 和 b.js 中的这部分公共代码提取出来

本文地址 https://shaoshilei.com/2018-05/webpack4-0-1.html