diff --git a/docs/frontend-plugins.md b/docs/frontend-plugins.md
index 1e098efe..d4d7cb11 100644
--- a/docs/frontend-plugins.md
+++ b/docs/frontend-plugins.md
@@ -155,13 +155,22 @@ export default MyCustomComponent;
### 4\. Federation Configuration
The core of the plugin is its Webpack configuration.
-All plugins should use this sample `webpack.config.js` as a base.
+All plugins should use this `webpack.config.js` as a base.
+
+Disclaimer:
+We try to not change this file.
+But in the future, it may evolve as the plugin system matures.
```javascript
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
-const { NativeFederationTypeScriptHost } = require('@module-federation/native-federation-typescript/webpack');
+const {
+ NativeFederationTypeScriptHost,
+} = require('@module-federation/native-federation-typescript/webpack');
+const {
+ NativeFederationTypeScriptHost: NativeFederationTypeScriptHostCore,
+} = require('@module-federation/native-federation-typescript');
module.exports = (env, argv) => {
const dev = argv.mode !== 'production';
@@ -189,6 +198,24 @@ module.exports = (env, argv) => {
},
};
+ let mfTypesReady;
+ const ensureFederatedTypesPlugin = {
+ apply(compiler) {
+ compiler.hooks.beforeCompile.tapPromise(
+ 'EnsureFederatedTypes',
+ async () => {
+ if (!mfTypesReady) {
+ const downloader = NativeFederationTypeScriptHostCore.raw({
+ moduleFederationConfig,
+ });
+ mfTypesReady = downloader.writeBundle();
+ }
+ await mfTypesReady;
+ },
+ );
+ },
+ };
+
return {
devServer: {
// The port should match the one in your plugin's configuration file
@@ -198,7 +225,12 @@ module.exports = (env, argv) => {
plugins: [
new ModuleFederationPlugin(moduleFederationConfig),
// This plugin enables type-sharing for intellisense
- ...(dev ? [NativeFederationTypeScriptHost({ moduleFederationConfig })] : []),
+ ...(dev
+ ? [
+ ensureFederatedTypesPlugin, // ensures the zip is ready before the first compile
+ NativeFederationTypeScriptHost({ moduleFederationConfig }),
+ ]
+ : []),
],
// ... other webpack config (output, module rules, etc.)
};
@@ -232,8 +264,8 @@ In your plugin's `tsconfig.json`:
When you run the host application with `NEXT_PUBLIC_DEVELOP_PLUGINS=true`, it generates a `@mf-types.zip` file.
-The `NativeFederationTypeScriptHost` plugin in your webpack config will automatically download and unpack it,
-making the host's types available to your plugin and IDE.
+The `NativeFederationTypeScriptHost` plugin in your webpack config will automatically download and unpack it ahead of the first compile,
+making the host's types available to your plugin and IDE. In development with this flag enabled, route changes may be slower because type generation and automatic exposure run during rebuilds; this does not affect production where navigations are instant.
@@ -554,4 +586,4 @@ Update the **`remote.url`** to the public-facing path that matches where you dep
"message": "Hello from production!"
}
}
-```
\ No newline at end of file
+```
diff --git a/src/frontend/apps/impress-plugin/src/MyCustomComponent.tsx b/src/frontend/apps/impress-plugin/src/MyCustomComponent.tsx
index cf863304..d58518f4 100644
--- a/src/frontend/apps/impress-plugin/src/MyCustomComponent.tsx
+++ b/src/frontend/apps/impress-plugin/src/MyCustomComponent.tsx
@@ -443,7 +443,7 @@ const MyCustomComponent: React.FC = ({
>
- Loading plugin data...
+ Fake Loading...
) : (
diff --git a/src/frontend/apps/impress-plugin/src/ThemingDemo.tsx b/src/frontend/apps/impress-plugin/src/ThemingDemo.tsx
index f551b609..f91d94e4 100644
--- a/src/frontend/apps/impress-plugin/src/ThemingDemo.tsx
+++ b/src/frontend/apps/impress-plugin/src/ThemingDemo.tsx
@@ -153,8 +153,7 @@ const ThemingDemo: React.FC = () => {
color: 'var(--c--theme--colors--greyscale-600)',
lineHeight: '1.4',
}}>
- 💡 This demo overrides primary-500, primary-600, and secondary-500 tokens.
- Any component using these tokens will update!
+ 💡 This demo overrides primary-500, primary-600, and secondary-500 css variables. It only works with CSS.
>
diff --git a/src/frontend/apps/impress-plugin/webpack.config.js b/src/frontend/apps/impress-plugin/webpack.config.js
index bed2b656..c4adce30 100644
--- a/src/frontend/apps/impress-plugin/webpack.config.js
+++ b/src/frontend/apps/impress-plugin/webpack.config.js
@@ -1,6 +1,11 @@
const path = require('path');
-const { NativeFederationTypeScriptHost } = require('@module-federation/native-federation-typescript/webpack');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
+const {
+ NativeFederationTypeScriptHost,
+} = require('@module-federation/native-federation-typescript/webpack');
+const {
+ NativeFederationTypeScriptHost: NativeFederationTypeScriptHostCore,
+} = require('@module-federation/native-federation-typescript');
const moduleFederationConfig = {
name: 'plugin_frontend',
@@ -31,6 +36,24 @@ const moduleFederationConfig = {
},
};
+let mfTypesReady;
+const ensureFederatedTypesPlugin = {
+ apply(compiler) {
+ compiler.hooks.beforeCompile.tapPromise(
+ 'EnsureFederatedTypes',
+ async () => {
+ if (!mfTypesReady) {
+ const downloader = NativeFederationTypeScriptHostCore.raw({
+ moduleFederationConfig,
+ });
+ mfTypesReady = downloader.writeBundle();
+ }
+ await mfTypesReady;
+ },
+ );
+ },
+};
+
module.exports = (env, argv) => {
const dev = argv.mode !== 'production';
@@ -70,10 +93,11 @@ module.exports = (env, argv) => {
new ModuleFederationPlugin(moduleFederationConfig),
...(dev
? [
- NativeFederationTypeScriptHost({
- moduleFederationConfig,
- }),
- ]
+ ensureFederatedTypesPlugin,
+ NativeFederationTypeScriptHost({
+ moduleFederationConfig,
+ }),
+ ]
: []),
],
};
diff --git a/src/frontend/apps/impress/next.config.js b/src/frontend/apps/impress/next.config.js
index 3adf69bf..a9544b4c 100644
--- a/src/frontend/apps/impress/next.config.js
+++ b/src/frontend/apps/impress/next.config.js
@@ -28,9 +28,15 @@ const nextConfig = {
NEXT_PUBLIC_BUILD_ID: buildId,
},
webpack(config, { isServer, dev }) {
- // Prevent rebuild loops by ignoring node_modules and build outputs
+ // Prevent rebuild loops by ignoring node_modules and generated types/outputs
config.watchOptions = {
- ignored: ['**/node_modules/**', '**/.next/**', '**/dist/**'],
+ ignored: [
+ '**/node_modules/**',
+ '**/.next/**',
+ '**/dist/**',
+ '**/@mf-types/**',
+ '**/@mf-types.zip',
+ ],
};
// Grab the existing rule that handles SVG imports