webpack是目前web前端最流行的项目管理工具,它的概念繁多配置繁琐但功能及其强大可以应对各种项目管理需求。

webpack4是webpack一个大的升级,自带一些默认设置项一些之前可以使用的插件也不在兼容。本文记录webpack4下主要会用到的模块和插件。

webpack核心功能是前端Javascript代码的模块管理,而对于css,png等其它类型的文件处理,是通过loader调用第三方提供的处理库。webpack4核心模块有:Entry,Output,Module,Optimization,Plugins,Mode

1
$ yarn add -D webpack  webpack-cli

Entry

entry用于配置项目入口文件。它支持的类型有:string | [string] | object { <key>: string | [string] } | (function: () => string | [string] | object { <key>: string | [string] })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// object模式
module.exports = {
entry: {
home: "./home.js",
about: "./about.js",
contact: "./contact.js"
}
}

// string模式
module.exports = {
entry: './app.js'
}

// [string]模式
module.exports = {
entry:['./home.js','./about.js']
}

// () =>模式
module.exports = {
entry: () => './demo'
}

如果传入的是 string[string]则输出文件名chunk是main

Output

output用于配置项目输出信息。你可以设定:输出文件目录,输出文件名,外部资源链接等。

output.filename

设定输出文件名。可以使用webpack提供的模板:

模板 描述
[hash] 模块标识的hash值
[chunkhash] 模块内容的hash值
[name] 模块名称(根据entry输入类型)
[id] 模块标识
[query] 模块的 query,例如,文件名 ? 后面的字符串

[hash]和[chunkhash]可以指定值长度,例如:[hash:16]。默认长度为20。

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
module.exports = {
//...
output: {
filename: 'bundle.js'
}
};

module.exports = {
//...
output: {
filename: '[name].bundle.js'
}
};

module.exports = {
//...
output: {
filename: '[id].bundle.js'
}
};

module.exports = {
//...
output: {
filename: '[name].[hash].bundle.js'
}
};

module.exports = {
//...
output: {
filename: '[chunkhash].bundle.js'
}
};

output.chunkFilename

设置为入口文件的输出名,它的配置模板和output.filename一样。默认值是[id].js。

output.path

指定项目输出路径,必须是绝对路径。

1
2
3
4
module.exports = {
//...
path: path.resolve(__dirname, 'dist/assets')
};

output.publicPath

为项目中所有资源(js,css,img等资源)指定一个基础路径。添加publicPath后静态资源打包后的路径是:

1
静态资源最终访问路径 = output.publicPath + 资源loader或插件等配置路径

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
output.publicPath = '/dist/'

// image
options: {
name: 'img/[name].[ext]?[hash]'
}

// 最终图片的访问路径为
output.publicPath + 'img/[name].[ext]?[hash]' = '/dist/img/[name].[ext]?[hash]'

// js output.filename
output: {
filename: '[name].js'
}
// 最终js的访问路径为
output.publicPath + '[name].js' = '/dist/[name].js'

// extract-text-webpack-plugin css
new ExtractTextPlugin({
filename: 'style.[chunkhash].css'
})
// 最终css的访问路径为
output.publicPath + 'style.[chunkhash].css' = '/dist/style.[chunkhash].css'

一般情况下publicPath应该以’/‘结尾,而其他loader或插件的配置不要以’/‘开头

Module

Module用于指定处理不同类型文件的方式。例如,项目中的css,fonts,png等处理方式需要在该模块指定处理方式。

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
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const isProduction = (process.env.NODE_ENV === 'production');
module.exports = {
//...
module: {
rules: [{ // rules装载需要处理的类型文件
test: /\.tsx?$/, // 如果文件后缀是 .ts/.tsx结尾的文件,通过 ts-loaser加载器处理
loader: [
'ts-loader',
],
include: path.resolve('src'), // 指定需要匹配文件所在的文件目录
exclude: /node_modules/
},
{
test: /\.css$/, // 指定处理.css 文件加载器
use: [!isProduction ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
],
},
{
test: /\.(eot|svg|ttf|woff|woff2|TTF|otf)(\?\S*)?$/, // 指定处理字体 文件加载器
loader: 'file-loader',
options: {
name: '[name].[ext]'
}
},
{
test: /\.(png|jpe?g|gif|svg)(\?\S*)?$/, // 指定处理 图片加载器
loader: 'url-loader',
query: {
limit: 1000,
name: '[name].[ext]'
}
}
]
}
};

针对不同的类型文件webpack生态都有针对的处理加载器可以方便和项目相融合。

加载器的配置是webpack部分最难懂。好在现在主流的前端技术框架 Vue,React都提供了一键式开发环境配置工具vue-clicreate-react-app

Mode

webpack4提供对项目优化的默认配置,这些配置可以在optimization可以再定制。而optimization中有些配置项的值 是根据mode值而定的。

mode是webpack4最新引入的模块,用于告诉webpage打包用以的环境(开发环境或生产环境)。

mode可以有三个可选值:productiondevelopment ,none

1
2
3
4
5
module.exports = {
mode: 'production'
};

// 也可以用命令行只当mode webpack --mode=production
操作 描述
development process.env.NODE_ENVDefinePlugin的值设置为development。并启用NamedChunksPlugin, NamedModulesPlugin
production process.env.NODE_ENVDefinePlugin的值设置为production。并启用 FlagDependencyUsagePluginFlagIncludedChunksPluginModuleConcatenationPluginNoEmitOnErrorsPluginOccurrenceOrderPluginSideEffectsFlagPlugin and UglifyJsPlugin.
none 关闭optimization中的所有优化。

Optimization

webpack4 提供了根据 mode值针对项目优化的默认配置。而这些配置是在optimization设定的,根据项目可以自定义这些配置。

optimization.minimize

mode值为production时,并且optimization.minimizetrue。webpack会调用UglifyjsWebpackPlugin压缩文件。

你可以在optimization.minimizer自定义UglifyjsWebpackPlugin

1
2
3
4
5
6
7
8
9
10
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

module.exports = {
//...
optimization: {
minimizer: [
new UglifyJsPlugin({ /* your config */ })
]
}
};

optimization.splitChunks

webpack4中切分公用模块的配置项。默认配置如下:

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
module.exports = {
//...
optimization: {
splitChunks: {
chunks: 'async',// 指定那些模块会被优化 他可以接收三字符串值:all(所有chunk都会被优化),async(异步加载的chunk被优化),initial(初始的chunk被优化) 。你还可以传递function 指定那些模块被优化或不被优化
minSize: 30000,// 生产chunk最小字节
maxSize: 0,
minChunks: 1, // 分割前被共享的最少次数
maxAsyncRequests: 5,// 按需加载时的最大并行请求数
maxInitialRequests: 3, // 项目入口文件最大请求次数
automaticNameDelimiter: '~',
name: true,// 切块的名字 ,true 表示自定生产一个名字
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
};

Plugins

plugins模块通过第三方插件实现对项目的定制话配置。

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 webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
var DashboardPlugin = require('webpack-dashboard/plugin');
const isProduction = (process.env.NODE_ENV === 'production');
module.exports = {
//....
plugins:[
new MiniCssExtractPlugin({
filename: !isProduction ? '[name].css' : '[name].[hash].css',
chunkFilename: !isProduction ? '[id].css' : '[id].[hash].css',
}),
new webpack.optimize.ModuleConcatenationPlugin(),
new webpack.LoaderOptionsPlugin({
minimize: true
}),
new DashboardPlugin(),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
template: path.join(__dirname, 'template.html'),
filename: 'index.html',
hash: false,
minify: {
removeAttributeQuotes: isProduction
}
}),
]
}

DevServer

通过webpack-dev-server我们可以在webpack中使用devServer模块。该模块可以启动一个node服务器方便我们在开发时及时预览页面效果。

通过webpack-dev-server --mode development --inline --hot --color 命令启用devServer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module.exports = {
//...
devServer: {
hot: true,
historyApiFallback: true,
compress: true,
open: true,
port: 8008,// node服务器 监听端口
publicPath: "/"
index: 'index.htm'// 自动打开首页 文件名
proxy: { // 将请求接口 代理之后端
"/api": "http://localhost:3000"
}
}
}