前言
從webpack3
一路到webpack4
,剛開始一直抱著搭起來能用的態(tài)度.直到開始工作,大大小小的項目接觸了四五個,慢慢有了一個適合自己使用的腳手架.在開發(fā)過程中有遇到很多不順手的地方:
由于項目需要,開發(fā)以及部署時的后臺
ip
地址經(jīng)常在變化,開發(fā)時會抽出一個單獨的js
文件定義所有這些外部的地址,便于管理.但是在打包之后就被webpack
打包了,如果要修改地址又要重新打包,過于繁瑣.個人喜歡
less
,但是less
不能自定義函數(shù),以及無法定義全局的變量
.比如想在variable.less
中定義頁面公用的一些變量,方便后期調(diào)整頁面布局.但是需要在每個用到這些變量的.vue
文件中單獨引入,太過累贅.
慢慢的解決問題,直到我發(fā)現(xiàn)我的webpack.config.js
居然有四五百行代碼,這太亂了.于是決定重新在構(gòu)造一個項目腳手架,進(jìn)行優(yōu)化.
重修之路
創(chuàng)建項目基礎(chǔ)結(jié)構(gòu),一步一步慢慢添加
├── dist // 打包后目錄
├── src
│ ├── assets // 全局的靜態(tài)文件,無法打包時
│ │ └── img
│ ├── config // 數(shù)據(jù)后臺IP地址配置文件
│ │ └── ip.config.js
│ └── index.js // 入口文件
├── package.json
└── webpack.config.js // webpack配置文件
先了解幾個webpack插件
-
clean-webpack-plugin
: 每個打包之前清理dist
文件夾 -
copy-webpack-plugin
: 復(fù)制文件或者文件夾到打包目錄 -
html-webpack-plugin
: 生成html
模板以及自動引入打包后文件
我們希望assets/
下的文件原封不動的復(fù)制到dist/
目錄下,比如有一些圖片webpack
無法打包時,我們就在assets
下新建一個img
文件夾,把這些圖片放進(jìn)去,打包時copy-webpack-plugin
就會自動就img
整個文件夾復(fù)制到dist
對于config/
,打包后我希望它一樣是在dist/config
下.
然后我們需要在html
文件中加入script
標(biāo)簽引入dist/config
目錄下所有的.js
文件
- 安裝
npm i -D copy-webpack-plugin clean-webpack-plugin html-webpack-plugin
- 使用
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
...
plugins: [
new CleanWebpackPlugin(),
new CopyWebpackPlugin([
{from: 'src/config/*.js', to: 'config/', toType: 'dir', flatten: true},
{from: 'src/assets/', toType: 'dir'}
]),
new HtmlWebpackPlugin({
inject: false,
template: require('html-webpack-template'),
title: '測試輸出',
appMountId: 'app',
meta: [
{
name: 'viewport',
content: 'width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0'
}
],
bodyHtmlSnippet: "<script src='config/ip.config.js'></script>"
})
]
...
}
- 說明
clean-webpack-plugin
使用是非常簡單的,默認(rèn)就是刪除dist
文件夾,安裝引入之后,直接在plugins
實例化即可.
copy-webpack-plugin
使用
-
from
:定義操作目標(biāo) -
to
: 復(fù)制到dist
文件夾下的哪里 -
toType
: 類型, 文件或者文件夾` -
flatten
: 是否按照本來的目錄復(fù)制, 默認(rèn)是false
下面再說說最強(qiáng)大的html-webpack-plugin
,會自動生成html
模板,也可以以自己定義的html
文件為模板
必須的參數(shù)
inject
: false,
template
:html
文件,如果是自己定義的則是文件所在路徑可選參數(shù)
title
: 標(biāo)題,
appMountId
: 插入的div
的id
meta
:meta
選項
headHtmlSnippet
: 插入head
的html
模板,這里我們需要插入config
目錄下所有的js
文件, 所以我們需要定義一個函數(shù),如果config
目錄下文件多的話我們手動一個一個去加就太浪費時間了,而且效率太低,加一個就要改一次配置
/**
* 獲取script標(biāo)簽字符串
* @param {String} source [源目標(biāo)目錄]
* @param {[String]} targetDir [生成的文件夾]
* @return {[String]} [指定文件夾下的js文件的script標(biāo)簽]
*/
function getConfigScript(source, targetDir) {
let configFiles = fs.readdirSync(source, {});
let jsFiles = configFiles.filter( file => {
return file.indexOf('.js') !== -1;
})
let scripts = jsFiles.map( file => {
return `<script src="${targetDir + file}"> </script>`
})
return scripts.join('\n');
}
改html-webpack-plugin
的bodyHTMLSnippet
bodyHtmlSnippet: getConfigScript('./src/config', 'config/')
- 打包一下,看看我們生成的是什么
├── config
│ └── ip.config.js
├── img
│ └── test.png
├── index.html
└── js
└── app.bundle.js
看一下index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta content="ie=edge" http-equiv="x-ua-compatible">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<title>測試輸出</title>
<script src="config/ip.config.js"> </script>
</head>
<body>
<div id="app">
</div>
<script src="js/app.bundle.js" type="text/javascript"></script>
</body>
</html>
到現(xiàn)在我們已經(jīng)成功實現(xiàn)了初始的基礎(chǔ)需求了.
更多html-webpack-plugin配置
但是我們使用webpack
往往不止會用來打包js
還有css
,img
等等,如果我們都寫在一個文件里的話代碼就會越來越多,到最后可讀性會越來越差,而且不利于閱讀以及再次復(fù)用,并且開發(fā)環(huán)境以及生產(chǎn)環(huán)境有一些配置是不用的,所以我們將不同的配置代碼拆開為dev
以及prod
,公用的定義為common
.我們可以使用webpack-merge
合并不同環(huán)境下的配置
- 新建一個
script
文件夾用來存放配置腳本, 將現(xiàn)在的webpack.config.js
改為webpack.common.js
, 新建webpack.dev.js
和webpack.prod.js
- 修改
npm
啟動腳本
"scripts": {
"start": "webpack-dev-server --open --config script/webpack.dev.js",
"build": "webpack --config script/webpack.prod.js"
}
開發(fā)模式
- 開啟
devtool
的source-map
便于調(diào)試 - 使用
webpack-dev-server
// webpack.dev.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const webpack = require('webpack');
module.exports = merge(common, {
mode: 'development',
output: {
publicPath: '/'
},
devtool: 'source-map',
devServer: {
contentBase: './dist',
host: '0.0.0.0',
port: 8001,
index: 'index.html',
open: true,
hot: true
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
})
生產(chǎn)模式
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'production'
})
webpack
生產(chǎn)模式下會自動對js
文件進(jìn)行壓縮混淆,但是我們還希望對圖片以及css
文件進(jìn)行處理.