在上篇中搭建了
vue
的基本腳手架,爲了加快腳手架打包項目的構建速度和減小打包代碼的體積,下面在上一篇的基礎上添磚加瓦,完成腳手架的優化。javascript
腳手架是在原有的基礎上構建的,因此基本的目錄結構相相似。不過加上了對JS
壓縮,CSS
代碼壓縮(tree shake),引入了dllPlugin
打包不常變更的類庫生成動態連接庫,加入happypack
開啓多進程打包,加快構建的速度,下面也會說到運用npm script
,經過sftp
把打包的文件上傳到部署的目錄,避免手動上傳。css
腳手架地址:https://github.com/Harhao/webpack/tree/dev
html
|-- .gitignore
|-- build
| |-- webpack.base.conf.js
| |-- webpack.dev.conf.js (開發環境打包配置)
| |-- webpack.dll.conf.js (生成dll動態連接庫)
| `-- webpack.prod.conf.js(生產環境打包配置)
|-- config
| `-- index.js (打包配置參數)
|-- dist (生產環境打包目錄)
| |-- index.html
| |-- precache-manifest.2df00ef5798fdac7218a2cecb8233a17.js(緩存清單)
| |-- service-worker.js(service-worker文件)
| `-- static
| |-- css
| | `-- main_de7bb505.css
| `-- js
| |-- framework_2f05dfbce1b06dd8.js
| |-- framework_2f05dfbce1b06dd8.js.gz (開啓gz壓縮打包結構)
| |-- main_2f05dfbce1b06dd8.js
| `-- vendors~main_2f05dfbce1b06dd8.js
|-- dll(開啓dllplugin打包的連接庫)
| |-- axios.dll.js
| |-- axios.manifest.json
| |-- framework.dll.js
| `-- framework.manifest.json
|-- package.json
|-- postcss.config.js
|-- public
| `-- index.html
`-- src(開發主目錄)
|-- App.vue
|-- main.js
|-- router
| `-- index.js
`-- views
|-- admin
| `-- index.vue
`-- login
`-- index.vue
複製代碼
在webpack.dev.conf.js
開發環境配置文件中,增長了happypack
、Dllplugin
動態連接。happypack
主要是開啓多進程打包文件,加快打包構建速度。而Dllplugin
主要是對一些不常變更的類庫提取打包,在再次編譯打包過程,能夠免除再次的打包。vue
下面是webpack.dev.conf.js
開發環境全瞰,主要增長了DllReferencePlugin
、happypack
、add-asset-html-webpack-plugin
插件。下面對各自的做用詳細說明。java
const path = require("path")
const HappyPack = require("happypack")
const VueLoaderPlugin = require("vue-loader/lib/plugin")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const DllReferencePlugin = require('webpack/lib/DllReferencePlugin')
const AddAssetHtmlWebpackPlugin = require("add-asset-html-webpack-plugin")
const HotModuleReplacementPlugin = require("webpack/lib/HotModuleReplacementPlugin")
const config = require("../config/index")
module.exports = {
mode: "development",
devtool: "cheap-module-eval-source-map",
entry: path.resolve(__dirname, "../src/main.js"),
output: {
filename: "[name]_[hash:16].js",
path: path.resolve(__dirname, "../dist"),
publicPath: '/'
},
resolve: {
modules: ["node_modules"],
alias: {
"@": path.resolve(__dirname, '../src')
},
extensions: [".js", ".json", ".vue", ".scss"]
},
module: {
rules: [{
test: /\.js$/,
use: ["happypack/loader?id=babel"],
exclude: path.resolve(__dirname, '../node_modules')
},
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "postcss-loader", "sass-loader"]
}, {
test: /\.vue$/,
use: ["vue-loader"]
}, {
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
use: ["happypack/loader?id=url"]
}]
},
plugins: [
new DllReferencePlugin({
manifest: require('../dll/framework.manifest.json')
}),
new DllReferencePlugin({
manifest: require('../dll/axios.manifest.json')
}),
new HappyPack({
id: 'babel',
loaders: ["babel-loader?cacheDirectory"]
}),
new HappyPack({
id: 'url',
loaders: ["url-loader"]
}),
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "../public/index.html"),
filename: 'index.html',
inject: 'body'
}),
new AddAssetHtmlWebpackPlugin({
filepath: path.resolve(__dirname, '../dll/framework.dll.js') // 對應的 dll 文件路徑
}),
new AddAssetHtmlWebpackPlugin({
filepath: path.resolve(__dirname, '../dll/axios.dll.js') // 對應的 dll 文件路徑
}),
new HotModuleReplacementPlugin()
],
devServer: {
...config.dev.server
},
/** * 開啓webpack對文件變更的監聽 */
watch: true,
watchOptions: {
ignored: /node_modules/,
aggregateTimeout: 300,
poll: 1000
}
}
複製代碼
.dll
爲後綴的文件,這些文件稱爲動態連接庫。提供爲其餘模塊使用的函數和數據。在一些不常變更的類庫vuejs
、vue-router
、vuex
,咱們能夠打包成動態連接庫,動態連接庫只須要編譯一次,在以後的構建過程當中被動態連接庫包含的模塊將不會在從新編譯。加快咱們構建的速度。配置dll
動態連接庫,須要另一個配置文件webpack.dll.conf.js
。node
Dllplugin
插件專門用於單獨的webpack配置中,以建立僅限dll的捆綁包。它建立了一個manifest.json
文件,用於[DllReferencePlugin
]映射依賴項。下面webpack.dll.conf.js
經過配置生成dll
動態連接庫。linux
經過配置npm script
生成動態連接庫文件,在package.json
定義了npm run build:dll
打包生成dll
動態連接庫。webpack
生成下面的dll
動態連接庫,在運行開發環境前,須要先打包生成dll
動態連接庫,這樣開發環境打包時會自動引用動態連接庫。其中framework
和axios
都是咱們自定義命名,menifest
是類庫的映射文件。ios
有動態連接庫,還須要在webpack.dev.conf.js
文件中對連接庫的引入。DllReferencePlugin
會去 manifest.json
文件讀取 name
字段的值, 把值的內容做爲在從全局變量中獲取動態連接庫中內容時的全局變量名。而AddAssetHtmlWebpackPlugin
是將JavaScript或CSS資源添加到生成的HTML中,這裏使用該插件將dll
動態連接庫添加到index.html
中。css3
生成index.html
源碼已經加入framework.dll.js
和axios.dll.js
,源碼結構以下所示:
HappyPack
經過並行
轉換文件使得初始webpack
構建更快。happypack
經過開啓多個子進程並行打包文件,使文件構建速度明顯加快。在使用happypack
過程當中,發現happypack
對scss
支持度不高。因此在webpack.dev.conf.js
沒有對scss
文件進行處理。在happypack
的官網案例中,happypack
對less
的支持度比較高。happypack
使用比較簡單,以下所示,下面對以js
爲後綴的文件用happypack進行打包。happypack
默認開啓的進程是3個,能夠自定義配置,詳細參數能夠參照官方文檔說明。
開啓happypack
成功打包的構建流程圖
在webpack.prod.conf.js
生產配置文件中,添加了workbox-webpack-plugin
漸進行PWA
的資源緩存;optimize-css-assets-webpack-plugin
對css
代碼壓縮處理;compression-webpack-plugin
對大文件進行gz
壓縮;UglifyJsPlugin
對js
文件壓縮處理,UglifyJsPlugin
在上篇已作說明。
webpack.prod.conf.js
生產配置環境文件,沒有對不常更改的類庫(vuejs
)生成動態連接庫。利用webpack4
內部提取公共代碼,進行了處理。總瞰以下所示:
const path = require("path")
const VueLoaderPlugin = require("vue-loader/lib/plugin")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const { CleanWebpackPlugin } = require("clean-webpack-plugin")
const UglifyJsPlugin = require("uglifyjs-webpack-plugin")
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const WorkboxPlugin = require('workbox-webpack-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const CompressionWebpackPlugin = require('compression-webpack-plugin')
module.exports = {
mode: "production",
entry: {
main: path.resolve(__dirname, "../src/main.js"),
framework: ["vue", "vue-router", "vuex"]
},
output: {
filename: "static/js/[name]_[hash:16].js",
path: path.resolve(__dirname, "../dist"),
publicPath: './'
},
resolve: {
modules: ["node_modules"],
alias: {
"@": path.resolve(__dirname, '../src')
},
extensions: [".js", ".json", ".vue", ".scss"]
},
module: {
rules: [{
test: /\.js$/,
use: [{
loader: "babel-loader",
options: {
presets: ['@babel/preset-env']
}
}],
exclude: /node_modules/
},
{
test: /\.scss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
"css-loader",
"postcss-loader",
"sass-loader"
],
exclude: /node_modules/
},
{
test: /\.vue$/,
use: ["vue-loader"],
exclude: /node_modules/
}]
},
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
title: '自搭建webpack腳手架',
template: path.resolve(__dirname, "../public/index.html"),
filename: 'index.html',
inject: 'body',
minify: {
removeComments: true,//移除註釋
collapseWhitespace: true,//移除空白字符串
removeAttributeQuotes: true //移除雙引號
}
}),
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: 'static/css/[name]_[chunkhash:8].css',
chunkFilename: '[id].css',
}),
new WorkboxPlugin.GenerateSW({
clientsClaim: true,
skipWaiting: true
}),
new CompressionWebpackPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: /(\.js$|\.css$)/,
threshold: 10240,
minRatio: 0.8
})
],
optimization: {
usedExports:true,
minimizer: [
new UglifyJsPlugin({
test: /\.js(\?.*)?$/i
}),
new OptimizeCSSAssetsPlugin({
// cssProcessorOptions: true? {map: { inline: false }}:{}
})
],
splitChunks: {
chunks: "all",
minChunks: 1,
minSize: 0,
cacheGroups: {
framework: {
test: "framework",
name: "framework",
enforce: true
}
}
}
}
}
複製代碼
漸進式Web應用程序(或PWA
)使咱們開發的應用在離線後,依然能夠訪問。主要依靠了Service Workers
的Web技術實現。在webpack
社區提供了workbox-webpack-plugin
方便實現PWA
功能。
在wenbpack.prod.conf.js
配置好插件workbox-webpack-plugin
後,須要在項目的入口文件裏註冊serviceWorker
。這裏展現的vuejs
的入口文件main.js
運行生產環境打包腳本命令,有2個額外的文件正在生成; service-worker.js
和precache-manifest.18d731d6b692ffdc910ac5548db2f8c0.js
。service-worker.js
是Service Worker
文件,precache-manifest.18d731d6b692ffdc910ac5548db2f8c0.js
是一個service-worker.js
須要運行的文件。您本身生成的文件可能會有所不一樣; 但你應該有一個service-worker.js
文件。
接下來要離線環境進行測試,查看service-worker
離線緩存的效果。webpack
官網提供了一個http-server
對service-worker
測試。
service worker
已經生效,斷開http-server
服務,刷新網頁,依舊能夠正確顯示到須要的資源。
optimize-css-assets-webpack-plugin
主要是對打包的css
文件進行壓縮處理。在webpack4
版本中,設置mode
模式爲production
,會自動對js
代碼進行壓縮處理,其實底下是用uglifyjs-webpack-plugin
進行壓縮。可是css
文件仍是須要手動進行壓縮。而optimize-css-assets-webpack-plugin
起的就是壓縮css
做用。
打包壓縮的文件以下所示,可見css
樣式是壓縮狀態的。
.entry[data-v-7ba5bd90]{color:red;-webkit-transform:scale(.8);-ms-transform:scale(.8);transform:scale(.8)}.admin[data-v-2ba5fe30]{color:#333}
複製代碼
optimize-css-assets-webpack-plugin
在webpack.prod.conf.js
配置使用:
postcss
是一個用JavaScript
工具和插件轉換 CSS
代碼的工具。postcss
加上autoprefixer
幫助咱們在新的css3
屬性自動添加廠商前綴。
在package.json
文件添加如下字段:
"browserslist": [
"last 5 version",
">1%",
"ie>=8"
]
複製代碼
在項目的根目錄下,建立postcss.config.js
,內容以下:
module.exports = {
plugins: {
autoprefixer: {
}
}
};
複製代碼
在webpack4
中使用tree shake
剔除沒有使用的JS
代碼比較簡單,直接在optimization
中開啓usedExports
,不過JS tree shake
只對ES6
語法有效,因此要度量使用。關於對於css
的tree shake
,有朋友建議是purecss
對沒有使用的css
代碼剔除,不過實驗了一下,感受沒有效果,就沒有作推薦。
在打包生成生產環境的項目中,想自動上傳打包目錄到開發測試環境預覽,能夠利用webpack-deploy-sftp
插件集成到webpack.prod.conf.js
中,打包完成會自動上傳到linux
開發環境中。
npm script
的方法,能夠本身編寫上傳腳本,下面是本身編寫的一個參考:
const Client = require("ssh2-sftp-client")
const fs = require('fs')
const path = require('path')
//有關帳號密碼端口設置文件
const config = require('./config')
//本地須要上傳的目錄
const filePath = './dist'
//遠程地址
const remotePath = '/home/xx/xx'
const sftp = new Client()
let tmpPath = ''
sftp.connect(config).then(() => {
console.log("鏈接成功")
fileTravel(filePath)
})
sftp.on('end', () => {
console.log('end event')
})
sftp.on('close', () => {
console.log('close event')
})
function fileTravel(filePath) {
fs.readdir(filePath, function (err, files) {
if (err) {
console.log(err)
} else {
files.forEach(function (filename) {
const filedir = path.join(filePath, filename)
console.warn(`upload file: ${filedir}`)
let url = filedir.substr(filedir.indexOf('\\') + 1)
url = url.replace(/\\/g, '/')
fs.stat(filedir, function (error, stats) {
if (error) {
console.error(`獲取文件stats失敗`)
} else {
const isFile = stats.isFile()
const isDir = stats.isDirectory()
if (isDir) {
tmpPath = `${remotePath}/${url}`
sftp.mkdir(tmpPath, true).then(() => {
fileTravel(filedir);
}).catch(err => {
fileTravel(filedir)
})
}
if (isFile) {
sftp.put(filedir, `${remotePath}/${url}`)
}
}
})
})
}
})
}
複製代碼
定義npm script
命令,執行上傳打包的文件夾。
在webpack.dev.conf.js
開發環境中使用了dllPlugin
的動態連接庫方法提取公用的類庫,加快構建速度。在生產環境中,採用的是webpack4
內置功能提取公用代碼。在webpack3
中採起CommonChunkPlugin
提取公共模塊和第三方庫。在webpack4
已經不建議使用該插件,而是使用內置的方法。
在上面使用splitChunks
提取公共模塊framework
,可是打包出來的模塊仍是比較大,在瀏覽器下載包模塊時候時間會比較長,因此在對打包出來,體積比較大的模塊使用compression-webpack-plugin
打包成gz
包。配合後端開啓gz
支持,這樣能夠加快資源下載的速度。
把webpack.dev.conf.js
和webpack.prod.conf.js
文件的公用部門提取到webpack.base.conf.js
中,經過webpack-merge
合併不一樣部分。
webpack.base.conf.js
公用部份以下:
wepack.dev.conf.js
剔除公用的部分,其餘配置項以下所示:
wepack.prod.conf.js
剔除公用的部分,其餘配置項以下所示:
若是喜歡能夠給個贊~或星~喲
GitHub地址: github.com/Harhao/webp…