8

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:

enter image description here

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.

enter image description here

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?

5
  • Have you tried using './pages/default/HomePage' as a path string instead of pages/default/HomePage? Commented May 24, 2017 at 19:14
  • Just tried it now with ./pages and ../pages and ../../pages and it gives me the same error. Commented May 24, 2017 at 19:27
  • Hmmm, maybe without the period, /pages..., otherwise I don't know. For bundle splitting I use require.ensure within React-Router's getComponent. Don't have experience with lazy-loading via import, sorry. Commented May 24, 2017 at 19:53
  • 1
    Have you found that require.ensure works with interpolated strings or expressions rather than plain strings? Commented May 25, 2017 at 13:44
  • Yes I just tried it with a string literal that evaluates correctly. Where are you trying to source this string from? A build environment variable? On client side based on an API call? There's a good example of this here: Github Commented May 25, 2017 at 18:37

1 Answer 1

18

Only 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-

Sign up to request clarification or add additional context in comments.

1 Comment

Just in case someone wonders, the same rule applies for dynamic require statements.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.