webdeb
webdeb

Reputation: 13211

Webpack load different modules based on chunk

Is it possible to make webpack load another module based on some context information?

For example I've two versions of my React application: desktop and mobile

In my index.js I decide which application to load:

if (isMobile()) {
   loadMobile().then(({default: App}) => render(App))
}

Now I would like to reuse some modules, but some I would like to override it. So by default it should load index.js, but if the context isMobile and next to the index.js a mobile.js file exists, it should load the mobile variant.

components/
  Button/
    index.js
    mobile.js

In the mobile context, webpack should load mobile.js instead of index.js

I could't find anything that I could use to solve it, any ideas?


PS: I've already created an issue on github, it also demonstrates the problem and what I want to achieve even better:

https://github.com/webpack/enhanced-resolve/issues/180

Upvotes: 11

Views: 2002

Answers (3)

UjinT34
UjinT34

Reputation: 4987

I guess that you have to create two builds: one with default resolve.mainFiles and one with

resolve: {
    mainFiles: ['mobile', 'index']
}

You will need to decide which bundle to load inside your html. Or create two different html files and move isMobile logic to the webserver config so it'll decide which html to return to user.

Some chunks might be the same between both builds. But it is very likely that you will end up with two different apps. You might reduce the built code duplication between two apps with DllPlugin.

Upvotes: 0

tunaayberk
tunaayberk

Reputation: 466

You can use dynamic loading function and dynamic importing syntax for this problem.

  1. Install Babel plugin plugin-syntax-dynamic-import:

    npm install --save-dev @babel/plugin-syntax-dynamic-import
    

    and use it in .babelrc

    {
      "plugins": ["@babel/plugin-syntax-dynamic-import"]
    }
    
  2. You need to create a component called load with the following codes:

        export default const load = (platform="index") => componentName => 
        import(`components/${componentName}/${platform}.js`);
    
  3. Then use dynamic import with loading function like the following code:

        const { Button } = await import("components/Loader.jsx").then(load => {
          load(${platform})(${componentName})
        })
    

These articles may help you:

Upvotes: 5

Aditya
Aditya

Reputation: 801

There are two different ways you can achieve this.

  1. Create 2 entry points 1 each for mobile and desktop so that webpack generate 2 bundles. You can load only the desired bundle from the html.
  2. If you require/import the Mobile code inside loadMobile() webpack automatically splits the code into 2 bundles. The mobile bundle is loaded only if it is necessary.

Upvotes: 0

Related Questions