假定我們的項目目錄為如下的樣子:
- root/
- assets/
- app/
- global.js
- index/
- index.js
- auth/
- login.js
- register.js
- ...
- webpack.config.js
- public/
- assets/
- build/
使用如下的 webpack 配置:
var webpack = require('webpack');
var fs = require('fs');
var path = require('path');
var glob = require('glob');
const debug = process.env.NODE_ENV !== 'production';
function entries (globPath) {
var files = glob.sync(globPath);
var entries = {}, entry, dirname, basename;
for (var i = 0; i < files.length; i++) {
entry = files[i];
dirname = path.dirname(entry);
basename = path.basename(entry, '.js');
entries[path.join(dirname, basename)] = './' + entry;
}
return entries;
}
module.exports = {
entry: entries('app/**/*.js'),
output: {
path: path.join(__dirname, '..', 'public', 'assets', 'build'),
publicPath: '/assets/build/',
filename: '[name]' + (debug ? '' : '-[chunkhash]') + '.js',
chunkFilename: '[id]' + (debug ? '' : '-[chunkhash]') + '.js'
},
plugins: [
function () {
this.plugin('done', function (stats) {
stats = stats.compilation.getStats().toJson({
hash: true,
publicPath: true,
assets: true,
chunks: false,
modules: false,
source: false,
errorDetails: false,
timings: false
});
var json = {}, chunk;
for (var key in stats.assetsByChunkName) {
if (stats.assetsByChunkName.hasOwnProperty(key)) {
chunk = stats.assetsByChunkName[key];
json[key + '.js'] = chunk[0];
}
}
fs.writeFileSync(
path.join(__dirname, '..', 'public', 'assets', 'build', 'rev-manifest.json'),
JSON.stringify(json, null, 2)
);
});
}
]
};
這樣,我們就可以得到形如這樣的構建輸出:
- root/
- assets/
- ...
- public/
- assets/
- build/
- rev-manifest.json
- app/
- global.js
- auth/
- login.js
- register.js
- ...
意義何在???
關鍵在於 rev-manifest.json
文件,我們查看一下文件內容:
{
"app/global.js": "app/global.js",
"app/index/index.js": "app/index/index.js",
"app/auth/login.js": "app/auth/login.js",
"app/auth/register.js": "app/auth/register.js",
}
意義何在???
好吧,我們再看一下在生產環境下的構建輸出:
{
"app/global.js": "app/global-6ff91e44b26765ae797a.js",
"app/index/index.js": "app/index/index-d294c62e36a91fa7237d.js",
"app/auth/login.js": "app/auth/login-f04b1d5a3cffac4d70aa.js",
"app/auth/register.js": "app/auth/register-502d794e8e0c7f1a230d.js",
}
如果配合模板中的函數:
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="{{ assets_url('app/index/index.js') }}"></script>
</head>
<body>
</body>
</html>
assets_url
函數可以直接獲取 rev-manifest.json
內容,根據給定的 key
得到對應的構建文件的可訪問路徑,自動的根據不同的環境獲取到正確的引用結果。
同時,我們可以在源代碼目錄里面,根據需求對代碼進行模塊化管理,構建出來的代碼結構會和我們源代碼中管理的一致。
這樣一來,既可以享受構建系統的優勢,又無需在新增或修改模塊時改動 webpack.config.js
,是不是很方便呢?