使用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>
我想进一步扩展,对于仅某些路由,请加载其他库。在上面的示例中,我想在信用卡路由上获取StripeJS(https://js.stripe.com/v2/)库 。
我想强调一点,我可以直接将Stripe加载到页脚中,并且一切正常。有多个库,我使用Stripe作为易于理解的示例。
以下尝试收效甚微:
<script>
属性的src
,等待它加载,然后让组件执行它这个工作正常,但是从可维护性(如果需要两个或更多库,我需要复制笨拙的手动script
加载)的观点来看真的很糟糕,并且似乎对Webpack&#34有效;方式&#34;。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(),
],
};
答案 0 :(得分:3)
https://github.com/hinok/webpack2-react-router-code-splitting
存储库包含使用动态import()的webpack2
+ react-router v4
+已实施code splitting
,并使用loadjs仅按需加载外部库一次。例如,它为特定路线加载Stripe.js
。
在存储库中,您可以找到两种进行代码拆分的方法
它基于官方Webpack文档和Andrew Clark的要点
在准备该存储库时,我发现@Chris只想为托管在外部CDN上的某些路由加载Stripe.js
。从那时起,我一直在考虑使用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 {};
}));
我可以说UMD包装器是标准的,但有时人们更喜欢不那么自以为是的包装器,或者他们只是不关心其他环境。我之所以提到它,是因为在git历史中,你可以找到commit called Amdify,它更能证明AMD env是如何被模拟的。最后我决定删除它,因为它远非理想,它不包括所有用法和边缘情况。
我找不到任何有关集成外部AMD模块或以某种方式使用AMD模块与webpack的信息。相反,我发现它不起作用
@ mc-zone您应该能够使用script.js加载AMD模块。但这与webpack无关,它只是起作用,因为AMD就是为此而设计的。因此,您将无法在这些AMD模块中使用webpack功能。 webpack需要对构建时进行静态分析。
by @jhns see on github
webpack不处理脚本加载。为此使用单独的库。一世。即https://github.com/ded/script.js/
by @sokra see on github
如果不可能,你不应该要求()它,而是通过脚本加载程序如script.js加载它。
by @jhns see on github
Github上的相关问题:
今天我在媒体上找到了关于他的项目an article by James Kale的react-loadable,它与LazilyLoad
组件几乎完全相同,但承诺
我强烈建议您查看。
答案 1 :(得分:0)
如果您使用的是Webpack 2,则在React Router配置文件中使用import()
export default {
component: App,
childRoutes: [
{
path: '/',
getComponent(location, cb) {
import('external-library-here')
.then(function(){
return System.import('pages/Home');
})
.then(loadRoute(cb)).catch(errorLoading);
}
},
{
path: 'blog',
getComponent(location, cb) {
import('pages/Blog').then(loadRoute(cb)).catch(errorLoading);
}
},
{
path: 'about',
getComponent(location, cb) {
import('pages/About').then(loadRoute(cb)).catch(errorLoading);
}
},
]
};
您还可以使用getComponent
组件中的getComponents
或Router
道具传递您专门针对该路线所需的模块。
答案 2 :(得分:0)
在这个问题中有一些案例应该详细讨论。
让我们开始。
react-router
的使用从组件切换到PlainRoute
对象,这样可以在执行代码拆分时提供更大的灵活性,并且还会跳过<AsyncComponent>
的创建成分credit-card
路线中的嵌套组件需要一个库呢?这是一项尚未实施的建议,但我试图让您就问题采取正确的方向
最后,这是我建议的方法:
import App from 'components/App';
function errorLoading(err) {
console.error('Dynamic page loading failed', err);
}
function loadRoute(cb) {
return (module) => cb(null, module.default);
}
function injectLibraries(libraries) {
Object.keys(libraries).forEach(key => {
window[key] = libraries[key];
});
}
export default {
component: App,
childRoutes: [
{
path: '/(index.html)',
name: 'home',
getComponent(location, cb) {
const importModules = Promise.all([
import('components/HomePage/'),
import('components/HomePage/libraries'),
]);
const renderRoute = loadRoute(cb);
importModules.then(([component, libraries]) => {
injectLibraries(libraries);
renderRoute(component);
});
importModules.catch(errorLoading);
},
},
{
path: '/credit-card',
name: 'credit-card',
getComponent(nextState, cb) {
const importModules = Promise.all([
import('components/CreditCardPage/'),
import('components/CreditCardPage/libraries'),
]);
const renderRoute = loadRoute(cb);
importModules.then(([component, libraries]) => {
injectLibraries(libraries);
renderRoute(component);
});
importModules.catch(errorLoading);
},
},
],
};
您的库文件应如下所示:
import stripe from 'stripe';
export default {
stripe
};
答案 3 :(得分:0)
您可能需要查看:
https://github.com/faceyspacey/webpack-flush-chunks
https://github.com/faceyspacey/require-universal-module
后者是一个通用软件包,旨在创建同步和异步需要其他模块的模块。
此包用于刷新确定为请求所需的Webpack块:
https://github.com/faceyspacey/webpack-flush-chunks
它不是React Router特定的,这可能意味着它更直接且需要更少的解决方法。