I'm using Create-React-App and am looking to use the dynamic import() supported by webpack 2.0 to import a module based on a variable string.
I've looked at the official proposal () and it seems possible to do something like this:
import(`./language-packs/${navigator.language}.js`)
But it breaks when I try something similar.
AppRoutes.js
import LazyLoad from 'services/LazyLoad';
export class AppRoutes extends React.Component {
render() {
return (
<Switch>
<Route
exact path="/"
render={(matchProps) => (
<LazyLoad
absoluteModulePath='pages/default/HomePage'
getComponent={() => import('pages/default/HomePage')}
{...matchProps}
/>
)}
/>
</Switch>
);
}
}
export default AppRoutes;
pages/default/HomePage/index.js
import React from 'react';
export const HomePage = () => {
return (
<div>
I'm the default HomePage
</div>
);
}
export default HomePage;
BROKEN services/LazyLoad/index.js
import React from 'react';
export class LazyLoad extends React.Component {
...
componentDidMount() {
import(this.props.absoluteModulePath) // Critical dependency: the request of a dependency is an expression
.then(module => module.default)
.then(AsyncModule => this.setState({AsyncModule}))
}
...
}
export default LazyLoad;
Error:
But when I change the LazyLoader to
WORKING services/LazyLoad/index.js
import React from 'react';
export class LazyLoad extends React.Component {
...
componentDidMount() {
this.props.getComponent()
.then(module => module.default)
.then(AsyncModule => this.setState({AsyncModule}))
}
...
}
export default LazyLoad;
it works.
The absolute paths is something built into create-react-app with the help of environment variables.
.env
NODE_PATH=src/
I require dynamically loading modules this way to build a proof of concept for multi-tenancy. How can I fix the broken LazyLoad such that I can pass a string as a prop and have the LazyLoad component dynamically load the component from that string prop?
I'm using Create-React-App and am looking to use the dynamic import() supported by webpack 2.0 to import a module based on a variable string.
I've looked at the official proposal (https://github.com/tc39/proposal-dynamic-import) and it seems possible to do something like this:
import(`./language-packs/${navigator.language}.js`)
But it breaks when I try something similar.
AppRoutes.js
import LazyLoad from 'services/LazyLoad';
export class AppRoutes extends React.Component {
render() {
return (
<Switch>
<Route
exact path="/"
render={(matchProps) => (
<LazyLoad
absoluteModulePath='pages/default/HomePage'
getComponent={() => import('pages/default/HomePage')}
{...matchProps}
/>
)}
/>
</Switch>
);
}
}
export default AppRoutes;
pages/default/HomePage/index.js
import React from 'react';
export const HomePage = () => {
return (
<div>
I'm the default HomePage
</div>
);
}
export default HomePage;
BROKEN services/LazyLoad/index.js
import React from 'react';
export class LazyLoad extends React.Component {
...
componentDidMount() {
import(this.props.absoluteModulePath) // Critical dependency: the request of a dependency is an expression
.then(module => module.default)
.then(AsyncModule => this.setState({AsyncModule}))
}
...
}
export default LazyLoad;
Error:
But when I change the LazyLoader to
WORKING services/LazyLoad/index.js
import React from 'react';
export class LazyLoad extends React.Component {
...
componentDidMount() {
this.props.getComponent()
.then(module => module.default)
.then(AsyncModule => this.setState({AsyncModule}))
}
...
}
export default LazyLoad;
it works.
The absolute paths is something built into create-react-app with the help of environment variables.
.env
NODE_PATH=src/
I require dynamically loading modules this way to build a proof of concept for multi-tenancy. How can I fix the broken LazyLoad such that I can pass a string as a prop and have the LazyLoad component dynamically load the component from that string prop?
Share Improve this question asked May 24, 2017 at 18:50 Kyle TruongKyle Truong 2,7419 gold badges36 silver badges55 bronze badges 5 |1 Answer
Reset to default 18Only partially dynamic statement are allowed for import().
In your AppRoutes.js you could do this:
...
<LazyLoad
modulePath='HomePage'
getComponent={() => import('pages/default/HomePage')}
{...matchProps}
/>
then in your LazyLoad Component you do:
componentDidMount() {
import(`pages/default/${this.props.modulePath}/index.js`)
.then(module => module.default)
.then(AsyncModule => this.setState({AsyncModule}))
}
Fully dynamic statements, such as import(foo), will fail because webpack requires at least some file location information.The import() must contain at least some information about where the module is located, so bundling can be limited to a specific directory or set of files.
https://webpack.js.org/api/module-methods/#import-
'./pages/default/HomePage'
as a path string instead ofpages/default/HomePage
? – Michael Lyons Commented May 24, 2017 at 19:14/pages...
, otherwise I don't know. For bundle splitting I userequire.ensure
within React-Router's getComponent. Don't have experience with lazy-loading via import, sorry. – Michael Lyons Commented May 24, 2017 at 19:53