代码拆分将一个包的导出单独导出到不同的包
Code-splitting separate exports from a package to different bundles
我有一个使用大量包的 Gatsby 站点。其中一个软件包是从我们的 monorepo 发布的:@example/forms
。该包包含许多命名的导出,一个用于我们网站上使用的每个表单组件。有相当多的形式,有些是相对复杂的多步形式,规模不小。
目前,Gatsby/Webpack 在 treeshaking 方面做得很好,并且确实产生了大量的 bundle,一些公共 bundle 和一个用于站点的每个页面,包含任何本地资产或仅使用的组件在那个页面上。但是,@example/forms
中的所有组件都被添加到 commons
包中,尽管大多数组件仅在一个页面上使用。这导致在每个页面上加载的 commons
包不必要的膨胀。
如果感觉 @example/forms
中的各个组件应该可以拆分成特定于页面的包,但我不确定我是否希望太多。例如,如果仅在第 4 页使用表格 A,我希望仅将表格 A 添加到第 4 页的捆绑包中。
这是受支持的东西吗?如果是,是什么阻止了这种情况的发生。
@example/forms
被转译,ES6 导出保持不变,sideEffects
在其 package.json
中设置为 false
。
它的 main
文件是 index.js
,它从它们自己的文件中(重新)导出所有表单组件作为单独的命名导出:
export {default as FormA} from './forms/formA'
export {default as FormB} from './forms/formB'
...
另一件可能相关的事情是,所有来自 @example/forms
的导出都是 在 Gatsby 站点中使用的,只是在单独的页面上。看起来 tree-shaking 可能不能跨束使用,即首先执行 tree shaking,然后将剩下的分成束。使用该逻辑,@example/forms
将在多个页面上使用并移至公共区域。然而,这绝对不是最优的,希望不是正在发生的事情。
tree-shaking 过程是缩小步骤的一部分,实际上处于后期阶段,因为不可能颠倒顺序,先 tree-shaking 然后分块。
但是您可以使用一些启发式方法事先拆分您的表单库
- 基本的方法是使用
splitChunks
将这个 @example/forms
模块拆分成一个单独的块作为一个整体,这将减少公用膨胀 & 在第一种形式上使用所有形式已加载。
// webpack.config.js
module.exports = {
...
optimization: {
splitChunks: {
cacheGroups: {
formComponents: {
chunks: 'all',
enforce: true,
minChunks: 1,
name: 'form-components',
priority: 10,
test: /[\\/]node_modules[\\/]@example[\\/]forms[\\/]/,
},
},
},
},
...
};
- 根据一些启发式方法为
@example/forms
模块中的每个表单创建一个块,在我的示例中,我 "grouping" 所有项目都基于表单路径。
// webpack.config.js
module.exports = {
...
optimization: {
splitChunks: {
cacheGroups: {
formComponents: {
chunks: 'all',
minChunks: 1,
name(module) {
const libPath = path.resolve(path.join('node_modules/@example/forms'))
const folderBasedChunk = path.relative(libPath, module.context);
const hash = crypto.createHash('sha1');
hash.update(folderBasedChunk)
return hash.digest('hex').substring(0, 8)
},
priority: 10,
reuseExistingChunk: true,
enforce: true,
test: /[\\/]node_modules[\\/]@example[\\/]forms[\\/]src[\\/]forms[\\/]/,
},
},
},
...
};
您可以查看我创建的模拟场景的小示例。
https://github.com/felixmosh/webpack-module-split-example
希望对您有所帮助
我有一个使用大量包的 Gatsby 站点。其中一个软件包是从我们的 monorepo 发布的:@example/forms
。该包包含许多命名的导出,一个用于我们网站上使用的每个表单组件。有相当多的形式,有些是相对复杂的多步形式,规模不小。
目前,Gatsby/Webpack 在 treeshaking 方面做得很好,并且确实产生了大量的 bundle,一些公共 bundle 和一个用于站点的每个页面,包含任何本地资产或仅使用的组件在那个页面上。但是,@example/forms
中的所有组件都被添加到 commons
包中,尽管大多数组件仅在一个页面上使用。这导致在每个页面上加载的 commons
包不必要的膨胀。
如果感觉 @example/forms
中的各个组件应该可以拆分成特定于页面的包,但我不确定我是否希望太多。例如,如果仅在第 4 页使用表格 A,我希望仅将表格 A 添加到第 4 页的捆绑包中。
这是受支持的东西吗?如果是,是什么阻止了这种情况的发生。
@example/forms
被转译,ES6 导出保持不变,sideEffects
在其 package.json
中设置为 false
。
它的 main
文件是 index.js
,它从它们自己的文件中(重新)导出所有表单组件作为单独的命名导出:
export {default as FormA} from './forms/formA'
export {default as FormB} from './forms/formB'
...
另一件可能相关的事情是,所有来自 @example/forms
的导出都是 在 Gatsby 站点中使用的,只是在单独的页面上。看起来 tree-shaking 可能不能跨束使用,即首先执行 tree shaking,然后将剩下的分成束。使用该逻辑,@example/forms
将在多个页面上使用并移至公共区域。然而,这绝对不是最优的,希望不是正在发生的事情。
tree-shaking 过程是缩小步骤的一部分,实际上处于后期阶段,因为不可能颠倒顺序,先 tree-shaking 然后分块。
但是您可以使用一些启发式方法事先拆分您的表单库
- 基本的方法是使用
splitChunks
将这个@example/forms
模块拆分成一个单独的块作为一个整体,这将减少公用膨胀 & 在第一种形式上使用所有形式已加载。
// webpack.config.js
module.exports = {
...
optimization: {
splitChunks: {
cacheGroups: {
formComponents: {
chunks: 'all',
enforce: true,
minChunks: 1,
name: 'form-components',
priority: 10,
test: /[\\/]node_modules[\\/]@example[\\/]forms[\\/]/,
},
},
},
},
...
};
- 根据一些启发式方法为
@example/forms
模块中的每个表单创建一个块,在我的示例中,我 "grouping" 所有项目都基于表单路径。
// webpack.config.js
module.exports = {
...
optimization: {
splitChunks: {
cacheGroups: {
formComponents: {
chunks: 'all',
minChunks: 1,
name(module) {
const libPath = path.resolve(path.join('node_modules/@example/forms'))
const folderBasedChunk = path.relative(libPath, module.context);
const hash = crypto.createHash('sha1');
hash.update(folderBasedChunk)
return hash.digest('hex').substring(0, 8)
},
priority: 10,
reuseExistingChunk: true,
enforce: true,
test: /[\\/]node_modules[\\/]@example[\\/]forms[\\/]src[\\/]forms[\\/]/,
},
},
},
...
};
您可以查看我创建的模拟场景的小示例。 https://github.com/felixmosh/webpack-module-split-example
希望对您有所帮助