—— 擁抱html-webpack-plugin的甜蜜
目錄一覽
webpack3.0學(xué)習(xí)筆記(一)
webpack3.0學(xué)習(xí)筆記(二)
webpack3.0學(xué)習(xí)筆記(三)
前情概要
通過(guò)筆記(二)中一整天的試錯(cuò)發(fā)現(xiàn)了構(gòu)建多頁(yè)面時(shí)使用
html-loader
生成html
文件的諸多弊病,重新回歸html-webpack-plugin
。
html-webpack-plugin 構(gòu)建頁(yè)面
筆記(一)中對(duì)
html-webpack-plugin
的理解略顯片面,用法得當(dāng)即可定制出一張滿足需求的頁(yè)面相满。
使用 html-webpack-plugin
插件對(duì)模板進(jìn)行填充完成 html
頁(yè)面的生成,其中的關(guān)鍵點(diǎn)是支持 ejs
的模板語(yǔ)法漱病。
-
html
模板內(nèi)容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>this is webpack loader test</title>
<link rel="stylesheet" href="<%= require('./style/index.css') %>">
<link rel="stylesheet" href="<%= require('./style/one.css') %>">
</head>
<body>
<img src="<%= require('./image/shana.jpg')%>" alt="shana" />
<div class="yintama"></div>
</body>
</html>
-
webpack.config.js
配置:
const path = require('path')
const url = require('url')
const webpack = require('webpack')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: {
app: path.resolve(__dirname,'src/script/index.js'),
one: path.resolve(__dirname,'src/script/one.js'),
vendor: [
'lodash'
]
},
output: {
filename: 'js/[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module:{
rules: [
{
test: /\.js$/,
use: 'babel-loader',
include: path.resolve(__dirname,'src'),
exclude: path.resolve(__dirname,'node_modules')
},
{
test: /\.css$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name]-[hash:6].[ext]',
outputPath: 'css/'
}
},
"extract-loader",
{
loader: "css-loader",
options: {
minimize: true
}
}
]
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [
{
loader: 'url-loader',
options: {
name: '[name]-[hash:6].[ext]',
outputPath: 'image/',
limit: 1,
publicPath: url.format({
hostname:'localhost',
protocol:'http:',
port:8080,
pathname:'/dist/'
})
}
},
'image-webpack-loader'
]
}
]
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
template: path.resolve(__dirname,'src/index.html'),
filename: 'index.html'
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function(module){
return module.context && module.context.indexOf("node_modules") !== -1;
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: "manifest",
minChunks: Infinity
})
]
};
在 html
模板頁(yè)面中通過(guò) ejs
語(yǔ)法配合 webpack
靜態(tài)資源引入方法 require('xxx')
铛碑,將其引入打包流程中,配合前兩篇筆記提及的幾個(gè) loader
對(duì)資源文件進(jìn)行優(yōu)化分離并獲取生成后地址病蛉,插入到新構(gòu)建的 html
頁(yè)面中。
注意:測(cè)試ES6的
import 'xxx'
的形式無(wú)法引入瑰煎,猜測(cè)是使用node進(jìn)行模塊引用铺然,暫時(shí)不支持該語(yǔ)法,使用require('xxx')
即可酒甸。
如需將CSS文件也進(jìn)行合并操作魄健,在對(duì)應(yīng)的JS文件內(nèi)進(jìn)行引入,配合 css-loader
style-loader
解析即可插勤。
項(xiàng)目的優(yōu)化手段
這里只用到了
uglifyjs
诀艰,CommonsChunkPlugin
等方式,DLL打包類庫(kù)的問(wèn)題饮六,之后接構(gòu)建具體項(xiàng)目的時(shí)候再進(jìn)行嘗試。
- 壓縮
- 圖片壓縮使用
image-webpack-loader
基本配置:
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [{
loader: 'url-loader',
options: {
name: '[name]-[hash:6].[ext]',
outputPath: 'image/',
limit: 1,
publicPath: url.format({
hostname: 'localhost',
protocol: 'http:',
port: 8080,
pathname: '/dist/'
})
}
},
{
loader: 'image-webpack-loader',
options: {
gifsicle: {
interlaced: false,
optimizationLevel: 1
},
mozjpeg: {
progressive: true,
quality: 65
}
}
}]
}
測(cè)試了下gif圖片的壓縮非常有限苛蒲,還是少用這種格式的圖片卤橄。
- CSS壓縮使用
css-loader
{
test: /\.css$/,
use: [{
loader: 'file-loader',
options: {
name: '[name]-[hash:6].[ext]',
outputPath: 'css/'
}
},
"extract-loader", {
loader: "css-loader",
options: {
minimize: true
}
}
]
}
CSS的壓縮直接使用loader進(jìn)行即可。
- JS壓縮使用
uglifyjs-webpack-plugin
配置如下:
plugins: [
new UglifyJSPlugin({
sourceMap: true
})
]
若 webpack
開啟了 devtool
臂外,這里的 sourceMap
選項(xiàng)設(shè)為 true
窟扑。
使用
uglifyjs-webpack-plugin
的時(shí)候正好說(shuō)說(shuō)webpack
的tree shaking
特性喇颁,雖然不是什么新東西,由于支持ES6的import
導(dǎo)入語(yǔ)法才開始廣泛使用嚎货。
- tree shaking
two.js
代碼如下:
function name (){
return 'Misery'
};
function age (){
return 30
};
export {name,age}
index.js
內(nèi)容如下:
import {name} from './two.js';
function test(){
var element = document.createElement('div');
element.innerHTML = `hello ${name()}`;
element.appendChild(btn);
return element;
}
document.body.appendChild(test());
打包合并后如下:
打包后 two.js
模塊中 name
和 age
方法都被打包了橘霎,但只有 name
方法被導(dǎo)出了模塊, age
由于沒有被調(diào)用而被忽略了殖属。
使用 uglifyjs-webpack-plugin
壓縮后 age
方法已經(jīng)被徹底剔除姐叁,這個(gè)方式對(duì)不是特別常用的公共模塊調(diào)用能起到精簡(jiǎn)代碼的作用,具體使用方法視項(xiàng)目而定洗显。
注意:如果項(xiàng)目中使用了
babel
可能會(huì)在webpack
打包前就將代碼進(jìn)行轉(zhuǎn)義導(dǎo)致tree shaking
不能生效外潜,因?yàn)檫@功能只支持ES6的import
方法,此時(shí)只需要使用babel-preset-env
插件挠唆,并修改.babelrc
文件处窥。
{
"presets": [
["env", {
"modules": false
}]
]
}
-
提取公共模塊
使用webpack
自帶的webpack.optimize.CommonsChunkPlugin
插件進(jìn)行公共模塊提取。
const path = require('path')
const webpack = require('webpack')
module.exports = {
entry: {
...
vendor: [
'lodash'
]
},
output: {
filename: 'js/[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
...
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function(module){
return module.context && module.context.indexOf("node_modules") !== -1;
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: "manifest",
minChunks: Infinity
})
]
};
在 entry
增加公共庫(kù)文件的chunk玄组,也可將 vue
react
這些框架統(tǒng)一寫入此處滔驾,在插件處配置 webpack.optimize.CommonsChunkPlugin
的設(shè)置,minChunks
接收的類型是 Number
和 Function
俄讹。
當(dāng)為 Number
時(shí)表示 chunk
被引用的次數(shù)不低于設(shè)定值哆致,則會(huì)被合入 vendor
模塊;若為 Function
颅悉,則根據(jù)函數(shù)返回值進(jìn)行判斷沽瞭,module.context && module.context.indexOf("node_modules") !== -1
該配置的含義為僅將 node_modules
目錄下的公共類庫(kù)、框架整合進(jìn) vendor
模塊內(nèi)剩瓶,而忽略項(xiàng)目中被多次調(diào)用的自建模塊驹溃。
名為
manifest
是個(gè)“貨物清單”的配置,是webpack
中一個(gè)特有的配置延曙,目的是將webpack
中的引導(dǎo)邏輯單獨(dú)提取到一個(gè)文件中豌鹤,將其他業(yè)務(wù)模塊中的引導(dǎo)模塊邏輯剔除,從而減少重復(fù)打包的問(wèn)題枝缔,減小單文件容量布疙。
總結(jié)
通過(guò)對(duì)
html-webpack-plugin
的學(xué)習(xí),更方便的去構(gòu)建一張HTML頁(yè)面愿卸,同時(shí)處理靜態(tài)資源文件引入問(wèn)題灵临。對(duì)js
、css
趴荸、圖片等文件在生產(chǎn)環(huán)境進(jìn)行壓縮的方法儒溉,接觸了webpack
中tree shaking
的使用方法。使用CommonsChunkPlugin
分離公共模塊的方法发钝,并了解創(chuàng)建一個(gè)manifest
貨物清單文件的意義(分離webpack
的引導(dǎo)邏輯)顿涣。
下章會(huì)結(jié)合一個(gè)vue
多頁(yè)面實(shí)例進(jìn)行構(gòu)建測(cè)試波闹,并引入DLLPlugin
和DLLReferencePlugin
插件,優(yōu)化打包速度涛碑。
尾巴
在
tree shaking
這塊卡了很久精堕,一直得不到理想效果,通過(guò)排查 才發(fā)現(xiàn)是babel
提前轉(zhuǎn)義了ES6的modules
引發(fā)的蒲障,需要引入babel-preset-env
取消轉(zhuǎn)義ES6modules
才得以解決歹篓!