目录
五、插件plugins
5.1、插件概要
Plugin 是用来扩展 Webpack 功能的,通过在构建流程里注入钩子实现,它给 Webpack 带来了很大的灵活性。
插件是 webpack 的支柱功能。webpack 自身也是构建于,你在 webpack 配置中用到的相同的插件系统之上!插件目的在于解决 loader 无法实现的其他事。
webpack 插件是一个具有 apply 属性的 JavaScript 对象。apply 属性会被 webpack compiler 调用,并且 compiler 对象可在整个编译生命周期访问。
[](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">ConsoleLogOnBuildWebpackPlugin.js
const pluginName = 'ConsoleLogOnBuildWebpackPlugin';
class ConsoleLogOnBuildWebpackPlugin {
apply(compiler) {
compiler.hooks.run.tap(pluginName, compilation => {
console.log("webpack 构建过程开始!");
});
}
}</pre>
](javascript:void(0); "复制代码")
compiler hook 的 tap 方法的第一个参数,应该是驼峰式命名的插件名称。建议为此使用一个常量,以便它可以在所有 hook 中复用。
由于插件可以带参数/选项,你必须在 webpack 配置中,向 plugins 属性传入 new 实例。
根据你的 webpack 用法,这里有多种方式使用插件。
[](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin'); //通过 npm 安装
const webpack = require('webpack'); //访问内置的插件
const path = require('path');
const config = {
entry: './path/to/my/entry/file.js',
output: {
filename: 'my-first-webpack.bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /.(js|jsx)$/,
use: 'babel-loader' }
]
},
plugins: [ new webpack.optimize.UglifyJsPlugin(), new HtmlWebpackPlugin({template: './src/index.html'})
]
};
module.exports = config;</pre>
[](javascript:void(0); "复制代码")
5.1、HTML Webpack Plugin(创建HTML插件)
该个插件的作用是用来自动生成html页面,既可以生成单个页面又可以生成多个页面,并且在生成前可以给它一些的配置参数,它会按照你想要的生成方式去生成页面。
第一步:安装
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">npm i html-webpack-plugin -D</pre>
第二步:在webpack.config.js里引入模块
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">const HtmlWebpackPlugin=require('html-webpack-plugin');</pre>
第三步:在webpack.config.js中的plugins对象里new一个实例
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">plugins:[ new HtmlWebpackPlugin({参数})
]</pre>
结果
[](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: 'index.js',
output: {
path: __dirname + '/dist',
filename: 'index_bundle.js' },
plugins: [ new HtmlWebpackPlugin()
]
}</pre>
](javascript:void(0); "复制代码")
参数:
title
生成页面的titile
元素
filename
生成的html文件的文件名。默认index.html
,可以直接配置带有子目录
](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">//webpack.config.js
...
plugins: [ new HtmlWebpackPlugin({
...
filename: 'index1.html'//可带子目录'html/index1.html'
})
]</pre>
](javascript:void(0); "复制代码")
template
模版文件路径
templateParameters
{Boolean|Object|Function}
允许覆盖模板中使用的参数
](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">//webpack.config.js
...
plugins: [ new HtmlWebpackPlugin({
...
templateParameters: {
title: 'xxxx',
favicon: './favicon/index.ico',
}
})
]</pre>
](javascript:void(0); "复制代码")
inject
插入的script
插入的位置,四个可选值:
true
: 默认值,script
标签位于html
文件的body
底部
body
: 同true
head
: script
标签位于html
文件的head
标签内
false
: 不插入生成的js
文件,只是生成的html
文件
favicon
为生成的html
文件生成一个favicon
,属性值是路径
minify
对html
文件进行压缩。属性值是false
或者压缩选项值。默认false
不对html
文件进行压缩。
html-webpack-plugin
中集成的html-minifier
,生成模板文件压缩配置,有很多配置项,这些配置项就是minify
的压缩选项值。
hash
给生成的js
文件尾部添加一个hash
值。这个hash
值是本次webpack
编译的hash
值。默认false
;
](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">//webpack.config.js
...
plugins: [ new HtmlWebpackPlugin({
...
hash: true })
] //html
<script type="text/javascript" src="bundle.js?59a5ed17040d94df87fe">
//59a5ed17040d94df87fe是本次webpack编译的hash值</pre>
](javascript:void(0); "复制代码")
cache
Boolean
类型。只在文件被修改的时候才生成一个新文件。默认值true
showErrors
Boolean
类型。错误信息是否写入html
文件。默认true
chunks
在html
文件中引用哪些js
文件,用于多入口文件时。不指定chunks时,所有文件都引用
](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">//webpack.config.js
entry: {
index1: path.resolve(__dirname, './index1.js'),
index2: path.resolve(__dirname, './index2.js'),
index3: path.resolve(__dirname, './index3.js')
}
...
plugins: [ new HtmlWebpackPlugin({
...
chunks: [index1, index2]//html文件中只引入index1.js, index2.js
})
]</pre>
](javascript:void(0); "复制代码")
excludeChunks
与chunks相反,html
文件不引用哪些js
文件
](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">//webpack.config.js
entry: {
index1: path.resolve(__dirname, './index1.js'),
index2: path.resolve(__dirname, './index2.js'),
index3: path.resolve(__dirname, './index3.js')
}
...
plugins: [ new HtmlWebpackPlugin({
...
excludeChunks: [index3.js]//html文件中不引入index3.js
})
]</pre>
](javascript:void(0); "复制代码")
chunksSortMode
控制script
标签的引用顺序。默认五个选项:
none
: 无序
auto
: 默认值, 按插件内置的排序方式
dependency
: 根据不同文件的依赖关系排序
manual
: chunks按引入的顺序排序, 即属性chunks的顺序
{Function}
: 指定具体的排序规则
xhtml
Boolean
类型,默认false
, true
时以兼容xhtml
的模式引用文件
示例:
[](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">plugins:[ new HtmlWebpackPlugin({
title:'Hello app', /这个值对应html里的title/ template:'./src/template.html', //模板文件地址
filename:'test1.html', //文件名,默认为index.html(路径相对于output.path的值)
inject:true, //script标签的位置,true/body为在</body>标签前,head为在<head>里,false表示页面不引入js文件
hash:true, //是否为引入的js文件添加hash值
chunks:['one'], //页面里要引入的js文件,值对应的是entry里的key。省略参数会把entry里所有文件都引入
//excludeChunks:['one'],//页面里不能引入的js文件,与chunks刚好相反
minify:{ //html-webpack-plugin内部集成了html-minifier
collapseWhitespace:true, //压缩空格
removeAttributeQuotes:true, //移除引号
removeComments:true, //移除注释
},
}), //生成两个文件,分别引入两个js文件(现在是一个文件里引入了两个js)
new HtmlWebpackPlugin({
title:'kaivon',
template:'./src/template.html',
hash:true,
filename:'test2.html',
chunks:['two']
})
]</pre>
](javascript:void(0); "复制代码")
示例1:
webpack.config03.js配置文件
[](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">//webpack配置文件
//导入用于生成html的插件
const HtmlWebpackPlugin=require("html-webpack-plugin"); //依赖node中的path模块
var path=require('path'); //定义一个默认模块对象
module.exports={
entry:{app01:"./src/app03.js"}, //设置输出结果
output: { //路径,将相对路径转绝对路径
path:path.resolve(__dirname,'dist'), //文件,[name]是模块名称,占位
filename: "[hash:8].bundle.js" },
module: {
},
plugins: [ //创建一个插件对象,并指定参数
new HtmlWebpackPlugin({ //指定生成的文件路径与名称
filename:"../app03.html", //标题
title:"Hello App03!" })
]
};</pre>
](javascript:void(0); "复制代码")
arc/app03.js
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">alert("Hello App03!");</pre>
打包结果:
运行:
示例2:
webpack.config03.js配置文件
[](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">//webpack配置文件
//导入用于生成html的插件
const HtmlWebpackPlugin=require("html-webpack-plugin"); //依赖node中的path模块
var path=require('path'); //定义一个默认模块对象
module.exports={
entry:{app01:"./src/app03.js"}, //设置输出结果
output: { //路径,将相对路径转绝对路径
path:path.resolve(__dirname,'dist'), //文件,[name]是模块名称,占位
filename: "[hash:8].bundle.js" },
module: {
},
plugins: [ //创建一个插件对象,并指定参数
new HtmlWebpackPlugin({ //指定生成的文件路径与名称
filename:"../app03.html", //标题
title:"Hello App03!", //指定模板
template:"./templates/tmpl03.html", //模板参数,允许覆盖templates中的参数
templateParameters:{
content:"Hello templateParameters!", //重写title
title:"Hello App03 title!",
key:"value" },
minify:{
removeComments:true, //移除注释
collapseWhitespace:true, //折叠空格
//更新请参数https://github.com/kangax/html-minifier#options-quick-reference
}
})
]
};</pre>
](javascript:void(0); "复制代码")
/templates/tmpl03.html 模板文件
View Code
生成结果:
5.2、Mini-css-extract-plugin(单独提取CSS插件)
将CSS提取为独立的文件的插件,对每个包含css的js文件都会创建一个CSS文件,支持按需加载css和sourceMap
默认情况下css是被js注入的一段style,如下所示:
只能用在webpack4中,对比另一个插件 extract-text-webpack-plugin特点:
- 异步加载
- 不重复编译,性能更好
- 更容易使用
- 只针对CSS
目前缺失功能,HMR(热模块替换)。
HMR解释
安装:
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">npm install --save-dev mini-css-extract-plugin</pre>
使用:
[](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [ new MiniCssExtractPlugin({ // 类似 webpackOptions.output里面的配置 可以忽略
filename: '[name].css',
chunkFilename: '[id].css',
}),
],
module: {
rules: [
{
test: /.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: { // 这里可以指定一个 publicPath
// 默认使用 webpackOptions.output中的publicPath
publicPath: '../' },
}, 'css-loader',
],
}
]
}
}</pre>
](javascript:void(0); "复制代码")
高级配置:
这个插件应该只用在 production 配置中,并且在loaders链中不使用 style-loader, 特别是在开发中使用HMR,因为这个插件暂时不支持HMR
[](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const devMode = process.env.NODE_ENV !== 'production';
module.exports = {
plugins: [ new MiniCssExtractPlugin({
filename: devMode ? '[name].css' : '[name].[hash].css',
chunkFilename: devMode ? '[id].css' : '[id].[hash].css',
})
],
module: {
rules: [
{
test: /.(sa|sc|c)ss$/,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader',
],
}
]
}
}</pre>
](javascript:void(0); "复制代码")
示例:
webpack.config03.js
[](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">//webpack配置文件
//导入用于生成html的插件
const HtmlWebpackPlugin=require("html-webpack-plugin"); //导入用于提取css的插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); //依赖node中的path模块
var path=require('path'); //定义一个默认模块对象
module.exports={
entry:{app01:"./src/app03.js"}, //设置输出结果
output: { //路径,将相对路径转绝对路径
path:path.resolve(_dirname,'dist'), //文件,[name]是模块名称,占位
filename: "[hash:8].bundle.js" },
module: {
rules: [
{
test: /.scss$/,
use: [{
loader:MiniCssExtractPlugin.loader //提取css并link
}, {
loader: "css-loader" // 将 CSS 转化成 CommonJS 模块
}, {
loader: "sass-loader" // 将 Scss 编译成 CSS
}]
}
]
},
plugins: [ //创建一个插件对象,并指定参数
new HtmlWebpackPlugin({ //指定生成的文件路径与名称
filename:"../app03.html", //标题
title:"Hello App03!", //指定模板
template:"./templates/tmpl03.html", //模板参数,允许覆盖templates中的参数
templateParameters:{
content:"Hello templateParameters!", //重写title
title:"Hello App03 title!",
key:"value" },
minify:{
removeComments:true, //移除注释
collapseWhitespace:true, //折叠空格
//更新请参数https://github.com/kangax/html-minifier#options-quick-reference
}
}), //创建一个用于提取css的插件对象
new MiniCssExtractPlugin({
filename:"[name][hash:10].css",
chunkFilename:"[id]" })
]
};</pre>
](javascript:void(0); "复制代码")
src/app03.js
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">import '../css/baseScss.scss';
alert("Hello App03!");</pre>
打包生成的结果
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);"><!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Hello App03 title!</title>
<link href="dist/app01_1b7c11aa92.css" rel="stylesheet">
</head>
<body><h2>Hello templateParameters!</h2>
<script type="text/javascript" src="dist/1b7c11aa.bundle.js"></script>
</body>
</html></pre>
](javascript:void(0); "复制代码")
运行结果:
5.3、clean-webpack-plugin(删除或清理构建目录)
在用HtmlWebpackPlugin的时候时需要把dist目录删掉再去看生成的文件,clean-webpack-plugin这个插件就可以做这件事情
第一步:安装
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">npm i clean-webpack-plugin --save-dev</pre>
第二步:在webpack.config.js里引入模块
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">const CleanWebpackPlugin=require('clean-webpack-plugin');</pre>
第三步:在plugins的最前面创建清理对象
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">plugins:[ new CleanWebpackPlugin(['./dist']), //这个一定要放在最上面,作用是先删除dist目录再创建新的dist目录。里面的参数为要删除的目录,放在一个数组里面
...
]</pre>
在文件夹里打开dist所在的目录,并在终端里再次执行命令webpack后,会看到dist目录先被删除后又被创建。
关于clean-webpack-plugin插件的所有配置参数请参考:https://www.npmjs.com/package/clean-webpack-plugin
该插件有两个参数:
Paths ( 必须)
An [array] of string paths to clean
[](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">[ 'dist', // removes 'dist' folder
'build/.', // removes all files in 'build' folder
'web/*.js' // removes all JavaScript files in 'web' folder
]</pre>
](javascript:void(0); "复制代码")
[](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">{ // Absolute path to your webpack root folder (paths appended to this)
// Default: root of your package
root: __dirname, // Write logs to console.
verbose: true, // Use boolean "true" to test/emulate delete. (will not remove files).
// Default: false - remove files
dry: false, // If true, remove files on recompile.
// Default: false
watch: false, // Instead of removing whole path recursively,
// remove all path's content with exclusion of provided immediate children.
// Good for not removing shared files from build directories.
exclude: [ 'files', 'to', 'ignore' ], // allow the plugin to clean folders outside of the webpack root.
// Default: false - don't allow clean folder outside of the webpack root
allowExternal: false
// perform clean just before files are emitted to the output dir
// Default: false
beforeEmit: false }</pre>
](javascript:void(0); "复制代码")
示例:
[](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">const CleanWebpackPlugin = require('clean-webpack-plugin'); //installed via npm
const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm
const webpack = require('webpack'); //to access built-in plugins
const path = require('path'); // the path(s) that should be cleaned
let pathsToClean = [ 'dist', 'build' ] // the clean options to use
let cleanOptions = {
root: '/full/webpack/root/path',
exclude: ['shared.js'],
verbose: true,
dry: false } // sample WebPack config
const webpackConfig = {
entry: './path/to/my/entry/file.js',
output: {
filename: 'my-first-webpack.bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /.(js|jsx)$/,
loader: 'babel-loader' }
]
},
plugins: [ new CleanWebpackPlugin(pathsToClean, cleanOptions), new webpack.optimize.UglifyJsPlugin(), new HtmlWebpackPlugin({template: './src/index.html'})
]
}</pre>
](javascript:void(0); "复制代码")
示例:
webpack.config03.js
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">//webpack配置文件
//导入用于理清目录的插件
const CleanWebpackPlugin=require('clean-webpack-plugin'); //导入用于生成html的插件
const HtmlWebpackPlugin=require("html-webpack-plugin"); //导入用于提取css的插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); //依赖node中的path模块
var path=require('path'); //定义一个默认模块对象
module.exports={
entry:{app01:"./src/app03.js"}, //设置输出结果
output: { //路径,将相对路径转绝对路径
path:path.resolve(_dirname,'dist'), //文件,[name]是模块名称,占位
filename: "[hash:8].bundle.js" },
module: {
rules: [
{
test: /.scss$/,
use: [{
loader:MiniCssExtractPlugin.loader //提取css并link
}, {
loader: "css-loader" // 将 CSS 转化成 CommonJS 模块
}, {
loader: "sass-loader" // 将 Scss 编译成 CSS
}]
}
]
},
plugins: [ //创建一个清理插件,参数一为目标,如路径,参数二为选项
new CleanWebpackPlugin(['dist'],{dry:false}), //创建一个插件对象,并指定参数
new HtmlWebpackPlugin({ //指定生成的文件路径与名称
filename:"../app03.html", //标题
title:"Hello App03!", //指定模板
template:"./templates/tmpl03.html", //模板参数,允许覆盖templates中的参数
templateParameters:{
content:"Hello templateParameters!", //重写title
title:"Hello App03 title!",
key:"value" },
minify:{
removeComments:true, //移除注释
collapseWhitespace:true, //折叠空格
//更新请参数https://github.com/kangax/html-minifier#options-quick-reference
}
}), //创建一个用于提取css的插件对象
new MiniCssExtractPlugin({
filename:"[name][hash:10].css",
chunkFilename:"[id]" })
]
};</pre>
](javascript:void(0); "复制代码")
运行前:
运行后:
5.4、常用plugins
5.4.1、用于修改行为
- define-plugin:定义环境变量
-
context-replacement-plugin:修改
require
语句在寻找文件时的默认行为。 - ignore-plugin:用于忽略部分文件。
5.4.2、用于优化
- commons-chunk-plugin:提取公共代码
- extract-text-webpack-plugin:提取 JavaScript 中的 CSS 代码到单独的文件中
- prepack-webpack-plugin:通过 Facebook 的 Prepack 优化输出的 JavaScript 代码性能
- uglifyjs-webpack-plugin:通过 UglifyES 压缩 ES6 代码
- webpack-parallel-uglify-plugin:多进程执行 UglifyJS 代码压缩,提升构建速度。
- imagemin-webpack-plugin:压缩图片文件。
- webpack-spritesmith:用插件制作雪碧图。
- ModuleConcatenationPlugin:开启 Webpack Scope Hoisting 功能
- dll-plugin:借鉴 DDL 的思想大幅度提升构建速度
- hot-module-replacement-plugin:开启模块热替换功能。
5.4.3、其它
- serviceworker-webpack-plugin:给网页应用增加离线缓存功能
- stylelint-webpack-plugin:集成 stylelint 到项目中
- i18n-webpack-plugin:给你的网页支持国际化。
- provide-plugin:从环境中提供的全局变量中加载模块,而不用导入对应的文件。
- web-webpack-plugin:方便的为单页应用输出 HTML,比 html-webpack-plugin 好用。
六、DevServer开发服务器
webpack-dev-server就是一个基于Node.js和webpack的一个简易服务器。它在服务器端使用webpack-dev-middleware进行webpack构建打包;并在客户端注入一份runtime,用于接受服务器端的构建打包后信息。
在实际开发中我们可能会需要完成如下功能:
- 提供 HTTP 服务而不是使用本地文件预览;
- 监听文件的变化并自动刷新网页,做到实时预览;
- 支持 Source Map,以方便调试。
Webpack 原生支持上述第2、3点内容,再结合官方提供的开发工具 DevServer 也可以很方便地做到第1点。 DevServer 会启动一个 HTTP 服务器用于服务网页请求,同时会帮助启动 Webpack ,并接收 Webpack 发出的文件更变信号,通过 WebSocket 协议自动刷新网页做到实时预览。
6.1、快速开启DevServer
安装 DevServer:
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">npm i -D webpack-dev-server</pre>
安装成功后在项目的根目录下执行webpack-dev-server 命令, DevServer 服务器就启动了,这时你会看到控制台有一串日志输出:
Project is running at http://localhost:8080/
webpack output is served from /
现在就可以直接访问了
这意味着 DevServer 启动的 HTTP 服务器监听在 http://localhost:8080/ ,DevServer 启动后会一直驻留在后台保持运行,访问这个网址你就能获取项目根目录下的 index.html。
注意:
1、此时可能会提示webpack-dev-server不是内部命令,解决办法为在全局再次安装一下webpack-dev-server模块,或者在package.json里的scripts里加上"dev": "webpack-dev-server",然后执行命令npm run dev
2、并没有通过webpack命令生成一个dist目录,然后在浏览器里输入地址http://localhost:8080/后,页面会正常显示。这个原因是devServer会将webpack构建出的文件保存到内存里,不需要打包生成就能预览
6.2、参数设置
在webpack.config.js中可以根据需要配置dev-server满足你更多的需求。
[](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">// webpack.config.js 配置一下 devServer
devServer: {
clientLogLevel: 'warning',
historyApiFallback: true,
hot: true,
compress: true,
host: 'localhost',
port: 8080 }</pre>
](javascript:void(0); "复制代码")
Hot (文档)
- 热模块更新作用。即修改或模块后,保存会自动更新,页面不用刷新呈现最新的效果。
- 这不是和 webpack.HotModuleReplacementPlugin (HMR) 这个插件不是一样功能吗?是的,不过请注意了,
***HMR* 这个插件是真正实现热模块更新的**
。而 devServer 里配置了 hot: true , webpack会自动添加 HMR 插件。所以模块热更新最终还是 HMR 这个插件起的作用。
host (文档)
- 写主机名的。默认 localhost
port (文档)
- 端口号。默认 8080
historyApiFallback (文档)
如果为 true ,页面出错不会弹出 404 页面。
-
如果为 {...} , 看看一般里面有什么。
- rewrites
](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">rewrites: [
[
{ from: /^/subpage/, to: '/views/subpage.html' },
{
from: /^/helloWorld/.*$/,
to: function() { return '/views/hello_world.html;
}
}
]
// 从代码可以看出 url 匹配正则,匹配成功就到某个页面。
// 并不建议将路由写在这,一般 historyApiFallback: true 就行了。</pre>](javascript:void(0); "复制代码")
- verbose:如果 true ,则激活日志记录。
-
disableDotRule: 禁止 url 带小数点
.
。
compress (文档)
- 如果为 true ,开启虚拟服务器时,为你的代码进行压缩。加快开发流程和优化的作用。
contentBase (文档)
你要提供哪里的内容给虚拟服务器用。这里最好填 绝对路径。
默认情况下,它将使用您当前的工作目录来提供内容。
](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">// 单目录
contentBase: path.join(__dirname, "public") // 多目录
contentBase: [path.join(__dirname, "public"), path.join(__dirname, "assets")]</pre>
](javascript:void(0); "复制代码")
Open (文档)
- true,则自动打开浏览器。
overlay (文档)
- 如果为 true ,在浏览器上全屏显示编译的errors或warnings。默认 false (关闭)
- 如果你只想看 error ,不想看 warning。
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">overlay:{
errors:true,
warnings:false }</pre>
quiet (文档)
- true,则终端输出的只有初始启动信息。 webpack 的警告和错误是不输出到终端的。
publicPath (文档)
- 配置了 publicPath后,
*url* = '主机名' + '*publicPath*配置的' + '原来的*url.path*'
。这个其实与 output.publicPath 用法大同小异。 - output.publicPath 是作用于 js, css, img 。而 devServer.publicPath 则作用于请求路径上的。
](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">// devServer.publicPath
publicPath: "/assets/"
// 原本路径 --> 变换后的路径
http://localhost:8080/app.js --> http://localhost:8080/assets/app.js</pre>
](javascript:void(0); "复制代码")
proxy (文档)
- 当您有一个单独的API后端开发服务器,并且想要在同一个域上发送API请求时,则代理这些 url 。看例子好理解。
](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);"> proxy: { '/proxy': {
target: 'http://your_api_server.com',
changeOrigin: true,
pathRewrite: { '^/proxy': '' }
}</pre>
](javascript:void(0); "复制代码")
- 假设你主机名为 localhost:8080 , 请求 API 的 url 是 http://your_api_server.com/user/list
-
'/proxy':如果点击某个按钮,触发请求 API 事件,这时请求 url 是
http://localhost:8080**/proxy**/user/list
。 -
changeOrigin:如果 true ,那么
http://localhost:8080/proxy/user/list 变为 http://your_api_server.com/proxy/user/list
。但还不是我们要的 url 。 -
pathRewrite:重写路径。匹配 /proxy ,然后变为
''
,那么 url 最终为http://your_api_server.com/user/list
。
watchOptions (文档)
- 一组自定义的监听模式,用来监听文件是否被改动过。
](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">watchOptions: {
aggregateTimeout: 300,
poll: 1000,
ignored: /node_modules/ }</pre>
](javascript:void(0); "复制代码")
- aggregateTimeout:一旦第一个文件改变,在重建之前添加一个延迟。填以毫秒为单位的数字。
- ignored:观察许多文件系统会导致大量的CPU或内存使用量。可以排除一个巨大的文件夹。
-
poll:填以毫秒为单位的数字。每隔(你设定的)多少时间查一下有没有文件改动过。不想启用也可以填
false
。
](javascript:void(0); "复制代码")
<pre style="margin: 0px; padding: 0px; font-family: "microsoft yahei" !important; white-space: pre-wrap; overflow-wrap: break-word; font-size: 16px !important; background: rgb(255, 255, 255);">var path = require("path"); var webpack = require("webpack");
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode:"development",
entry:{
app:"./src/js/main.js" },
output:{
filename: "bundle.js",
path:path.resolve(__dirname,"../dist"), //path.resolve是nodejs里的方法,具体看nodejs api
},
devServer:{
contentBase:false, //我这里没有设置contentBase,contentBase必须指向存在的bundle.js文件所在目录,
//因为这里是开发模式,所以dist目录并不存在,所以用false.
host:'localhost',
port:'8888',
inline:true,//webpack官方推荐
watchOptions: {
aggregateTimeout: 2000,//浏览器延迟多少秒更新
poll: 1000//每秒检查一次变动
},
compress:true,//一切服务都启用gzip 压缩
historyApiFallback:true,//找不到页面默认跳index.html
hot:true,//启动热更新,必须搭配new webpack.HotModuleReplacementPlugin()插件
open:true,
},
plugins: [ new webpack.HotModuleReplacementPlugin(), new HtmlWebpackPlugin({
template:"index.html",
title:'index',
inject: true }), // new webpack.NamedModulesPlugin(),
// HMR shows correct file names in console on update.
// new webpack.NoEmitOnErrorsPlugin()
]
} </pre>
](javascript:void(0); "复制代码")
示例:
配置文件:
View Code
运行结果:
七、视频
https://www.bilibili.com/video/av37008594/
八、示例
https://git.dev.tencent.com/zhangguo5/WebPackDemo.git
九、作业
(1)、创建一个项目,项目中使用ES6的模块功能与箭头函数,使用babel-loader转译成兼容IE8的前端输出。
本文转载于张果大神的《10分钟学会前端工程化webpack4.0》