Home > Enterprise >  How are the imports implemented in different React libraries and how can I implement the same patter
How are the imports implemented in different React libraries and how can I implement the same patter

Time:07-11

For example, the recommended way of importing in React Bootstrap is to go this way:

import Button from 'react-bootstrap/Button' instead of import { Button } from 'react-bootstrap';

The reason is "Doing so pulls in only the specific components that you use, which can significantly reduce the amount of code you end up sending to the client."

source: https://react-bootstrap.github.io/getting-started/introduction/

Same for React MUI components:

import Button from '@mui/material/Button';

source: https://mui.com/material-ui/getting-started/usage/

I want to implement something similar in my React components library, to limit the usage of code in the bundle, but I don't know how they implement this specific pattern. I have looked at their code base, but I don't quite understand.

CodePudding user response:

Basically it is all about modules and module files and their organization. You can have a lot of.. lets call them folders, "compoments/*" for example. "components/button", "components/alert", "component/badge", and other things. All of them will have some index.js or .ts file that will export or declare and export all the functionality that needed in order to make this component work, 'react-bootstrap/Button' for example. Ideally all those subfolders or submodules are independend from each other, no references between them but probably each one will have 1 reference to 1 common/shared submodule like "components/common" which will contain some constants, for example, and no references to other files. At the top level of them you will have another index.js or .ts file that is referencing all of those components, so "components/index.js" will import and reexport all the nested components index files. So in order to import a Button, for example, you can either import "components/index.js" file with all the other imports this file is using, either only 1 single "components/button/index.js" file which is obviously much more easy to fetch. Just imagine a tree data structure, you import root of the tree (root index.js) - you get all the tree nodes. You import one specific Node (components/button/index.js) of the tree - just load all the childs (imports) of that node.

Sorry for a long read but asuming you mentioned webpack - there is a technique called tree-shaking which will cut off all the unused things.

Info about modules: https://www.w3schools.com/js/js_modules.asp

Info about Tree-Shaking: https://webpack.js.org/guides/tree-shaking/

CodePudding user response:

It might not be as complicated as you think. Let's say you write the following library:

// your-library.js

const A = 22
const B = 33

export function getA () { return A }
export function getB () { return B }

export function APlusB () { return A   B }

// a lot of other stuff here

If some consumer of your library wants to make use of the APlusB function, they must do the following:

// their-website.js
import { APlusB } from 'your-library'

const C = APlusB()

However, depending on how the code is bundled, they may or may not wind up with the entire your-library file in their web bundle. Modern bundling tools like Webpack may provide tree shaking to eliminate dead code, but this should be considered an additional optimization that the API consumer can opt into rather than a core behavior of the import spec.

To make your library more flexible, you can split up independent functions or chunks of functionality into their own files while still providing a full bundle for users who prefer that option. For example:

// your-library/constants.js

export const A = 22
export const B = 33
// your-library/aplusb.js
import { A, B } from 'constants'

export default function APlusB () { return A   B }
// your-library/index.js

// instead of declaring everything in one file, export it from each module
export * from 'constants'
export { default as APlusB } from 'aplusb'
// more exports here

For distribution purposes you can package your library like so:

your-library
|__aplusb.js
|__constants.js
|__index.js

You mentioned react-bootstrap and you can see this exact pattern in their file structure:

https://github.com/react-bootstrap/react-bootstrap/tree/master/src

and you can see they aggregate and re-export modules in their index file here:

https://github.com/react-bootstrap/react-bootstrap/blob/master/src/index.tsx

  • Related