11 likes
·
3.1K reads
19 comments
Hi José Pablo Ramírez Vargas, super helpful series. Especially since there has not been much out there around single-spa that is really up to date. Really like the thoughtful, in-depth approach and you explain very well, I find.
You state in this article that Furthermore, we concluded that it is wasteful to create a UI-less root.
However, following along with the code we do not get to a point where the root is actually a UI, say a Main Navigation for example.
Have you explored this further? I only got started with playing around with it, and there are a few behaviours to do with the routing that are still a bit unclear to me.
So anything you are able to share would be helpful.
Thanks again. And keep up the good work!
Hello, Jan! I am glad you find this helpful. Indeed, from the looks of the search results in Google and Bing, I'm kind of the foremost authority in the subject for now, hehe. So I'll do my best to live up to the expectation.
I have indeed created roots with UI. I haven't played with routers, though. I realize routers may be a pain point, and I bet it is very difficult to reconcile a single-spa project that loads routers from multiple frameworks, like a router in React with a router in Vue. Vue routers seem tricky.
I do have, however, a "play" project in GitHub with a navbar-like UI in Svelte: github.com/webJose/single-spa-and-svelte
Feel free to look at it. Again, no router stuff yet in my research, but I have it present. Follow the series as this is not yet over.
Hi again José,
thanks for the swift reply.
The main missing piece in fact was the mount point of the microfrontend.
Which I figured out can be passed to for example singleSpaReact like so: domElementGetter: () => document.getElementById('react-mifo-container')
[other framework helpers have similar options I believe]
That way the mount point can be nested easily wherever in your component tree you need it.
And as long as the router of the apps is a browser history based router, it all works great.
i.e. the single-spa setup determines which app handles which paths generally and then the individual apps' figure out which content to display exactly based on the precise url path (+ params).
Cheers, Jan
Jan Steinhoff Hi! I somehow missed your comment. Yes, that is one way to set the mount position. Generally speaking, you can use a special single-spa
ID in a block element: <div id="single-spa-application:mifeName"></div>
, where mifeName
is the name you give the application in the call to registerApplication()
.
This package as well as this entire blog is revolutionary and is a core piece in the development of the single-spa framework for Vite!
Hello, Nihir. I am glad you find it useful. Indeed, when I started my journey there was little to nothing to start with. By now, vite-plugin-single-spa
is in v0.5.2 supporting multiple exports, multiple parcel/micro-frontend instances and just today had a hotfix. Please drop by GitHub and give the project a star and a follow so you don't miss releases and other important information.
Cheers!
Hello, thank you for the articles
I've created root-project (Vite + Vue) & app (Vite + React) based on your example, right now trying to configure second app using (Vite + Vue) as another project module for root-project In your example there 2 active applications on route /mifea (as we can see vite + vue & vite + react)
What I'm trying to achieve is to activate only one app (that is responsible for price page) on route /price (for example) And on route /admin activate project that's responsible for admin page
Would appreciate if you could provide some advice on how to achieve that behavior?
Basically on 1 route (/price) I want to see price-app On 2nd route (/admin) I want to see admin-app
Dorov Toni Hello. There's nothing special you need to do for your scenario. Yours is just textbook scenario described by single-spa: Simply set the registration for each application to use different routes. That's it.
const spas = [
{
name: 'price',
moduleName: '@myApp/price',
activeWhen: '/price'
},
{
name: 'admin',
moduleName: '@myApp/admin',
activeWhen: '/admin'
}
];
spas.forEach( s => {
registerApplication({
name: s.name,
app: () => import(/* @vite-ignore */ s.moduleName),
activeWhen: s.activeWhen
});
});
Just like that. Separate routes for each.
José Pablo Ramírez Vargas Thank you :) also styles doesn't loaded
Dorov Toni I have an entire article that explains what needs to be done to load the micro-frontend CSS. Go through it.
Having said that, vite-plugin-single-spa
can do CSS injection for you.
Hello, thank you for the series of articles. What you're doing is really great. I've built my POC application and everything works fine as long as I have the console open. As soon as I close the console and reload the page, a white screen appears. Today, I restarted the application according to this article and the problem occurred again. Could you advise what might be the problem? You know, Single SPA, and even your plugin, I'm using the latest versions of everything.
Hello. I'll be happy to help out if I can. Go to this GitHub Discusssions page and start a new discussion. Describe your problem, including error messages you get and links to your repositories. We can take it from there.
I wrote
Hello José Pablo Ramírez Vargas. During my own journey with single-spa I came across your articles. Thank you for your work and effort to bring vite into single-spa.
In connection with the "standalone" version of the "mife", I stumbled upon a problem that I have not yet been able to solve. What would be the approach if you import a utility module in a "mife". The problem I have is that the import maps for the mife type cannot be set in the plugin and I have not yet figured out how to tell the mife to import this external dependency at runtime.
If I use Webpack, I can import the module manually afterwards using the button (bottom right by default).
Have I overlooked something obvious?
I would be very happy if someone would share their thoughts or suggestions with me. If I get this point solved, then I can switch everything to vite.
Happy Easter to all
Hello, Philip Hahn. In Vite, you set any module alias as an external so the build process won't try to bundle its code. This is not enough for Vite in serve mode (npm run dev
) because serve mode doesn't bundle. What I do is make a small plug-in (really easy to do) that provides a fake module (or even a copy if that's what you need) when working with Vite in serve mode.
If you require further help, open a discussion item here where we have more room to share information and code snippets around.
Hi @José Pablo Ramírez Vargas! Does your vite plugin provide the possibility of bundle an utility module? I'm asking, because your type property only provides 'root' and 'mifi'.
Utility MFE's provide importable modules, is it not? If this is the case, you don't need the plug-in at all, I would say. Just bundle the module and that's it. You can publish it to a CDN and be done.
Is your utility project different somehow?
Hi José Pablo Ramírez Vargas! No, it's just a normal utility project and was created via create-single-spa --moduleType util-module. But when I try to bundle it with vite, this MFE is not found... In the webpack.config.js, what does the singleSpaDefaults do? Must I follow some kind of pattern in vite, to replace it properly or bundle my project in a single-SPA way?
Philip Hahn I don't know webpack, so I cannot help you with this. Anything that create-single-spa creates for me has never even run once for me. Unsure if it is a problem in my PC. It is one of the reasons I quickly moved to an all-Vite solution.
Generally speaking: Utility modules should be bundled and served via a CDN. When more than one MFE import it, it should be added to the root config so it can be shared and is not duplicated. If no UI components are being exported, then you don't need sing-spa stuff anywhere. If there are UI components, it is not a utility project and instead is probably a MFE that exports parcels.