《前端工程化開發(fā)二》

目錄

五夜郁、插件plugins

5.1什燕、插件概要

Plugin 是用來擴(kuò)展 Webpack 功能的,通過在構(gòu)建流程里注入鉤子實(shí)現(xiàn)竞端,它給 Webpack 帶來了很大的靈活性屎即。

插件是 webpack 的支柱功能。webpack 自身也是構(gòu)建于事富,你在 webpack 配置中用到的相同的插件系統(tǒng)之上技俐!插件目的在于解決 loader 無法實(shí)現(xiàn)的其他事。

webpack 插件是一個具有 apply 屬性的 JavaScript 對象统台。apply 屬性會被 webpack compiler 調(diào)用雕擂,并且 compiler 對象可在整個編譯生命周期訪問。

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

<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 構(gòu)建過程開始贱勃!");
});
}
}</pre>

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

compiler hook 的 tap 方法的第一個參數(shù)井赌,應(yīng)該是駝峰式命名的插件名稱。建議為此使用一個常量贵扰,以便它可以在所有 hook 中復(fù)用仇穗。

由于插件可以帶參數(shù)/選項,你必須在 webpack 配置中戚绕,向 plugins 屬性傳入 new 實(shí)例纹坐。

根據(jù)你的 webpack 用法,這里有多種方式使用插件舞丛。

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

<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'); //訪問內(nèi)置的插件
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>

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

5.1耘子、HTML Webpack Plugin(創(chuàng)建HTML插件)

該個插件的作用是用來自動生成html頁面,既可以生成單個頁面又可以生成多個頁面瓷马,并且在生成前可以給它一些的配置參數(shù)拴还,它會按照你想要的生成方式去生成頁面。

第一步:安裝

<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一個實(shí)例

<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({參數(shù)})
]</pre>

結(jié)果

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

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

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

參數(shù):

title

生成頁面的titile元素

filename

生成的html文件的文件名欧聘。默認(rèn)index.html片林,可以直接配置帶有子目錄

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

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

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

template

模版文件路徑

templateParameters

{Boolean|Object|Function} 允許覆蓋模板中使用的參數(shù)

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

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

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

inject

插入的script插入的位置,四個可選值:
true: 默認(rèn)值怀骤,script標(biāo)簽位于html文件的body底部
body: 同true
head: script標(biāo)簽位于html文件的head標(biāo)簽內(nèi)
false: 不插入生成的js文件费封,只是生成的html文件

favicon

為生成的html文件生成一個favicon,屬性值是路徑

minify

html文件進(jìn)行壓縮蒋伦。屬性值是false或者壓縮選項值弓摘。默認(rèn)false不對html文件進(jìn)行壓縮。
html-webpack-plugin中集成的html-minifier痕届,生成模板文件壓縮配置韧献,有很多配置項末患,這些配置項就是minify的壓縮選項值。

hash

給生成的js文件尾部添加一個hash值锤窑。這個hash值是本次webpack編譯的hash值璧针。默認(rèn)false;

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

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

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

cache

Boolean類型。只在文件被修改的時候才生成一個新文件渊啰。默認(rèn)值true

showErrors

Boolean類型探橱。錯誤信息是否寫入html文件。默認(rèn)true

chunks

html文件中引用哪些js文件,用于多入口文件時绘证。不指定chunks時隧膏,所有文件都引用

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

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

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

excludeChunks

與chunks相反,html文件不引用哪些js文件

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

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

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

chunksSortMode

控制script標(biāo)簽的引用順序嚷那。默認(rèn)五個選項:
none: 無序
auto: 默認(rèn)值, 按插件內(nèi)置的排序方式
dependency: 根據(jù)不同文件的依賴關(guān)系排序
manual: chunks按引入的順序排序, 即屬性chunks的順序
{Function}: 指定具體的排序規(guī)則

xhtml

Boolean類型胞枕,默認(rèn)false, true時以兼容xhtml的模式引用文件

示例:

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

<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', /這個值對應(yīng)html里的title/ template:'./src/template.html', //模板文件地址
filename:'test1.html', //文件名,默認(rèn)為index.html(路徑相對于output.path的值)
inject:true, //script標(biāo)簽的位置车酣,true/body為在</body>標(biāo)簽前曲稼,head為在<head>里,false表示頁面不引入js文件
hash:true, //是否為引入的js文件添加hash值
chunks:['one'], //頁面里要引入的js文件湖员,值對應(yīng)的是entry里的key。省略參數(shù)會把entry里所有文件都引入
//excludeChunks:['one'],//頁面里不能引入的js文件瑞驱,與chunks剛好相反
minify:{ //html-webpack-plugin內(nèi)部集成了html-minifier
collapseWhitespace:true, //壓縮空格
removeAttributeQuotes:true, //移除引號
removeComments:true, //移除注釋
},
}), //生成兩個文件娘摔,分別引入兩個js文件(現(xiàn)在是一個文件里引入了兩個js)
new HtmlWebpackPlugin({
title:'kaivon',
template:'./src/template.html',
hash:true,
filename:'test2.html',
chunks:['two']
})
]</pre>

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

示例1:

webpack.config03.js配置文件

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

<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配置文件

//導(dǎo)入用于生成html的插件
const HtmlWebpackPlugin=require("html-webpack-plugin"); //依賴node中的path模塊
var path=require('path'); //定義一個默認(rèn)模塊對象
module.exports={
entry:{app01:"./src/app03.js"}, //設(shè)置輸出結(jié)果
output: { //路徑,將相對路徑轉(zhuǎn)絕對路徑
path:path.resolve(__dirname,'dist'), //文件,[name]是模塊名稱唤反,占位
filename: "[hash:8].bundle.js" },
module: {
},
plugins: [ //創(chuàng)建一個插件對象凳寺,并指定參數(shù)
new HtmlWebpackPlugin({ //指定生成的文件路徑與名稱
filename:"../app03.html", //標(biāo)題
title:"Hello App03!" })
]
};</pre>

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

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>

打包結(jié)果:

image

運(yùn)行:

image

示例2:

webpack.config03.js配置文件

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

<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配置文件

//導(dǎo)入用于生成html的插件
const HtmlWebpackPlugin=require("html-webpack-plugin"); //依賴node中的path模塊
var path=require('path'); //定義一個默認(rèn)模塊對象
module.exports={
entry:{app01:"./src/app03.js"}, //設(shè)置輸出結(jié)果
output: { //路徑,將相對路徑轉(zhuǎn)絕對路徑
path:path.resolve(__dirname,'dist'), //文件,[name]是模塊名稱彤侍,占位
filename: "[hash:8].bundle.js" },
module: {
},
plugins: [ //創(chuàng)建一個插件對象肠缨,并指定參數(shù)
new HtmlWebpackPlugin({ //指定生成的文件路徑與名稱
filename:"../app03.html", //標(biāo)題
title:"Hello App03!", //指定模板
template:"./templates/tmpl03.html", //模板參數(shù),允許覆蓋templates中的參數(shù)
templateParameters:{
content:"Hello templateParameters!", //重寫title
title:"Hello App03 title!",
key:"value" },
minify:{
removeComments:true, //移除注釋
collapseWhitespace:true, //折疊空格
//更新請參數(shù)https://github.com/kangax/html-minifier#options-quick-reference
}
})
]
};</pre>

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

/templates/tmpl03.html 模板文件

image

View Code

生成結(jié)果:

image

5.2盏阶、Mini-css-extract-plugin(單獨(dú)提取CSS插件)

將CSS提取為獨(dú)立的文件的插件晒奕,對每個包含css的js文件都會創(chuàng)建一個CSS文件,支持按需加載css和sourceMap

默認(rèn)情況下css是被js注入的一段style名斟,如下所示:

image

只能用在webpack4中脑慧,對比另一個插件 extract-text-webpack-plugin特點(diǎn):

  • 異步加載
  • 不重復(fù)編譯,性能更好
  • 更容易使用
  • 只針對CSS

目前缺失功能砰盐,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>

使用:

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

<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
// 默認(rèn)使用 webpackOptions.output中的publicPath
publicPath: '../' },
}, 'css-loader',
],
}
]
}
}</pre>

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

高級配置:

這個插件應(yīng)該只用在 production 配置中,并且在loaders鏈中不使用 style-loader, 特別是在開發(fā)中使用HMR岩梳,因?yàn)檫@個插件暫時不支持HMR

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

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

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

示例:

webpack.config03.js

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

<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配置文件

//導(dǎo)入用于生成html的插件
const HtmlWebpackPlugin=require("html-webpack-plugin"); //導(dǎo)入用于提取css的插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); //依賴node中的path模塊
var path=require('path'); //定義一個默認(rèn)模塊對象
module.exports={
entry:{app01:"./src/app03.js"}, //設(shè)置輸出結(jié)果
output: { //路徑囊骤,將相對路徑轉(zhuǎn)絕對路徑
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 轉(zhuǎn)化成 CommonJS 模塊
}, {
loader: "sass-loader" // 將 Scss 編譯成 CSS
}]
}
]
},
plugins: [ //創(chuàng)建一個插件對象,并指定參數(shù)
new HtmlWebpackPlugin({ //指定生成的文件路徑與名稱
filename:"../app03.html", //標(biāo)題
title:"Hello App03!", //指定模板
template:"./templates/tmpl03.html", //模板參數(shù)也物,允許覆蓋templates中的參數(shù)
templateParameters:{
content:"Hello templateParameters!", //重寫title
title:"Hello App03 title!",
key:"value" },
minify:{
removeComments:true, //移除注釋
collapseWhitespace:true, //折疊空格
//更新請參數(shù)https://github.com/kangax/html-minifier#options-quick-reference
}
}), //創(chuàng)建一個用于提取css的插件對象
new MiniCssExtractPlugin({
filename:"[name]
[hash:10].css",
chunkFilename:"[id]" })
]
};</pre>

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

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>

打包生成的結(jié)果

[
復(fù)制代碼
](javascript:void(0); "復(fù)制代碼")

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

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

運(yùn)行結(jié)果:

image

5.3藕各、clean-webpack-plugin(刪除或清理構(gòu)建目錄)

在用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的最前面創(chuàng)建清理對象

<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目錄再創(chuàng)建新的dist目錄激况。里面的參數(shù)為要刪除的目錄,放在一個數(shù)組里面
...
]</pre>

在文件夾里打開dist所在的目錄膘魄,并在終端里再次執(zhí)行命令webpack后乌逐,會看到dist目錄先被刪除后又被創(chuàng)建。

關(guān)于clean-webpack-plugin插件的所有配置參數(shù)請參考:https://www.npmjs.com/package/clean-webpack-plugin

該插件有兩個參數(shù):

Paths ( 必須)

An [array] of string paths to clean

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

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

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

Options and defaults (可選)

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

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

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

示例:

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

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

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

示例:

webpack.config03.js

[
復(fù)制代碼
](javascript:void(0); "復(fù)制代碼")

<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配置文件

//導(dǎo)入用于理清目錄的插件
const CleanWebpackPlugin=require('clean-webpack-plugin'); //導(dǎo)入用于生成html的插件
const HtmlWebpackPlugin=require("html-webpack-plugin"); //導(dǎo)入用于提取css的插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); //依賴node中的path模塊
var path=require('path'); //定義一個默認(rèn)模塊對象
module.exports={
entry:{app01:"./src/app03.js"}, //設(shè)置輸出結(jié)果
output: { //路徑创葡,將相對路徑轉(zhuǎn)絕對路徑
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 轉(zhuǎn)化成 CommonJS 模塊
}, {
loader: "sass-loader" // 將 Scss 編譯成 CSS
}]
}
]
},
plugins: [ //創(chuàng)建一個清理插件,參數(shù)一為目標(biāo),如路徑灿渴,參數(shù)二為選項
new CleanWebpackPlugin(['dist'],{dry:false}), //創(chuàng)建一個插件對象洛波,并指定參數(shù)
new HtmlWebpackPlugin({ //指定生成的文件路徑與名稱
filename:"../app03.html", //標(biāo)題
title:"Hello App03!", //指定模板
template:"./templates/tmpl03.html", //模板參數(shù),允許覆蓋templates中的參數(shù)
templateParameters:{
content:"Hello templateParameters!", //重寫title
title:"Hello App03 title!",
key:"value" },
minify:{
removeComments:true, //移除注釋
collapseWhitespace:true, //折疊空格
//更新請參數(shù)https://github.com/kangax/html-minifier#options-quick-reference
}
}), //創(chuàng)建一個用于提取css的插件對象
new MiniCssExtractPlugin({
filename:"[name]
[hash:10].css",
chunkFilename:"[id]" })
]
};</pre>

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

運(yùn)行前:

image

運(yùn)行后:

image

5.4骚露、常用plugins

5.4.1蹬挤、用于修改行為

5.4.2焰扳、用于優(yōu)化

5.4.3育瓜、其它

六钙态、DevServer開發(fā)服務(wù)器

webpack-dev-server就是一個基于Node.js和webpack的一個簡易服務(wù)器。它在服務(wù)器端使用webpack-dev-middleware進(jìn)行webpack構(gòu)建打包菇晃;并在客戶端注入一份runtime册倒,用于接受服務(wù)器端的構(gòu)建打包后信息。

在實(shí)際開發(fā)中我們可能會需要完成如下功能:

  1. 提供 HTTP 服務(wù)而不是使用本地文件預(yù)覽磺送;
  2. 監(jiān)聽文件的變化并自動刷新網(wǎng)頁驻子,做到實(shí)時預(yù)覽灿意;
  3. 支持 Source Map,以方便調(diào)試崇呵。

Webpack 原生支持上述第2缤剧、3點(diǎn)內(nèi)容,再結(jié)合官方提供的開發(fā)工具 DevServer 也可以很方便地做到第1點(diǎn)域慷。 DevServer 會啟動一個 HTTP 服務(wù)器用于服務(wù)網(wǎng)頁請求荒辕,同時會幫助啟動 Webpack ,并接收 Webpack 發(fā)出的文件更變信號犹褒,通過 WebSocket 協(xié)議自動刷新網(wǎng)頁做到實(shí)時預(yù)覽抵窒。

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>

安裝成功后在項目的根目錄下執(zhí)行webpack-dev-server 命令叠骑, DevServer 服務(wù)器就啟動了李皇,這時你會看到控制臺有一串日志輸出:

Project is running at http://localhost:8080/

webpack output is served from /

image

現(xiàn)在就可以直接訪問了

image

這意味著 DevServer 啟動的 HTTP 服務(wù)器監(jiān)聽在 http://localhost:8080/ ,DevServer 啟動后會一直駐留在后臺保持運(yùn)行宙枷,訪問這個網(wǎng)址你就能獲取項目根目錄下的 index.html掉房。

注意:

1、此時可能會提示webpack-dev-server不是內(nèi)部命令慰丛,解決辦法為在全局再次安裝一下webpack-dev-server模塊卓囚,或者在package.json里的scripts里加上"dev": "webpack-dev-server",然后執(zhí)行命令npm run dev

2璧帝、并沒有通過webpack命令生成一個dist目錄捍岳,然后在瀏覽器里輸入地址http://localhost:8080/后,頁面會正常顯示睬隶。這個原因是devServer會將webpack構(gòu)建出的文件保存到內(nèi)存里,不需要打包生成就能預(yù)覽

6.2页徐、參數(shù)設(shè)置

在webpack.config.js中可以根據(jù)需要配置dev-server滿足你更多的需求苏潜。

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

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

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

Hot文檔

  • 熱模塊更新作用。即修改或模塊后变勇,保存會自動更新恤左,頁面不用刷新呈現(xiàn)最新的效果。
  • 這不是和 webpack.HotModuleReplacementPlugin (HMR) 這個插件不是一樣功能嗎搀绣?是的飞袋,不過請注意了,***HMR* 這個插件是真正實(shí)現(xiàn)熱模塊更新的**链患。而 devServer 里配置了 hot: true , webpack會自動添加 HMR 插件巧鸭。所以模塊熱更新最終還是 HMR 這個插件起的作用。

host文檔

  • 寫主機(jī)名的麻捻。默認(rèn) localhost

port文檔

  • 端口號纲仍。默認(rèn) 8080

historyApiFallback文檔

  • 如果為 true 呀袱,頁面出錯不會彈出 404 頁面。

  • 如果為 {...} , 看看一般里面有什么郑叠。

    • rewrites

    [
    復(fù)制代碼

    ](javascript:void(0); "復(fù)制代碼")

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

    [
    復(fù)制代碼

    ](javascript:void(0); "復(fù)制代碼")

    • verbose:如果 true ,則激活日志記錄沸版。
    • disableDotRule: 禁止 url 帶小數(shù)點(diǎn) . 嘁傀。

compress (文檔)

  • 如果為 true ,開啟虛擬服務(wù)器時推穷,為你的代碼進(jìn)行壓縮心包。加快開發(fā)流程和優(yōu)化的作用。

contentBase文檔

  • 你要提供哪里的內(nèi)容給虛擬服務(wù)器用馒铃。這里最好填 絕對路徑蟹腾。

  • 默認(rèn)情況下,它將使用您當(dāng)前的工作目錄來提供內(nèi)容区宇。

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

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

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

Open文檔

  • true妇智,則自動打開瀏覽器。

overlay (文檔)

  • 如果為 true 锣光,在瀏覽器上全屏顯示編譯的errors或warnings憋活。默認(rèn) false (關(guān)閉)
  • 如果你只想看 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* = '主機(jī)名' + '*publicPath*配置的' + '原來的*url.path*'胜宇。這個其實(shí)與 output.publicPath 用法大同小異耀怜。
  • output.publicPath 是作用于 js, css, img 。而 devServer.publicPath 則作用于請求路徑上的桐愉。

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

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

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

proxy (文檔)

  • 當(dāng)您有一個單獨(dú)的API后端開發(fā)服務(wù)器财破,并且想要在同一個域上發(fā)送API請求時,則代理這些 url 从诲∽罅。看例子好理解。

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

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

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

  1. 假設(shè)你主機(jī)名為 localhost:8080 , 請求 APIurlhttp://your_api_server.com/user/list
  2. '/proxy':如果點(diǎn)擊某個按鈕,觸發(fā)請求 API 事件抖锥,這時請求 urlhttp://localhost:8080**/proxy**/user/list 亿眠。
  3. changeOrigin:如果 true ,那么 http://localhost:8080/proxy/user/list 變?yōu)?http://your_api_server.com/proxy/user/list 磅废。但還不是我們要的 url 纳像。
  4. pathRewrite:重寫路徑。匹配 /proxy 拯勉,然后變?yōu)?code>'' 竟趾,那么 url 最終為 http://your_api_server.com/user/list

watchOptions文檔

  • 一組自定義的監(jiān)聽模式宫峦,用來監(jiān)聽文件是否被改動過岔帽。

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

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

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

  1. aggregateTimeout:一旦第一個文件改變导绷,在重建之前添加一個延遲犀勒。填以毫秒為單位的數(shù)字。
  2. ignored:觀察許多文件系統(tǒng)會導(dǎo)致大量的CPU或內(nèi)存使用量妥曲〖址眩可以排除一個巨大的文件夾。
  3. poll:填以毫秒為單位的數(shù)字檐盟。每隔(你設(shè)定的)多少時間查一下有沒有文件改動過褂萧。不想啟用也可以填false

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

<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, //我這里沒有設(shè)置contentBase导犹,contentBase必須指向存在的bundle.js文件所在目錄,
//因?yàn)檫@里是開發(fā)模式羡忘,所以dist目錄并不存在谎痢,所以用false.
host:'localhost',
port:'8888',
inline:true,//webpack官方推薦
watchOptions: {
aggregateTimeout: 2000,//瀏覽器延遲多少秒更新
poll: 1000//每秒檢查一次變動
},
compress:true,//一切服務(wù)都啟用gzip 壓縮
historyApiFallback:true,//找不到頁面默認(rèn)跳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>

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

示例:

配置文件:

image

View Code

運(yùn)行結(jié)果:


image

七卷雕、視頻

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

八舶得、示例

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

九、作業(yè)

(1)爽蝴、創(chuàng)建一個項目,項目中使用ES6的模塊功能與箭頭函數(shù)纫骑,使用babel-loader轉(zhuǎn)譯成兼容IE8的前端輸出蝎亚。

本文轉(zhuǎn)載于張果大神的《10分鐘學(xué)會前端工程化webpack4.0》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市先馆,隨后出現(xiàn)的幾起案子发框,更是在濱河造成了極大的恐慌,老刑警劉巖煤墙,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件梅惯,死亡現(xiàn)場離奇詭異宪拥,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)铣减,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門她君,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人葫哗,你說我怎么就攤上這事缔刹。” “怎么了劣针?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵校镐,是天一觀的道長。 經(jīng)常有香客問我捺典,道長鸟廓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任襟己,我火速辦了婚禮引谜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘稀蟋。我一直安慰自己煌张,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布退客。 她就那樣靜靜地躺著骏融,像睡著了一般。 火紅的嫁衣襯著肌膚如雪萌狂。 梳的紋絲不亂的頭發(fā)上档玻,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機(jī)與錄音茫藏,去河邊找鬼误趴。 笑死,一個胖子當(dāng)著我的面吹牛务傲,可吹牛的內(nèi)容都是我干的凉当。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼售葡,長吁一口氣:“原來是場噩夢啊……” “哼看杭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起挟伙,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤楼雹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贮缅,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡榨咐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了谴供。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片块茁。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖憔鬼,靈堂內(nèi)的尸體忽然破棺而出龟劲,到底是詐尸還是另有隱情,我是刑警寧澤轴或,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布昌跌,位于F島的核電站,受9級特大地震影響照雁,放射性物質(zhì)發(fā)生泄漏蚕愤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一饺蚊、第九天 我趴在偏房一處隱蔽的房頂上張望萍诱。 院中可真熱鬧,春花似錦污呼、人聲如沸裕坊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽籍凝。三九已至,卻和暖如春苗缩,著一層夾襖步出監(jiān)牢的瞬間饵蒂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工酱讶, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留退盯,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓泻肯,卻偏偏與公主長得像渊迁,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子灶挟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容