-
Notifications
You must be signed in to change notification settings - Fork 168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Bug]: MF breaks the asset path when more than one sub path #2482
Comments
Note that when you use |
Note that |
|
Is public path set to auto? |
Was fixed in dev by setting Updated the codesandbox to demo when it fails with |
I tried to change publicPath to / but it is not working for the host app. |
Did you setup MF via tools: {
rspack: (config, { appendPlugins }) => {
config.output.publicPath = "/";
appendPlugins([
new ModuleFederationPlugin({ // ...my options })
]);
},
}, |
I'm using the v1 moduleFederation.options . |
No certain but I think you can find the plugin of the 1.5 from |
maybe related to #2747 ? |
To resolve this issue, upgrade to the latest version of Module Federation. |
@imzisy this issue also happen with the built-in module federation of rsbuild, not only using the external plugin |
After upgrading to |
this doesn't seem like an issue anymore. should be safe to close it? |
Fixed on the latest versions |
@XavierLeTohic whats the resolution for this? It's not clear on how we can resolve this issue as I'm currently facing the same. By upgrading to @rsbuild/core latest, can we still use the built-in |
@petrosD93 we ended up setting MF options using: import { defineConfig } from '@rsbuild/core';
export default defineConfig({
tools: {
rspack: (config, { appendPlugins, rspack }) => {
appendPlugins(
[
new rspack.container.ModuleFederationPlugin({
// mf config
}),
],
);
}
}
}); I thought that issue would have been fixed using |
@ScriptedAlchemy thanks for pointing this out, I was following the documentation of RsBuild. My issue seems to be more complex though. I am trying to transform our projects from Webpack to RsBuild. Thing is I am using the API of MF to load remotes (that was done in order to be able to change MF Config of remotes at runtime, and to also ensure proper error handling of host application when one of the remotes are failing). I understand that the logic we used back then was depending on fetching remote js modules, where now we do fetch the mf-manifest.json. I wonder if there is any documentation on how to use the API of module federation with RsBuild and the module federation plugin |
Federation runtime might be useful? https://module-federation.io/guide/basic/runtime.html Primarily the main thing is you should be using the package from us and not the builtin container object in the bundler. Since those just expose the base classes from rust side of rspack. |
@ScriptedAlchemy tools: {
...config.tools,
rspack: {
...config.tools?.rspack,
output: {
publicPath: 'auto',
// clean: true,
},
},
}, , everything worked, but then I started to configure react tanstack router and realized that internal routes do not work because the js script is inserted
so all internal routes, say /dashboard/edit, don't work. When I removed publicPath: auto, the router started working and in dev mode mf works, but in production build, the microfrontend stopped working: You can see that the paths referenced by module federation are wrong, it inserts relative paths localhost:3000, but the bindle files themselves are localhost:3051 (in remove app). I using: @module-federation/rsbuild-plugin |
@XavierLeTohic Can you help please? |
Have you tried using module federation directly getting it from the container like in my last comment above? I haven't tried @module-federation/rsbuild-plugin yet. |
@XavierLeTohic Yes, this is my config: import type { moduleFederationPlugin } from '@module-federation/sdk';
import { loadEnv, RsbuildConfig } from '@rsbuild/core';
import { pluginReact } from '@rsbuild/plugin-react';
import { pluginSass } from '@rsbuild/plugin-sass';
import path from 'path';
// eslint-disable-next-line import/no-relative-packages
import packagesVersion from '../../../package.json' assert { type: 'json' };
const { parsed } = loadEnv();
const defaultPublicEnvList: (keyof ImportMetaEnv)[] = ['API_GATEWAY'];
const typedParsed = parsed as Record<keyof ImportMetaEnv, string>;
export const rsbuildConfig = (
config: RsbuildConfig = {},
moduleFederation: moduleFederationPlugin.ModuleFederationPluginOptions = {},
publicEnvList: (keyof ImportMetaEnv)[] = [],
): RsbuildConfig => {
const plugins = [...(config.plugins ?? [])];
plugins.push(
pluginReact(),
pluginSass(),
// pluginModuleFederation({
//
// }),
);
const resultConfig: RsbuildConfig = {
...config,
server: {
...config.server,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization',
},
publicDir: [
{
name: 'public',
watch: true,
},
{
name: path.resolve(__dirname, '../../../libs/ui/public'),
watch: true,
},
],
},
source: {
...config.source,
define: Object.keys(typedParsed)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
.filter(item => publicEnvList.includes(item as any))
.concat(defaultPublicEnvList as never)
.reduce(
(prev, key) => {
const sanitizedKey = key.replace(/[^a-zA-Z0-9_]/g, '_');
prev[`import.meta.env.${sanitizedKey}`] = JSON.stringify(parsed[key]);
return prev;
},
{} as Record<string, string>,
),
},
output: {
...config.output,
cleanDistPath: true,
},
tools: {
...config.tools,
rspack: (config, { appendPlugins, rspack }) => {
appendPlugins([
new rspack.container.ModuleFederationPlugin({
...moduleFederation,
dts: true,
manifest: true,
shared: {
react: {
singleton: true,
requiredVersion: packagesVersion.dependencies.react,
},
'react-dom': {
singleton: true,
requiredVersion: packagesVersion.dependencies['react-dom'],
},
jotai: {
singleton: true,
requiredVersion: packagesVersion.dependencies['jotai'],
},
'jotai-effect': {
singleton: true,
requiredVersion: packagesVersion.dependencies['jotai-effect'],
},
clsx: {
singleton: true,
requiredVersion: packagesVersion.dependencies['clsx'],
},
zod: {
singleton: true,
requiredVersion: packagesVersion.dependencies['zod'],
},
},
runtimePlugins: [
path.resolve(__dirname, './module-federation-plugins/shared-strategy.ts'),
path.resolve(__dirname, './module-federation-plugins/offline-remote.ts'),
],
}),
]);
},
},
html: {
...config.html,
template: './template.html',
},
performance: {
...config.performance,
chunkSplit: {
...config.performance?.chunkSplit,
strategy: 'single-vendor',
},
},
};
return {
...resultConfig,
plugins,
};
}; Host app rsbuild.config.ts import { rsbuildConfig } from '@platform/rsbuild-config';
import { defineConfig } from '@rsbuild/core';
// eslint-disable-next-line import/no-relative-packages
import mfConfigs from '../../.deploy/mf.json' assert { type: 'json' };
const env = process.env.ENV;
const appConfig = mfConfigs.mfs.app;
if (!appConfig) {
throw new Error('You dont setup this mf in mf.json!');
}
export default defineConfig(
rsbuildConfig(
{
server: {
port: appConfig.ports[env],
},
},
{
name: appConfig.name,
remotes: appConfig.mfs.reduce((acc, curr) => {
return {
...acc,
[curr.alias]: `${curr.name}@${curr.entry[process.env.NODE_ENV][env]}`,
};
}, {}),
},
),
); Remote app rsbuild.config.ts import { rsbuildConfig } from '@platform/rsbuild-config';
import { defineConfig } from '@rsbuild/core';
// eslint-disable-next-line import/no-relative-packages
import mfConfigs from '../../.deploy/mf.json' assert { type: 'json' };
const env = process.env.ENV;
const appConfig = mfConfigs.mfs.tasks;
if (!appConfig) {
throw new Error('You dont setup this mf in mf.json!');
}
export default defineConfig(
rsbuildConfig(
{
server: {
port: appConfig.ports[env],
},
},
{
name: appConfig.name,
filename: 'remoteEntry.js',
exposes: {
'./Tasks': './src/components/Tasks.tsx',
},
},
),
); But, I got same issue with @module-federation/rsbuild-plugin |
What happens if you set the publicPath to "/" instead of auto? I would recommend that you make either a reproducible example in a repository or a code sandbox |
I wrote it like this: tools: {
...config.tools,
rspack: {
...config.tools?.rspack,
output: {
publicPath: '/',
// clean: true,
},
},
}, Nothing has changed, I'm very tired:( |
I will have a look tomorrow, also why are you spreading the default rsbuild config everywhere? It's not gonna erase the whole config at the end but apply some kind of patch |
Do you think it is necessary to write publicPath="auto" only for remote apps? |
@VictorPulzz have a look at this module-federation/core#3343 I ended up using the base meta tag |
@XavierLeTohic @petrosD93 import { rsbuildConfig } from '@platform/rsbuild-config';
import { defineConfig } from '@rsbuild/core';
// eslint-disable-next-line import/no-relative-packages
import mfConfigs from '../../.deploy/mf.json' assert { type: 'json' };
const env = process.env.ENV;
const appConfig = mfConfigs.mfs.tasks;
if (!appConfig) {
throw new Error('You dont setup this mf in mf.json!');
}
export default defineConfig(
rsbuildConfig(
{
server: {
port: appConfig.ports[env],
},
tools: {
rspack: {
output: {
publicPath: 'auto',
},
},
},
},
{
name: appConfig.name,
filename: 'remoteEntry.js',
exposes: {
'./Tasks': './src/components/Tasks.tsx',
},
},
),
); Everything seems to work, locally dev/prod, as well as on amazon, I want to put my setup rsbuild+eslint+prettier+tailwind+mf in a separate monorepo, maybe it will help someone, as I will write here:)) |
Version
Details
When setting
moduleFederation.options
and reloading with more than one sub path (.i.e/sub/path
) Rsbuild inject assets without the prefix/
even settingoutput.assetPrefix: "/"
resulting in a white page.Commenting or removing the whole
moduleFederation
from rsbuild config and everything works well.See the attached Codesandbox and repository to reproduce.
Reproduce link
https://codesandbox.io/p/github/XavierLeTohic/rsbuild-mf-asset-path/main
Reproduce Steps
The repo of the codesandbox is here:
https://github.com/XavierLeTohic/rsbuild-mf-asset-path
To reproduce:
npm install
oryarn install
npm run dev
oryarn dev
http://localhost:5050/example
everything will work as expected if you reloadhttp://localhost:5050/example/sub/path
and reload it will be brokenrsbuild.config.ts
and try to reload it'll workThe text was updated successfully, but these errors were encountered: