Я думаю, если вы сделаете это:
optimization: {
splitChunks: {
chunks: 'all',
},
runtimeChunk: true,
}
Он создаст для вас блоки vendors~
и runtime~
. Сокра сказал, что значение по умолчанию для splitChunks
таково:
splitChunks: {
chunks: "async",
minSize: 30000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
name: true,
cacheGroups: {
default: {
minChunks: 2,
priority: -20
reuseExistingChunk: true,
},
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
}
}
}
Которая уже включает в себя пакеты vendors
и default
. При тестировании я не видел появления default
связки.
Я не знаю, каков ожидаемый рабочий процесс для включения этих файлов, но я написал эту вспомогательную функцию на PHP:
public static function webpack_asset($chunkName, $extensions=null, $media=false) {
static $stats;
if($stats === null) {
$stats = WxJson::loadFile(WX::$path.'/webpack.stats.json');
}
$paths = WXU::array_get($stats,['assetsByChunkName',$chunkName],false);
if($paths === false) {
throw new \Exception("webpack asset not found: $chunkName");
}
foreach($stats['assetsByChunkName'] as $cn => $files) {
if(self::EndsWith($cn, '~' . $chunkName)) {
// prepend additional supporting chunks
$paths = array_merge($files, $paths);
}
}
$html = [];
foreach((array)$paths as $p) {
$ext = WXU::GetFileExt($p);
if($extensions) {
if(is_array($extensions)) {
if(!in_array($ext,$extensions)) {
continue;
}
} elseif(is_string($extensions)) {
if($ext !== $extensions) {
continue;
}
} else {
throw new \Exception("Unexpected type for \$extensions: ".WXU::get_type($extensions));
}
}
switch($ext) {
case 'js':
$html[] = WXU::html_tag('script',['src'=>$stats['publicPath'].$p,'charset'=>'utf-8'],'');
break;
case 'css':
$html[] = WXU::html_tag('link',['href'=>$stats['publicPath'].$p,'rel'=>'stylesheet','type'=>'text/css','media'=>$media],null); // "charset=utf-8" doesn't work in IE8
break;
}
}
return implode(PHP_EOL, $html);
}
Что работает с моим плагином ресурсов (обновлено для WP4):
{
apply: function(compiler) {
//let compilerOpts = this._compiler.options;
compiler.plugin('done', function(stats, done) {
let assets = {};
stats.compilation.namedChunks.forEach((chunk, name) => {
assets[name] = chunk.files;
});
fs.writeFile('webpack.stats.json', JSON.stringify({
assetsByChunkName: assets,
publicPath: stats.compilation.outputOptions.publicPath
}), done);
});
}
},
Все это выплевывает что-то вроде:
<script src="/assets/runtime~main.a23dfea309e23d13bfcb.js" charset="utf-8"></script>
<link href="/assets/chunk.81da97be08338e4f2807.css" rel="stylesheet" type="text/css"/>
<script src="/assets/chunk.81da97be08338e4f2807.js" charset="utf-8"></script>
<link href="/assets/chunk.b0b8758057b023f28d41.css" rel="stylesheet" type="text/css"/>
<script src="/assets/chunk.b0b8758057b023f28d41.js" charset="utf-8"></script>
<link href="/assets/chunk.00ae08b2c535eb95bb2e.css" rel="stylesheet" type="text/css" media="print"/>
Теперь, когда я изменяю один из моих пользовательских файлов JS, изменяется только один из этих фрагментов JS. Ни среду выполнения, ни комплект поставщиков обновлять не нужно.
Если я добавлю новый файл JS и require
его, среда выполнения все равно не будет обновлена. Я думаю, потому что новый файл будет просто скомпилирован в основной пакет - он не должен быть в сопоставлении, потому что он не импортируется динамически. Если я import()
это вызывает разделение кода, тогда обновляется среда выполнения. Пакет поставщиков также, похоже, изменился - я не знаю почему. Я думал, что этого следовало избежать.
Я также не понял, как делать хеши для каждого файла. Если вы измените файл .js, который является тем же фрагментом, что и файл .css, оба их имени изменятся на [chunkhash]
.
Я обновил плагин ресурсов выше. Я думаю, что порядок, в котором вы включаете теги <script>
, может иметь значение ... это будет поддерживать этот порядок AFAICT:
const fs = require('fs');
class EntryChunksPlugin {
constructor(options) {
this.filename = options.filename;
}
apply(compiler) {
compiler.plugin('done', (stats, done) => {
let assets = {};
// do we need to use the chunkGraph instead to determine order??? https://gist.github.com/sokra/1522d586b8e5c0f5072d7565c2bee693#gistcomment-2381967
for(let chunkGroup of stats.compilation.chunkGroups) {
if(chunkGroup.name) {
let files = [];
for(let chunk of chunkGroup.chunks) {
files.push(...chunk.files);
}
assets[chunkGroup.name] = files;
}
}
fs.writeFile(this.filename, JSON.stringify({
assetsByChunkName: assets,
publicPath: stats.compilation.outputOptions.publicPath
}), done);
});
}
}
module.exports = EntryChunksPlugin;
person
mpen
schedule
16.03.2018