I want to be able to load React components asynchronously based on different user types. For example, as User A navigates around the app, their set of components are loaded via async. Then when User B uses the app they received a different set of components also loaded via async.
At the moment I'm using React Router and Redux. I also use Webpack to create component chunks which load async like this:
<Route
path="/"
getComponent={(location, callback) => {
require.ensure([], (require) => {
callback(null, require('./app/App.jsx').default);
}, 'App');
}}
>
But when I try to expand this to dynamically load the components it doesn't work. I've created an array of objects which contains all the components I want to load...
{
components: [
{
id: 0,
name: 'Dashboard',
src: './dashboard/Dashboard.jsx',
indexRoute: true,
path: '/',
},
{
id: 1,
name: 'Quote',
src: './quote/Quote.jsx',
indexRoute: false,
path: '/quote',
},
],
}
I then use map to create routes for each one of these components...
const routes = components.map((component) => {
if (component.indexRoute) {
return (
<IndexRoute
getComponent={(location, callback) => {
require.ensure([], (require) => {
callback(null, require(component.src).default);
}, component.name);
}}
key={component.id}
/>
);
}
return (
<Route
path={component.path}
getComponent={(location, callback) => {
require.ensure([], (require) => {
callback(null, require(component.src).default);
}, component.name);
}}
key={component.id}
/>
);
});
But when I insert my created routes into the main route...
<Route
path="/"
getComponent={(location, callback) => {
require.ensure([], (require) => {
callback(null, require('./app/App.jsx').default);
}, 'App');
}}
>
{routes}
</Route>
I get the following error:
Uncaught TypeError: __webpack_require__(...).ensure is not a function
and warning:
require function is used in a way in which dependencies cannot be statically extracted
I presume this is because Webpack needs to know what chunks it has to compile at build time? Is this the problem and is there a way round this? Or even a better solution?
Thanks
For anyone who comes across this at a later stage, I managed to work around this by creating a object with all the async components my app could possibly load. Each components route definition has it's require.ensure function defined like such...
const asyncComponents = [
{
id: 0,
name: 'Dashboard',
require: (location, callback) => {
require.ensure([], (require) => {
callback(null, require('./dashboard/Dashboard.jsx').default);
}, 'Dashboard');
},
},
];
export default asyncComponents;
Doing it this way will inevitably face scaling problems at some point as you have to maintain a separate list of all your components. It works for now though.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.