【问题标题】:Webpack code splitting to asynrounously load react components within a libraryWebpack 代码拆分以异步加载库中的反应组件
【发布时间】:2018-06-21 06:21:41
【问题描述】:

我们开发了一个供内部使用的 React 组件库。该库使用 webpack 将所有内容捆绑到 bundle.js 中。该库作为 NPM 模块公开,供我们的应用程序使用,到目前为止效果很好。

最近我们添加了一个 Grid 组件,它具有一些非常大的外部依赖项。即使我们的一些应用程序不需要库中的这个组件,我们还是决定将它包含在最终的包中。这会对包的大小产生巨大的影响,所以我按照 Webpack 的 code splitting guide 使用动态导入来分解 Grid 组件。对于我们将这个库安装为 NPM 模块的应用程序,组件库包现在在 node_modules 中看起来像这样:

├── node_modules/                 
│   ├── [our component library]/                 
│   │   ├── Grid.js # Asynchronously loaded Grid component
│   │   ├── bundle.js # Main bundle
│   │   └── ... other files in component library bundle

在构建应用程序时(也使用 Webpack),Grid 组件似乎没有作为自己的文件包含在最终包中。事实上,它根本没有被包括在内:

├── dist/                 
│   ├── main.js # App bundle
│   ├── vendor.js # Vendor bundle created with CommonChunksPlugin
│   └── ... other files in application bundle but no Grid.js

当尝试在浏览器中加载使用异步加载的 Grid 组件的页面时,Webpack 返回以下错误:

Error: Loading chunk 0 failed.
  at HTMLScriptElement.onScriptComplete (bundle.js:757)

本质上,这表示找不到 Grid 组件块。我究竟做错了什么?甚至可以像这样对 React 组件库进行代码拆分吗?

【问题讨论】:

  • 为什么不让内部库中的每个组件都可以单独导入?不需要为此进行代码拆分。 Webpack 只会在最终的包中包含真正导入的内容。
  • @trixn 当您说“可单独导入”时,您的意思是为库中的每个组件创建一个入口点吗?我还能做到import { Component } from 'component-library'吗?
  • 你能显示你的入口点文件和 webpack 配置吗?

标签: reactjs webpack


【解决方案1】:

我同时使用了 https://webpack.js.org/guides/code-splitting/#dynamic-imports import() 和 require.ensure 语法来进行动态导入。两者都运作良好。检查我的这个项目以获得很好的例子https://github.com/croraf/myboiler。

这个项目也是一个例子:https://github.com/croraf/nutrients-calculator。但是我稍微复杂了动态导入部分。检查https://github.com/croraf/nutrients-calculator/blob/master/frontend/src/App.js 和https://github.com/croraf/nutrients-calculator/blob/master/frontend/src/routes/util/DynamicRoute.js 文件。

【讨论】:

  • 我们在项目中也通过路由进行代码拆分。我试图弄清楚应用程序如何能够识别异步加载的库组件。如果我们的组件库和我们的应用程序在同一个项目中,这会容易得多,但这不是一个选择。
【解决方案2】:

我们决定对此采取不同的路线。如果将 Grid 组件与其他组件分开,而不是包含在它自己的 npm 模块中,我们会拆分它。我仍然看到在库中动态导入反应组件的用例,但我们认为这是解决问题的更好方法。使用此解决方案,唯一真正的缺点是应用程序现在需要添加 2 个 npm 模块而不是一个,如果它需要使用 Grid 组件和我们的标准组件库。由于我们的应用程序使用 webpack + 动态导入通过路由进行代码拆分,因此 Grid 代码仅被捆绑到需要它的路由中。

【讨论】:

    【解决方案3】:

    一个可能的原因是 babel 将您的代码从 import("..") 转换为 require。检查转译文件以确认这一点。 如果是这种情况并且您使用的是preset,您可以添加它来禁用此行为:

      "@babel/preset-env",
      {
        **"modules": false,**
        "targets": {
          "esmodules": true
        }
      }
    ],
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-15
      • 2017-05-31
      • 2017-11-11
      • 1970-01-01
      • 2018-05-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-21
      相关资源
      最近更新 更多