Preface
What is a plug-in? A functional module that focuses on processing a specific task in the compilation process of webpack can be called a plug-in.
Plugin is an extender, it enriches webpack itself, for the whole process of webpack packaging after the loader is over, it does not directly manipulate files, but works based on the event mechanism, it will monitor some nodes in the webpack packaging process, and execute A wide range of tasks.
Features of Plugin
- Is an independent module
- The module exposes a js function
- Function prototype
(prototype)
defined on an injectioncompiler
objectapply
methodapply
function is required bycompiler
objects mountedwebpack
event hook, hook callback can get the current compilationcompilation
the object, if it is asynchronous, then you can get the compiler plugin To callbackcallback
- Complete the custom sub-compilation process and process the internal data of the
complition
- If the plug-in is compiled asynchronously, the
callback
callback will be executed after the data processing is completed.
HotModuleReplacementPlugin
Module hot update plug-in. Hot-Module-Replacement
hot update is dependent on webpack-dev-server
, which is the update package file or reload an entire page refresh file changes during packaging, HRM
is updated only modified part.
HotModuleReplacementPlugin
comes with the webpack
webpack
, it can be used directly in the plugins
const webpack = require('webpack')
plugins: [
new webpack.HotModuleReplacementPlugin(), // 热更新插件
]
html-webpack-plugin
Generate html files. The webpack in entry
relevant entry configuration chunk
and extract-text-webpack-plugin
extracted css style is inserted into the plug provided template
or templateContent
generating CI content specified on the basis of a html file, particularly insert mode is the style link
inserted head
element, script
Insert it into head
or body
.
const HtmlWebpackPlugin = require('html-webpack-plugin')
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: path.join(__dirname, '/index.html'),
minify: {
// 压缩HTML文件
removeComments: true, // 移除HTML中的注释
collapseWhitespace: true, // 删除空白符与换行符
minifyCSS: true, // 压缩内联css
},
inject: true,
}),
]
inject has four option values
- true: the default value, the
script
tag is located at the bottom ofbody
html
- body: The
script
tag is located at the bottom ofbody
html
file (same as true) - head: The
script
tag is located in thehead
tag - false: do not insert the generated js file, just generate a
html
file
Multi-page application packaging
Sometimes, our application is not necessarily a single-page application, but a multi-page application, so how to use webpack for packaging.
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: {
index: './src/index.js',
login: './src/login.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[hash:6].js',
},
//...
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html',
filename: 'index.html', //打包后的文件名
}),
new HtmlWebpackPlugin({
template: './public/login.html',
filename: 'login.html', //打包后的文件名
}),
],
}
If you need to configure multiple HtmlWebpackPlugin
, then the filename
field cannot be defaulted, otherwise the default generated index.html
.
But there is a problem. index.html
and login.html
will find that they both introduce index.f7d21a.js
and login.f7d21a.js
at the same time. Usually this is not what we want. We hope that index.html
only introduces index.f7d21a.js
, and login.html
login.f7d21a.js
.
HtmlWebpackPlugin
provides a chunks
, which can accept an array. Configuring this parameter will only introduce the js specified in the array into the html file
module.exports = {
//...
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html',
filename: 'index.html', //打包后的文件名
chunks: ['index'],
}),
new HtmlWebpackPlugin({
template: './public/login.html',
filename: 'login.html', //打包后的文件名
chunks: ['login'],
}),
],
}
Such execution npm run build
, you can see index.html
only introduced index js file, and login.html
also just introduced login js file.
clean-webpack-plugin
clean-webpack-plugin
used to clean up the bundle file generated by the last project before packaging. It will output.path
; this plug-in is used very frequently in the production environment because the production environment often generates many bundle files through hash, if not If you clean it, a new one will be generated every time, resulting in a very large folder.
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, '/index.html'),
}),
new CleanWebpackPlugin(), // 所要清理的文件夹名称
]
extract-text-webpack-plugin
Make css into a file instead of inline. The main purpose of this plugin is to extract the CSS styles and prevent the page style loading disorder caused by packaging the styles in js.
const ExtractTextPlugin = require('extract-text-webpack-plugin')
plugins: [
// 将css分离到/dist文件夹下的css文件夹中的index.css
new ExtractTextPlugin('css/index.css'),
]
mini-css-extract-plugin
A plug-in that extracts CSS as a separate file, creates a CSS file for each js file that contains css, and supports on-demand loading of css and sourceMap
. It can only be used in webpack4. Compared with another plug-in extract-text-webpack-plugin, it has the following features:
- Asynchronous loading
- No repeated compilation, better performance
- Easier to use
- Only for CSS
This plug-in should only be used in a production environment configuration, and loaders
without the use of chain style-loader
, and this plugin is not supported HMR
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
module: {
rules: [
{
test: /\.(le|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../',
},
},
'css-loader',
'postcss-loader',
'less-loader',
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash:8].css',
chunkFilename: 'css/[id].[contenthash:8].css',
}),
],
}
purifycss-webpack
Sometimes we write too much or repetitive css, which results in redundant code, which we hope to remove in the production environment.
const path = require('path')
const PurifyCssWebpack = require('purifycss-webpack') // 引入PurifyCssWebpack插件
const glob = require('glob') // 引入glob模块,用于扫描全部html文件中所引用的css
module.exports = merge(common, {
plugins: [
new PurifyCssWebpack({
paths: glob.sync(path.join(__dirname, 'src/*.html')),
}),
],
})
optimize-css-assets-webpack-plugin
We hope to reduce the volume of css after packaging, you can use optimize-css-assets-webpack-plugin
.
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin") // 压缩css代码
optimization: {
minimizer: [
// 压缩css
new OptimizeCSSAssetsPlugin({})
]
UglifyJsPlugin
uglifyJsPlugin
is the vue-cli
to compress js files, thereby reducing the size of js files and accelerating the load speed. It uses single-threaded compression code, and the packaging time is slow, so you can close it in the development environment and open it again when deploying in the production environment.
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
plugins: [
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: true, //是否启用文件缓存
parallel: true //使用多进程并行运行来提高构建速度
})
ParallelUglifyPlugin
Open multiple sub-processes, and assign the work of compressing multiple files to multiple sub-processes to complete. In fact, each sub-process still uses UglifyJS
to compress the code, but it becomes a parallel execution.
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin')
plugins: [
new ParallelUglifyPlugin({
//cacheDir 用于配置缓存存放的目录路径。
cacheDir: '.cache/',
sourceMap: true,
uglifyJS: {
output: {
comments: false,
},
compress: {
warnings: false,
},
},
}),
]
terser-webpack-plugin
Webpack4.0 uses the terser-webpack-plugin
compression plugin by default. Before that, uglifyjs-webpack-plugin
was used. The difference between the two is that the latter does not compress ES6 very well. At the same time, we can turn on the parallel
parameter and use multi-process compression to speed up the compression.
const TerserPlugin = require('terser-webpack-plugin') // 压缩js代码
optimization: {
minimizer: [
new TerserPlugin({
parallel: 4, // 开启几个进程来处理压缩,默认是 os.cpus().length - 1
cache: true, // 是否缓存
sourceMap: false,
}),
]
}
NoErrorsPlugin
Report an error but do not exit the webpack process. When a compilation error occurs, use NoEmitOnErrorsPlugin
to skip the output stage. This ensures that the output resource does not contain errors.
plugins: [new webpack.NoEmitOnErrorsPlugin()]
compression-webpack-plugin
All modern browsers support gzip
compression. Enabling gzip
compression can greatly reduce the size of transmission resources, thereby shortening the resource download time, reducing the time for the first white screen, and improving the user experience.
gzip has the best compression effect on text-based files (such as CSS, JavaScript, and HTML). It can often achieve a compression rate of up to 70-90% when compressing larger files. For already compressed resources (such as pictures) Gzip compression processing, the effect is very bad.
const CompressionPlugin = require('compression-webpack-plugin')
plugins: [
new CompressionPlugin({
// gzip压缩配置
test: /\.js$|\.html$|\.css/, // 匹配文件名
threshold: 10240, // 对超过10kb的数据进行压缩
deleteOriginalAssets: false, // 是否删除原文件
}),
]
Of course, this method also requires back-end configuration support.
DefinePlugin
We can DefinePlugin
. We can use these variables directly in the module without any declaration. DefinePlugin
is a plug-in that comes with webpack
plugins: [
new webpack.DefinePlugin({
DESCRIPTION: 'This Is The Test Text.',
}),
]
// 直接引用
console.log(DESCRIPTION)
ProvidePlugin
Load modules automatically. At any time, when identifier
is treated as an unassigned variable, the module will be automatically loaded, and identifier
will be assigned by the output of this module. This is a plugin that comes with webpack.
module.exports = {
resolve: {
alias: {
jquery: './lib/jquery',
},
},
plugins: [
//提供全局的变量,在模块中使用无需用require引入
new webpack.ProvidePlugin({
$: 'jquery',
React: 'react',
}),
],
}
DLLPlugin
This is only to create a dll in an additional independent webpack setting bundle(dll-only-bundle)
. This plugin will generate a file named manifest.json
, which is used to DLLReferencePlugin
to related dependencies.
are as follows: 1608a8aaf3db26
1. Create webpack.dll.config.js
const path = require('path')
const webpack = require('webpack')
module.exports = {
entry: {
vendor: [
'vue-router',
'vuex',
'vue/dist/vue.common.js',
'vue/dist/vue.js',
'vue-loader/lib/component-normalizer.js',
'vue',
'axios',
'echarts',
],
},
output: {
path: path.resolve('./dist'),
filename: '[name].dll.js',
library: '[name]_library',
},
plugins: [
new webpack.DllPlugin({
path: path.resolve('./dist', '[name]-manifest.json'),
name: '[name]_library',
}),
// 建议加上代码压缩插件,否则dll包会比较大。
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
},
}),
],
}
2. Add the configuration behind the plugin of webpack.prod.conf.js
new webpack.DllReferencePlugin({
manifest: require('../dist/vendor-manifest.json'),
})
3. Add the shortcut command (build:dll)
package.json
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"lint": "eslint --ext .js,.vue src",
"build": "node build/build.js",
"build:dll": "webpack --config build/webpack.dll.conf.js"
}
When packaging the production environment, the npm run build:dll
command will generate the vendor-manifest.json
file and vendor.dll.js file in the packaging directory. Then npm run build
produces other files.
index.html
under the root directory is added to the reference
<script type="text/javascript" src="./vendor.dll.js"></script>
HappyPack
HappyPack
allows webpack to decompose tasks to multiple child processes for concurrent execution, and send the results to the main process after the child processes are processed. Note that HappyPack
to file-loader
, url-loader
support unfriendly, it is not recommended to use the loader.
1. HappyPack plug-in installation
npm i -D happypack
2. Configure webpack.base.conf.js
module: {
rules: [
{
test: /\.js$/,
use: ['happypack/loader?id=babel'],
include: [resolve('src'), resolve('test')],
exclude: path.resolve(__dirname, 'node_modules'),
},
{
test: /\.vue$/,
use: ['happypack/loader?id=vue'],
},
]
}
3. Configure in the production environment webpack.prod.conf.js
const HappyPack = require('happypack')
// 构造出共享进程池,在进程池中包含5个子进程
const HappyPackThreadPool = HappyPack.ThreadPool({ size: 5 })
plugins: [
new HappyPack({
// 用唯一的标识符id,来代表当前的HappyPack是用来处理一类特定的文件
id: 'babel',
// 如何处理.js文件,用法和Loader配置中一样
loaders: ['babel-loader?cacheDirectory'],
threadPool: HappyPackThreadPool,
}),
new HappyPack({
id: 'vue', // 用唯一的标识符id,来代表当前的HappyPack是用来处理一类特定的文件
loaders: [
{
loader: 'vue-loader',
options: vueLoaderConfig,
},
],
threadPool: HappyPackThreadPool,
}),
]
Note that when the project is small, multi-threaded packaging will slow down the packaging speed.
copy-webpack-plugin
We public/index.html
, but webpack will not help us copy to the dist directory when packaging, so copy-webpack-plugin
can help me do the copying work well.
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = {
plugins: [
new CopyWebpackPlugin({
patterns: [
{
from: 'public/js/*.js',
to: path.resolve(__dirname, 'dist', 'js'),
flatten: true,
},
],
}),
],
}
IgnorePlugin
This is a built-in webpack plug-in. Its function is to ignore the specified directories of third-party packages and prevent these specified directories from being packaged.
For example, we want to use moment
, which mainly formats the time and supports multiple national languages. Although I set the language to Chinese, when packaging, all languages will be packaged. This results in a large package and slow packaging speed. In this regard, we can use IgnorePlugin
make the specified directory ignored, which makes the packaging faster and the files smaller.
const Webpack = require('webpack')
plugins: [
//moment这个库中,如果引用了./locale/目录的内容,就忽略掉,不会打包进去
new Webpack.IgnorePlugin(/\.\/locale/, /moment/),
]
’./locale/'
according to the above method, it also makes it impossible to display the Chinese language when we use it, so at this time, we can manually import the Chinese language directory.
import moment from 'moment'
//手动引入所需要的语言包
import 'moment/locale/zh-cn'
moment.locale('zh-cn')
let r = moment().endOf('day').fromNow()
console.log(r)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。