Home > Mobile >  Can I conditionally import and re-export JS library?
Can I conditionally import and re-export JS library?

Time:05-31

I have been trying to find a good pattern to split up my code as I am currently bundling N versions of every React component, and only ever using one at a time.

The current pattern is

import {
    Component1 as Component1_Lib1,
    Component2 as Component2_Lib1,
} from 'lib1';

import {
    Component1 as Component1_Lib2,
    Component2 as Component2_Lib2,
} from 'lib2';

export const SiteSpecificComponent1 = (site) => {
    return {
            site1: Component1_Lib1,
            site2: Component1_Lib2
        }[site]
    };

etc.

These are then used in various components shared across the sites. The bundle will always include all versions of every component.

I have been trying to design a pattern to cleanly split this up. I have looked at lazy loading and conditional importing but I haven't come up with anything yet so I come to you. Are there any build tricks or architecture patterns you are familiar with that could help me split the unused components from my bundle?

Thanks for any help.

CodePudding user response:

you can use dynamic imports .This is also available as babel-preset.

Following is way to do conditional rendering as per your case.

if (condition) {
    import('something')
    .then((something) => {
       console.log(something.something);
    });
}

you can check dynamic import.

CodePudding user response:

Ideally, you should rely on Tree shaking to do its job such that only required components are ever bundled. However successful tree shaking depends on two factors:

  • Publishing your library as ESM Module. (Using type: "module" in your package.json file or using *.mjs files)
  • Using sideEffects to declare package side effect free (Your module should actually have not side effects like singleton, using global window object at the top of the module, etc.)

However, this is not enough. The presence of following code will not allow tree shaking to work properly as Webpack/Rollup cannot figure out what's the value of site would be at compile time. This means it ends up picking everything in the bundled code.

export const SiteSpecificComponent1 = (site) => {
  return ({
      site1: Component1_Lib1,
      site2: Component1_Lib2
  })[site];
};

To solve this problem, we need to make an assumption about your sites. If these different versions of the components are meant to be used in different sites/applications, then it probably means that application would have a separate build script and also separate repository. Now if you are using tech stack is latest - Node 16, Webpack 5, TypeScritp 4.5, Jest 28, then you can make use of new package.json exports fields that supports submodules or subpath exports. Your package.json will look like:

// package.json file
{
  "name": "your-lib-name",
  "type": "module",
  "exports": {
    "site1": "./dist/site1.js",
    "site2": "./dist/site2.js"
  }
}

In each file, you would only export components that belong to a particular site or application. For example,

// site1.js
export { Component1 as Component1_Lib1 } from 'lib1';
export { Component1 as Component1_Lib2 } from 'lib2';

// site2.js
export { Component2 as Component2_Lib1 } from 'lib1';
export { Component2 as Component2_Lib2 } from 'lib2';


// Usage
import { Component1_Lib1 } from 'you-lib-name/site1.js';
import { Component2_Lib1 } from 'you-lib-name/site2.js';

Of course, you loose the capability to dynamically get the component name using a method invocation, but this is more bundle friendly as it readily tree-shakeable.

  • Related