Closed adamhaeger closed 4 years ago
that's what your outer config should do.
you can write all env config in a Map, and get corresponding publicPath by juding env.
env variable can be supplied by your package scripts or npm scripts.
'create a separate build for each environment' is right, all remotes should be served by local server, such as webpack-dev-server.
if you want more flexiable, you can download config from server and use advanced api in MF at runtime.
if you want more flexiable, you can download config from server and use advanced api in MF at runtime.
Thanks for the super swift answer! Sounds like Im on the right track then. I am interested in a more flexible way to set the path though, would be nice to not have to run the build once for each environment.
Is there any examples on how to use the advanced API that you mention? I haven't found this in the docs anywhere.
public path is on the docket for a future release. Allowing hosts to execute initialization code in a remote, like changing public path. For right now. you're stuck with defining it in a hard-coded webpack config. The only solution beyond waiting for us to do it is for webpack
You can reverse engineer this -> https://gist.github.com/ScriptedAlchemy/60d0c49ce049184f6ce3e86ca351fdca
I can confirm that the intermediary approach @ScriptedAlchemy outlined above ☝️ works well in the context of assigning publicPath
's to individual remotes at run time.
We have a Micro Front-end setup using Federated Modules. We can build our artifact once and move it along our environment flow (Dev, Test, Stage, UAT, Prod) without re-building our bundle 🎉
I will describe a simplified version of our system below and hope that it can help others get set up and working with the Federated Module paradigm 🙏
To achieve this environment agnostic setup, we use two configuration files:
location.config.json
A global reference of each Micro Front-end's endpoints on a per-environment basis.
environment.config.json
A file scoped to the root of each environment bucket that gives the application its context at run time.
When we build our artifact, we exchange the static public path for a function that will execute at run time.
The function expects global variables to be present in the windows scope, so we need to set them up at run time before calling the function (see below) 👇 .
First, we fetch our configuration files (location.config.json
and environment.config.json
), then assign them to global variables.
From there, we fetch all of the required Javascript (generic bundle and remoteEntry.js
data) and add it to the page.
When the Javascript added above ☝️ initialises, it will generate a publicPath
based on the global variables that hold our configuration files 🎊
I hope that this helps someone 🙏
This has proven effective in our team so far. The Webpack and HTML (shell) orchestration is generic and can be used for each Micro Front-end as part of a boilerplate 👍
This would be a great topic to cover in Practical Module Federation (which I enjoyed reading BTW) 😃 .
This has been resolved. https://link.medium.com/odRa0yWMdab
For anyone needing a working solution, I put together a repository using the code and methods outlined by devonChurch and ScriptedAlchemy above; thank you both for sharing your insights!
https://github.com/waldronmatt/dynamic-host-module-federation
https://dev.to/waldronmatt/tutorial-a-guide-to-module-federation-for-enterprise-n5
at the moment, 2022, set publicPath: 'auto'
works perfectly.
Anyway, thanks @devonChurch for his solution with DynamicPublicPathPlugin
, I have followed that solution, it has been working fine for a while.
yep publicPath: auto is the built in way, it uses document.currentScript.src to get the base path based on where the remote came from to begin with
publicPath : auto
is not working as expected . In my react micro frontend project which uses module federation plugin remoteEntry.js path is incorrectly fetched and application crashes.
With hard-coded publicPath
in webpack things work as expected.
Due existing CI/CD setup in my project, I couldn't hard-code publicPath at the build time.
it was recommended to use publicPath : auto
in the webpack config of the application.
Yes publicPath : auto
solves the issue of hard coding at build time.
But during page refresh, remoteEntry.js
is fetched from incorrect url.
To simulate the scenario I created a simple react application using webpack and module federation plugin
On the initial load remoteEntry.js is fetched from http://localhost:3000/remoteEntry.js
as expected
When under nested URL http://localhost:3000/home/foo/about
, On refresh main.js and remoteEntry.js is fetched from http://localhost:3000/home/foo/remoteEntry.js
- application crashes
Github link for the project simulating the scenario https://github.com/jidu0106/mf-page-refresh-issue
I am using "react-router-dom": "^6.3.0" and also tried with "@reach/router": "^1.3.4", but the issue is same
probably a config issue with how youre serving the spa. it always is
probably a config issue with how youre serving the spa. it always is
Thanks for the response.
With reference to https://github.com/module-federation/module-federation-examples/pull/2170 adding another publicPath : '/'
in HtmlWebpackPlugin() solved the issue
new HtmlWebPackPlugin({
template: './public/index.html',
favicon: './public/favicon.png',
assets: './public/assets',
publicPath: '/',
}),
@cyberfury10
assigned to HtmlWebpackPlugin
as above code, but still request bundle file in wrong place when refreshed. 😥
the publicPath of the host app is set to'auto'
and the publicPath of the remote app is set to domain
(ex: http://localhost:4000).
is there anything I set wrong? I'd appreciate your advice.
@taylous I had the same issue and setting the base field in the HtmlWebPackPlugin
config, seems to help:
new HtmlWebPackPlugin({
template: './public/index.html',
// ...
base: { href: '/' }
}),
Thanks for the response. With reference to #2170 adding another
publicPath : '/'
in HtmlWebpackPlugin() solved the issue
Man! That is really helpfull! I've spent so much time trying to configure my project to work as standalone and via module federation at once and this fixed the issue with page refresh in standalone mode.
Now I have in my webpack config:
output: {
publicPath: 'auto', // this is for Module Federation exposition
},
...
plugins[
new HtmlWebpackPlugin({
publicPath: '/', // this is for standalone mode
...
],
Having this error I am unable to resolve this @robinsout [ Module Federation Manifest Plugin ]: Manifest will not generate, because publicPath can only be absolute path, but got 'auto' (node:20292) [DEP_WEBPACK_PRE_COMPILED_SCHEMA_INVALID] import { NextFederationPlugin } from '@module-federation/nextjs-mf';
const nextConfig = {
reactStrictMode: true,
webpack: (config, options) => {
const { isServer } = options;
config.plugins.push(
new NextFederationPlugin({
name: 'shop',
remotes: {
main: main@http://localhost:3000/_next/static/${isServer ? 'ssr' : 'chunks'}/remoteEntry.js
,
},
filename: 'static/chunks/remoteEntry.js',
exposes:{
'./catalog': "./src/components/MISCard.tsx"
},
extraOptions: {
exposePages: true
},
// publicPath:'/'
})
);
config.output.publicPath='auto';
console.log(config.output);
return config;
}
}; export default nextConfig; I have tried to set the both you said either of them haven't solved this error I am also unable to run my application My OS-Windows 10 I am using "webpack": "5.1.3", "next": "14.1.4"
look into runtime plugins from module-federation/enhanced and /runtime - this would let you control more aspects
look into runtime plugins from module-federation/enhanced and /runtime - this would let you control more aspects
https://module-federation.io/configure/getpublicpath.html
This worked for me.
Hi!
Im amazed and grateful by all this work, truly a gamechanger! Very smooth to implement, but the one thing Im struggling with is publicPath. I know there is a pr up to solve this, but there seems to be debate about whether it should be merged or not.
In our case, we have a host application that has dev, test and prod environments, and then the remote apps also have dev, test and prod environments. So the host app in dev, needs to load the remote code from dev etc. It seems to me that the only way to achieve this currently is to create a separate build for each environment. Is this correct or is there a workaround?
Thanks again!