paint-brush
Micro-Frontends: Using TypeScript's Ambient Modulesby@raztide
18,366 reads
18,366 reads

Micro-Frontends: Using TypeScript's Ambient Modules

by Leonard JonesDecember 23rd, 2022
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

When cross-sharing micro-frontend imports at runtime your IDE won't be able to find where the module is installed. If you're working in TypeScript you can use ambient modules to add declarations for your cross-shared micro-frontends to improve local development.
featured image - Micro-Frontends: Using TypeScript's Ambient Modules
Leonard Jones HackerNoon profile picture


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.


uh-oh! module not found

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.