Tom*_*zyk 44 node.js webpack code-splitting webpack-4
在webpack 3配置中,我将使用下面的代码创建单独的vendor.js
块:
entry: {
client: ['./client.js'],
vendor: ['babel-polyfill', 'react', 'react-dom', 'redux'],
},
output: {
filename: '[name].[chunkhash].bundle.js',
path: '../dist',
chunkFilename: '[name].[chunkhash].bundle.js',
publicPath: '/',
},
plugins: [
new webpack.HashedModuleIdsPlugin(),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'runtime',
}),
],
Run Code Online (Sandbox Code Playgroud)
通过所有更改,我不知道如何使用Webpack 4.我知道这CommonChunksPlugin
已被删除,因此有不同的方法来实现它.我也阅读了本教程,但我仍然不确定是否提取运行时块并正确定义output
属性.
编辑: 不幸的是,我遇到了最流行的答案问题.看看我的答案.
glu*_*ued 26
这里有几个例子:https: //github.com/webpack/webpack/tree/master/examples
基于您的示例,我相信这转化为:
// mode: "development || "production",
entry: {
client: './client.js',
},
output: {
path: path.join(__dirname, '../dist'),
filename: '[name].chunkhash.bundle.js',
chunkFilename: '[name].chunkhash.bundle.js',
publicPath: '/',
},
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
chunks: 'initial',
name: 'vendor',
test: 'vendor',
enforce: true
},
}
},
runtimeChunk: true
}
Run Code Online (Sandbox Code Playgroud)
jha*_*Pac 23
您可以从entry属性中删除vendor并设置优化属性,如此...
entry: {
client: './client.js'
},
output: {
path: path.join(__dirname, '../dist'),
filename: '[name].chunkhash.bundle.js',
chunkFilename: '[name].chunkhash.bundle.js',
publicPath: '/',
},
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /node_modules/,
chunks: 'initial',
name: 'vendor',
enforce: true
},
}
}
}
Run Code Online (Sandbox Code Playgroud)
查看此源webpack示例
Car*_*uis 17
为了分离供应商和运行时,您需要使用该optimization
选项.
可能的Webpack 4配置:
// mode: 'development' | 'production' | 'none'
entry: {
client: ['./client.js'],
vendor: ['babel-polyfill', 'react', 'react-dom', 'redux'],
},
output: {
filename: '[name].[chunkhash].bundle.js',
path: '../dist',
chunkFilename: '[name].[chunkhash].bundle.js',
publicPath: '/',
},
optimization: {
runtimeChunk: 'single',
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
enforce: true,
chunks: 'all'
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
有关W4的更多信息可以在这个Webpack-Demo中找到.
此外,您可以实现相同的optimization.splitChunks.chunks
属性更改"all"
.在这里阅读更多
注意:您可以通过配置来配置它
optimization.splitChunks
.这些示例说明了一些关于块的内容,默认情况下它只适用于异步块,但optimization.splitChunks.chunks: "all"
对于初始块也是如此.
swa*_*993 13
为了减小供应商js包的大小。我们可以将节点模块软件包拆分为不同的捆绑文件。我提到此博客是 为了拆分由webpack生成的庞大的供应商文件。我最初使用的链接的要点:
optimization: {
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
maxInitialRequests: Infinity,
minSize: 0,
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name(module) {
// get the name. E.g. node_modules/packageName/not/this/part.js
// or node_modules/packageName
const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
// npm package names are URL-safe, but some servers don't like @ symbols
return `npm.${packageName.replace('@', '')}`;
},
},
},
},
}
Run Code Online (Sandbox Code Playgroud)
如果要分组多个包和块,然后分成不同的捆绑包,请参考以下要点。
optimization: {
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
maxInitialRequests: Infinity,
minSize: 0,
cacheGroups: {
reactVendor: {
test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
name: "reactvendor"
},
utilityVendor: {
test: /[\\/]node_modules[\\/](lodash|moment|moment-timezone)[\\/]/,
name: "utilityVendor"
},
bootstrapVendor: {
test: /[\\/]node_modules[\\/](react-bootstrap)[\\/]/,
name: "bootstrapVendor"
},
vendor: {
test: /[\\/]node_modules[\\/](!react-bootstrap)(!lodash)(!moment)(!moment-timezone)[\\/]/,
name: "vendor"
},
},
},
}
Run Code Online (Sandbox Code Playgroud)
Tom*_*zyk 11
过了一段时间我发现这个配置:
entry: {
vendor: ['@babel/polyfill', 'react', 'react-dom', 'redux'],
client: './client.js',
},
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
chunks: 'initial',
name: 'vendor',
test: 'vendor',
enforce: true
},
}
},
runtimeChunk: true
}
Run Code Online (Sandbox Code Playgroud)
无法以某种方式加载@babel/polyfill
导致浏览器不兼容错误...所以最近我查阅了更新的webpack文档,并找到了一种方法来创建正确加载的显式供应商块@babel/polyfill
:
const moduleList = ["@babel/polyfill", "react", "react-dom"];
...
entry: {
client: ["@babel/polyfill", "../src/client.js"]
}
optimization: {
runtimeChunk: "single",
splitChunks: {
cacheGroups: {
vendor: {
test: new RegExp(
`[\\/]node_modules[\\/](${moduleList.join("|")})[\\/]`
),
chunks: "initial",
name: "vendors",
enforce: true
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,我创建了一个包含所有代码的条目,然后指定splitChunks.cacheGroups.vendor.test
应将哪些模块拆分为供应商块.
不过,我不确定这是100%正确还是可以改进,因为这实际上是最混乱的事情之一.但是,这似乎与文档最接近,当我用webpack-bundle-analyzer检查它们时似乎产生了正确的块(只更新了已更改的块,其余部分在构建中保持不变)并修复了polyfill的问题.
Mot*_*ine 10
我找到了一种更短的方法来做到这一点:
optimization: {
splitChunks: { name: 'vendor', chunks: 'all' }
}
Run Code Online (Sandbox Code Playgroud)
当splitChunks.name
以字符串形式给出时,文档说:“指定一个字符串或一个始终返回相同字符串的函数会将所有公共模块和供应商合并到一个块中。” 与 结合使用splitChunks.chunks
,它将提取所有依赖项。
我想如果你这样做:
optimization: {
splitChunks: {
chunks: 'all',
},
runtimeChunk: true,
}
Run Code Online (Sandbox Code Playgroud)
这将创建一个vendors~
与runtime~
块给你.Sokra说默认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
}
}
}
Run Code Online (Sandbox Code Playgroud)
其中已包含a vendors
和default
bundle.在测试中,我还没有看到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);
}
Run Code Online (Sandbox Code Playgroud)
哪个适用于我的资产插件(针对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);
});
}
},
Run Code Online (Sandbox Code Playgroud)
所有这些都吐出了类似的东西:
<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"/>
Run Code Online (Sandbox Code Playgroud)
现在当我修改我的一个自定义JS文件时,只有其中一个JS块发生了变化.运行时和供应商包都不需要更新.
如果我添加一个新的JS文件,require
它仍然没有更新运行时.我认为因为新文件将被编译到主包中 - 它不需要在映射中,因为它不是动态导入的.如果我import()
这导致代码分裂,则运行时会更新.这些厂商包也似乎已经改变了-我不知道为什么.我认为应该避免这样做.
我还没弄明白如何进行每个文件的哈希.如果修改与.css文件相同的块的.js文件,则它们的文件名都将随之改变[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;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
61912 次 |
最近记录: |