javascript - Webpack:将动态导入的模块拆分为单独的 block ,同时将库保留在主包中

标签 javascript webpack webpack-4

我正在开发一个网络应用程序,其中包含应该使用dynamic imports延迟加载的小部件。 。 每个小部件都应该收到其单独的包,并且它们的依赖项只有在用户请求时才由浏览器获取。有一个异常(exception):流行的小部件应该包含在主包以及它们使用或扩展的库类中。下面您可以看到我想要实现的文件夹结构以及我想要的输出:

File Structure                       Desired chunk

src/
├── widgets/
│   ├── popular-widget/index.ts      main
│   ├── edge-case-widget/index.ts    edge-case-widget
│   └── interesting-widget/index.ts  interesting-widget
├── library/
│   ├── Widget.ts                    main
│   └── WidgetFactory.ts             main
└── index.ts                         main (incl. entry point)

dist/
├── edge-case-widget.app.js          edge-case-widget
├── interesting-widget.app.js        interesting-widget
└── main.app.js                      main (incl. entry point)

为了延迟加载小部件,我在 create 中使用以下表达式WidgetFactory中的方法。这工作正常,小部件模块会被 Webpack 神奇地拾取。

const Widget = await import(`../widgets/${name}/index`)

我试图通过配置 optimization.splitChunks.cacheGroups 来解决代码分割挑战在 Webpack 中。提供test函数我将模块分配到 librarywidgets缓存组。

module.exports = {
  entry: './src/index.ts',
  [...]
  optimization: {
    splitChunks: {
      cacheGroups: {
        library: {
          test: module => isInLibrary(module.identifier()),
          name: 'library',
          chunks: 'all',
          minSize: 0
        },
        widgets: {
          test: module => isWidgetBundle(module.identifier()),
          name: module => widgetNameFromModuleId(module.identifier()),
          chunks: 'async',
          minSize: 0
        }
      }
    }
  }
}

我被困住了!

  • 如何在小部件包中包含小部件依赖项?
  • 使用chunks: 'async'关于library缓存组使一些库类转到 main block 而其他人留在 library block 。为什么?
  • 当我使用chunks: 'all'时关于library缓存组所有模块都正确地组合在其中,但我丢失了 main 上的入口点 block 并获得一个空白页。怎么办?
  • 当我重命名library时将组缓存到 main我丢失了入口点,as documented here 。我不太明白为什么会出现这种情况以及我如何设法将 main 结合起来入口点为library打包成一个包。

希望您能帮助我了解我陡峭的 Webpack 学习曲线。

最佳答案

创建了一个简单的github repo具有您需要的配置。

  1. SplitChunks 配置(如果需要,请将 testname 函数更改为您的):
    splitChunks: {
            cacheGroups: {
                widgets: {
                    test: module => {
                        return module.identifier().includes('src/widgets');
                    },
                    name: module => {
                        const list = module.identifier().split('/');
                        list.pop();
                        return list.pop();
                    },
                    chunks: 'async',
                    enforce: true
                }
            }
    }
  • 如果您希望PopularWidget位于main中,则不应动态导入它。使用常规 import 语句。因为 webpack 总是会为任何动态导入创建一个新 block 。那么请看一下this文件。
  •     import { Widget } from '../widgets/popular-widget';
    
        export class WidgetFactory {
            async create(name) {
                if (name === 'popular-widget') return await Promise.resolve(Widget);
                return await import(`../widgets/${name}/index`)
            }
        }
    
    

    UPD
    更改了配置以保留相关的 node_modules 和小部件。
    我为新的小部件 block 创建编写了两个简单的函数。
    这里的技巧是 module.issuer 属性,它意味着谁导入了这个文件。因此,函数 isRelativeToWidget 将为在小部件文件结构的任何深度导入的任何依赖项(无论是否为 node_modules)返回 true。
    代码可查here .
    结果配置:

    splitChunks: {
                chunks: 'all',
                cacheGroups: {
                    vendors: false,
                    default: false,
                    edgeCaseWidget: getSplitChunksRuleForWidget('edge-case-widget'),
                    interestingWidget: getSplitChunksRuleForWidget('interesting-widget')
                }
            }
    
    function isRelativeToWidget(module, widgetName) {
        if (module.identifier().includes(widgetName)) return true;
    
        if (module.issuer) return isRelativeToWidget(module.issuer, widgetName)
    }
    
    function getSplitChunksRuleForWidget(widgetName) {
        return {
            test: module => isRelativeToWidget(module, widgetName),
            name: widgetName,
            chunks: 'async',
            enforce: true,
        }
    }
    

    关于javascript - Webpack:将动态导入的模块拆分为单独的 block ,同时将库保留在主包中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58901229/

    相关文章:

    javascript - Webpack 如何独立打包 JS 和 CSS 文件?

    javascript - Webpack:webpack.config.js 是否已提交?

    javascript - 脚本 1002 : Syntax error in IE11 with React + Babel + Webpack

    javascript - UglifyJs 意外 token : keyword «const» Webpack 4

    javascript - 在 webpack 中暴露 UIkit

    javascript - 如何在不点击按钮的情况下验证电子邮件

    reactjs - React Router 与可加载组件错误

    php - JavaScript 到 PHP 的安全性

    javascript - 为什么不设置选择元素的值?

    javascript - 如何在 D3.js 中读取 Blob