前端工程化和模块化

《前端工程化开发二》

2020-03-22  本文已影响0人  前端驿站

目录

五、插件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>

打包结果:

image

运行:

image

示例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 模板文件

image

View Code

生成结果:

image

5.2、Mini-css-extract-plugin(单独提取CSS插件)

将CSS提取为独立的文件的插件,对每个包含css的js文件都会创建一个CSS文件,支持按需加载css和sourceMap

默认情况下css是被js注入的一段style,如下所示:

image

只能用在webpack4中,对比另一个插件 extract-text-webpack-plugin特点:

目前缺失功能,HMR(热模块替换)。

image

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>

打包生成的结果

[ 复制代码 ](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);"><!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); "复制代码")

运行结果:

image

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); "复制代码")

Options and defaults (可选)

[ 复制代码

](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

[ 复制代码 ](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配置文件

//导入用于理清目录的插件
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); "复制代码")

运行前:

image

运行后:

image

5.4、常用plugins

5.4.1、用于修改行为

5.4.2、用于优化

5.4.3、其它

六、DevServer开发服务器

webpack-dev-server就是一个基于Node.js和webpack的一个简易服务器。它在服务器端使用webpack-dev-middleware进行webpack构建打包;并在客户端注入一份runtime,用于接受服务器端的构建打包后信息。

在实际开发中我们可能会需要完成如下功能:

  1. 提供 HTTP 服务而不是使用本地文件预览;
  2. 监听文件的变化并自动刷新网页,做到实时预览;
  3. 支持 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 /

image

现在就可以直接访问了

image

这意味着 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文档

host文档

port文档

historyApiFallback文档

compress (文档)

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文档

overlay (文档)

<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文档

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 (文档)

[ 复制代码

](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); "复制代码")

  1. 假设你主机名为 localhost:8080 , 请求 APIurlhttp://your_api_server.com/user/list
  2. '/proxy':如果点击某个按钮,触发请求 API 事件,这时请求 urlhttp://localhost:8080**/proxy**/user/list
  3. changeOrigin:如果 true ,那么 http://localhost:8080/proxy/user/list 变为 http://your_api_server.com/proxy/user/list 。但还不是我们要的 url
  4. 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); "复制代码")

  1. aggregateTimeout:一旦第一个文件改变,在重建之前添加一个延迟。填以毫秒为单位的数字。
  2. ignored:观察许多文件系统会导致大量的CPU或内存使用量。可以排除一个巨大的文件夹。
  3. 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); "复制代码")

示例:

配置文件:

image

View Code

运行结果:


image

七、视频

https://www.bilibili.com/video/av37008594/

八、示例

https://git.dev.tencent.com/zhangguo5/WebPackDemo.git

九、作业

(1)、创建一个项目,项目中使用ES6的模块功能与箭头函数,使用babel-loader转译成兼容IE8的前端输出。

本文转载于张果大神的《10分钟学会前端工程化webpack4.0》

上一篇 下一篇

猜你喜欢

热点阅读