I’m working on a project where we’re breaking up a monolithic application into a series of micro-frontends using single-spa. Single-Spa is a micro-frontend framework.
Our project uses webpack externals to treat certain dependencies as in-browser modules. This means to exclude them during build-time and expect the browser to provide them at run-time.
Single-spa provides great documentation on how to achieve this.
The issue I ran into is that your IDE is not aware of this setup when you’re developing.
In the above image, my IDE is showing a “Module is not installed” warning.
This is because @effectv-platform/ep-ui-auth
is a micro-frontend. I’m importing an exported function from that micro-frontend called useAuth
. This is not a package published on npm declared within the project’s package.json, and installed in the project’s node_modules folder.
This module is an in-browser module provided by an import map.
You can publish your micro-frontends to a repository manager and declare them within your package.json. This will install them into your node_modules folder and your IDE will be happy.
An alternative is to use TypeScript’s “ambient” module functionality.
You create a <name>.d.ts
file within your project and add a declaration for that module. The file needs to end in .d.ts
. You can also export interfaces and functions from within that module's declaration.
We had an existing node.d.ts
file within our project. I updated that file to include the below code. This code adds a declaration for the @effectv-platform/ep-ui-auth
module.
declare module '@effectv-platform/ep-ui-auth'{
export function useAuth(): {signIn, signOut};
}
The downside to this approach is that you have to define and maintain this declaration file within each micro-frontend that needs it. This violates the principle of “Don’t Repeat Yourself” (DRY) and may lead to maintenance headaches.
For simple scenarios and when you’re first planning out the project this may be acceptable.