Conversation
|
|
||
| David is doing a great job documenting this whole process and architecture, and thus I'll not repeat myself here. [add-david-mfe-link]() | ||
|
|
||
| As part of this initiative, we created a shared library (which works as any other MFE) and only contains the components that are shared across products. All of this lives on a single repo, and we're using Webpack's Module Federation to define this clear interface between products. |
There was a problem hiding this comment.
I'd probably introduce the MFE meaning before when you mention Micro-frontends. People may not read my articles, and thus wouldn't automatically associate that
| However, some challenges came out of this, and one of them is the one I'm sharing here today. | ||
| ## The challenge | ||
|
|
||
| We wanted to import components from a different MFE, and we wanted this to be _code-splitted_, meaning that it should only be loaded when it is needed. We'll refer to this components as **remote components** as they live in a different location. |
There was a problem hiding this comment.
refer to these --> not this
|
|
||
| We wanted to import components from a different MFE, and we wanted this to be _code-splitted_, meaning that it should only be loaded when it is needed. We'll refer to this components as **remote components** as they live in a different location. | ||
|
|
||
| Webpack allows to do this by using the _dynamic import_ syntax (`import()`). Here's what we needed to do to load a component that belongs to the **shared** library. |
There was a problem hiding this comment.
This is true for react components only, when importing other data types, there's no need to use the dynamic import
| ```js | ||
| import React from "react"; | ||
|
|
||
| const Button = React.lazy(() => import("shared/components/Button")); | ||
|
|
||
| const HomePage = () => { | ||
| return <Button />; | ||
| }; | ||
| ``` |
There was a problem hiding this comment.
You should probably say that this code assumes there's a higher up in the tree
|
|
||
| Then, when this `Button` component is used, it will be fetched from the remote source, and rendered to the page. This makes it possible for webpack to code-split our codebase, only downloading the Button when the user needs it. | ||
|
|
||
| However, and even thus it works, we though it would be too much of a burden for developers to do. They shouldn't have to care if the component lives in a remote source or not, nor they have to remember of wrapping it in a React.lazy call. All of this would make it very error prone, and at the same time would get our codebase full of `React.lazy` calls. |
| return { | ||
| visitor: { | ||
| ImportDeclaration: function (path, state) { | ||
| if (path.node.source.value.startsWith('sharedcomps/')) { |
There was a problem hiding this comment.
you mentioned the shared/components/.. before, here you should do the same
|
|
||
| We knew that babel-loaders needed to use the `babel-config` `custom` function with a callback, and that they would need to register themselves as a plugin in the global configuration. | ||
|
|
||
| As we skimmed through babel-handbook, we also noted that we'd most likely use the visitor pattern, starting by _visiting_ the `ImportDeclarations`, since our initial code was one of them. We decided that we wanted every import starting with `shared` to be a target for this transformation, and thus we added the code to do that. |
There was a problem hiding this comment.
And we don't want every shared component to do this, only the ones we register in the options
| visitor: { | ||
| const componentPath = path.node.source.value; | ||
|
|
||
| if (path.node.source.value.startsWith('sharedcomps')) { |
| visitor: { | ||
| ImportDeclaration: function (path, state) { | ||
| // console.log('opts', state) | ||
| if (path.node.source.value.includes('sharedcomps/Button')) { |
| ``` | ||
|
|
||
| The above code finds the `ImportDefaultSpecifier` and modifies the initial import declaration so that it keeps all except the default. Then it adds the code to do the dynamic import, together with `React.lazy`. | ||
| ## Conclusion |
There was a problem hiding this comment.
Before the conclusion I would add the piece of code that allows us to decide on what components we want this to run on. It's open on a PR for dashboard-ui
d45f6c4 to
5271df1
Compare
No description provided.