1

我们最近一直在考虑将代码拆分到我们复杂的 Web 应用程序中,以减少主包的大小。我们关注的主要部分是使用 webpack 和 react-loadable 进行动态导入。

我遇到了一些我认为是相当大的问题,举个例子:

const FirstChild = Loadable({
    loader: () => import('some/file/path/FirstChild.jsx') 
});
const SecondChild = Loadable({
    loader: () => import('some/file/path/SecondChild.jsx') 
});
const ParentComponent = () => (
    <div>
        <FirstChild />
        <SecondChild />
    </div>
);

其中 FirstChild.jsx 和 SecondChild.jsx 都导入相同的服务:

import MyService from 'some/file/path/my.service.js';

当与 webpack 捆绑时,我们最终得到 3 个文件:

  • 主包(包括父组件)
  • FirstChild 捆绑包(包括MyService
  • SecondChild 捆绑包(其中还包括MyService

在这一点上,我看到了一个问题 - 我们MyService在两个文件之间都有重复项。对于一些小型应用程序,这可能不是问题(或者如果服务只是帮助方法),但如果我们使用我们的服务在应用程序的整个生命周期内存储一些数据,我们最终会得到两个对象引用服务,因此完全违背了它的意义。

我知道这里的服务可以“顶级”移动ParentComponent到每个组件,并可能作为道具传递给每个组件,但它似乎破坏了 webpack 首先拥有的架构 - 能够导入我们的任何东西需要我们需要的任何地方,它只创建一个参考。如果您有很多嵌套组件都需要导入各种服务和其他组件,这也可能会出现问题。

显然,这个例子很简单,但是将它实现到一个具有非常复杂架构的大型应用程序中可能会立即让我们遇到问题。

对此有什么想法吗?谢谢!

4

1 回答 1

1

将在这个问题上回答我自己的问题。

发现:

  • MyService.js最终出现在每个块的输出中并不重要。Webpack 足够聪明,只加载MyService它找到的第一个实例,并且只使用一个引用。这意味着如果首先FirstChild加载MyService,那么也将使用加载SecondChild的相同内容,并且它的副本将被忽略。MyServiceFirstChildMyService
  • 动态导入中的文件导入可以通过添加小的 Webpack 配置和正则表达式文件名匹配来手动拆分(感谢@AndriiGolubenko 为我指明了正确的方向),我们最终会得到奇怪的文件夹结构和文件名。例如,MyService.js在这种情况下的代码可能会以类似的块结尾services~FirstChild/SecondChild/SecondChild.js- 这对于调试来说并不是很好,但我认为这是 Webpack 引用它的导入的方式。

    optimization: {
        splitChunks: {
           cacheGroups: {
                services: {
                    test: /\.service.js$/,
                    enforce: true
                }
            }
        }
    },

如果其中有任何错误,或者您发现有关代码拆分 + webpack 的其他有趣点,请告诉我。

于 2019-05-10T11:18:43.180 回答