使用React Router和Webpack 2如何仅在某些路由上需要外部库?

Chr*_*ris 16 javascript ecmascript-6 reactjs webpack react-router

正在工作

使用Webpack 2和React Router v4,我已经能够设置工作代码分割.有一个中间件<AsyncComponent>可以解析promise并返回组件(在github问题上找到的模式).

下面的一组示例路线:

<Switch>
    <Route 
        path="me" 
        render={(props) => 
            <AsyncComponent promise={ require.ensure([], (require) => require('./modules/Profile'), 'profile') } props={props} />
        } 
    />
    <Route 
        path="credit-card" 
        render={(props) => 
            <AsyncComponent promise={ require.ensure([], (require) => require('./modules/CreditCard'), 'credit-card') } props={props} />
        } 
    />
</Switch>
Run Code Online (Sandbox Code Playgroud)

目的

我想进一步扩展它,并且对于某些路由,加载其他库.在上面的例子中,我想取StripeJS(https://js.stripe.com/v2/)库只有当信用卡路线.

我想强调一下,我可以将Stripe直接加载到页脚中,并且一切正常.有多个库,我使用Stripe作为一个易于理解的例子.

尝试

以下尝试收效甚微:

  • 在webpack配置中标记lib外部.这(正确地)将库标记为外部库,并且在require的解析序列期间不会尝试将其捆绑.然而,期望是手动引入库.
  • 我已经玩过使用伪脚本加载器的想法(当遇到该路由时,手动创建一个<script>带有src属性,等待它加载,然后让组件做它的事情.这样做可行,但从可维护性来看真的很可怕(如果需要两个或更多库,那么我需要复制笨拙的手动script加载)的观点,并且似乎对webpack"方式"有效.

配置的相关部分

const core = [
    'lodash',
    'react',
    'react-dom',
    'axios',
    'react-router-dom',
];

const config = {
    context: path.resolve(__dirname, './ts_build'),
    node: {
        fs: "empty"
    },
    entry: {
        app: './app.js',
        core: core,
    },
    output: {
        filename: '[name].js',
        chunkFilename: '[name].[id].chunk.js',
        path: path.resolve(__dirname, './../../public'),
        publicPath: 'http://example.org/',
    },
    resolve: {
        modules: [
            path.resolve('./src'),
        ],
    },
    plugins: [
        new webpack.optimize.CommonsChunkPlugin({
            names: ['core'], 
            minChunks: Infinity,
        }),
        new webpack.NamedModulesPlugin(),
    ],
};
Run Code Online (Sandbox Code Playgroud)

hin*_*nok 3

https://github.com/hinok/webpack2-react-router-code-splitting

存储库包含使用动态import()实现的webpack2++ ,并使用loadjs仅按需加载外部库一次。例如它加载react-router v4code splittingStripe.js特定路线。

在存储库中,您可以找到两种进行代码分割的方法

它基于 Andrew Clark 的官方 Webpack 文档和要点

在准备该存储库时,我发现 @ChrisStripe.js只想加载外部 CDN 上托管的某些路由。从那时起,我一直在考虑使用 AMD 模块并避免泄漏全局变量的最佳方法,但这有点棘手,因为每个 AMD 模块可能有不同的包装器,我所说的包装器的意思是:

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['b'], function (b) {
            return (root.amdWebGlobal = factory(b));
        });
    } else {
        root.amdWebGlobal = factory(root.b);
    }
}(this, function (b) {
    return {};
}));
Run Code Online (Sandbox Code Playgroud)

我可以说UMD包装器是一种标准,但有时人们更喜欢不那么固执己见的包装器,或者他们只是不关心其他环境。我提到它是因为在 git 历史记录中,您可以找到名为 Amdify 的提交,它更多地证明了如何模拟 AMD env 的概念。最后我决定删除它,因为它远非理想,并且它没有涵盖所有用法和边缘情况。

我找不到任何有关集成外部 AMD 模块或以某种方式通过 webpack 使用 AMD 模块的信息。相反我发现它根本行不通

@mc-zone 你应该能够使用 script.js 加载 AMD 模块。但这与 webpack 无关,它只是起作用,因为 AMD 就是为此设计的。因此,您将无法在这些 AMD 模块中使用 webpack 功能。webpack 需要对构建时间进行静态分析。

作者:@jhns请参阅 github

webpack 不处理脚本加载。为此使用单独的库。即https://github.com/ded/script.js/

作者:@sokra请参阅 github

如果不可能,您不应该 require() 它,而是通过 script.js 等脚本加载器加载它。

作者:@jhns请参阅 github

Github上的相关问题:


今天我在媒体上发现了James Kale 写的一篇关于他的项目React-Loadable 的文章,该项目的功能与组件几乎相同LazilyLoad,但承诺

  • 它通过动态 require() 支持服务器端渲染
  • 它在需要时急切地预加载组件

我强烈建议您检查一下。