Module Federation: Vite + Webpack
Vite, Module Federation, & Webpack

Module Federation: Vite + Webpack

We've been using Webpack's Module Federation (MF) quite effectively for some time now across my organization. It's one of the reasons why we are able to safely and quickly (at scale) allow our product teams to independently deploy and release their products in production.

Keeping up with JavaScript

We've been using Webpack since its initial release 9 years ago and it has been a staple in our toolbox for almost every single web application that we've built. One of its attractions for us is because it has sensible defaults. To put it simply; it works and that's one of the best things that can expect to a tool that you use. You, your team, and your organization can rely on it, every day, every single time.

As time went on, there's been a couple of Webpack contenders where we seriously considered using, to the point that they were starting to become legitimate Webpack replacements. These new and upcoming tools can't really promise the reliability and stable environment of Webpack, but what they can promise is speed and performance. Who doesn't like their builds to be faster?

Here's some of the tools that we've considered.

Fast-forward to 2023 and it's time for us to revisit Webpack contenders again.

The frontend tool that we've landed on is Vite. Vite took the JS community by storm back in 2020 and ever since then, it has matured to a frontend tool that we believe, can now be safely used for production.

Here's one caveat though, we're still using Webpack in production. And as you may have noticed from my previous war stories, we're not "a team", we're a team of teams, in short, a big organization. We have to take some extra care when giving guidance on what our recommended frontend tool would be for everyone.

Avoiding internal friction

Friction among teams is something that my team aggressively tries to avoid. If we cannot avoid friction, then we'll try and reduce it. We've learned in our developer experience journey that if our product teams actively see that we are really trying to make their lives easier and we are meeting them where they are at, that it's a lot easier to get buy-in and get wide adoption of new tools that we recommend.

Which is why one of my requirements as product manager is that we find a solution where teams can gradually move away from Webpack and start using Vite.

The second requirement that I have for my team is to retain the setup's invisible infrastructure, where our product teams don't really need to know that they exist so they can keep focusing on developing our product and not on tooling.

Webpack and Vite by themselves are relatively easy to use. It's when you take into account module federation that things start becoming a little bit complicated. Add to the fact that we have recently moved (and still moving) away from CommonJS and into a pure ESM, then that complication by module federation becomes two fold, at least initially.

Here's how we manage to get Vite and Webpack module federation setups work extremely well toward one another.

Initial setup

Some of the initial setup that you need to know before we start diving into our journey of making things work.

  • package.json is ESM e.g. "type": "module".
  • Webpack exports the bundle using "type": "module".
  • Module Federation is unidirectional a.k.a. one host and several remotes.
  • We deploy to /assets/<repository name>.

mf-core

webpack.config.js

The mf-core repository acts as our one true host. The composer of all the remotes. And from a React perspective, this package is where most of our singleton providers live.

You can see that mf-core gets deployed to /assets/core and both mf-pkg-a and mf-pkg-b gets deployed to /assets/pkg-a and /assets/pkg-b respectively.

mf-pkg-a and mf-pkg-b

webpack.config.js
webpack.config.js

Both mf-pkg-a and mf-pkg-b have identical configurations. The only difference is the name of the federation module; PKGA versus PKGB.

As far as how mf-core imports them, it will be like PKGA/app and PKGB/app.

Vite

Our Vite setup, believe it or not is pretty simple. Behold.

vite.config.ts

The only plugin that we use is @vitejs/plugin-react-swc since we want things to be a little bit faster than the default plugin for React during development. This plugin replaces Babel and replaces it with swc/esbuild.

First decision tree

Webpack has a built-in plugin for module federation so you don't have to think about this part on a Webpack + Webpack setup, but for a Vite + Webpack setup, you have two options–@module-federation/vite or @originjs/vite-plugin-federation.

The first thing that we had to take a look is if this plugins that we're looking at are compatible with a Vite + Webpack setup. Because if it doesn't support that integration then we can't move forward with out first requirement–gradual updates.

The second thing that we had to take a look is what the initial setup looks like, and then compare it to what our current Webpack setup looks like. The reason why this is important is because we do not want the extra cognitive load for our software engineers when they are looking into migrating to Vite's module federation. If it's really close to our current setup right now, then it's a win.

We picked @originjs/vite-plugin-federation as it hits both requirements that we have.

Second decision tree

Looking at our current module federation setup, it's unidirectional. So we have to pick if our host will be Vite and Vite/Webpack remotes or Webpack host and Vite/Webpack remotes.

For us, the decision was easy. If we will eventually move to Vite, then we want to make sure if Vite (host) + Webpack (remote) works versus Webpack (host) + Vite (host).

Implementation

Time to get to work. mf-pkg-a and mf-pkg-b starts on 8081 and 8082 respectively. Our initial assumption was that we wouldn't have to change anything on our current Webpack configurations.

Next step is updating the host configuration which is mf-core.

This was now our Vite configuration after reading the documentation.

vite.config.ts

Errors

Chrome DevTools watching https://localhost:5173

At first glance and even 3rd, this absolutely makes no sense. Why aren't these files available to the browser? So we had to look for additional clues. Lucky for us, Vite gave us some clues.

Missing "./package.json" specifier in "mf-pkg-c" package        

We're getting somewhere but we're still in the "WTH" mode after seeing this error. How can mf-pkg-c which was working perfectly before have a missing package.json file?

It turns out that currently the plugin that we're using for module federation has a hard time reading a pure ESM npm packge.json if it's using the exports field. So you have to specify the versions in the shared config.

Here's the updated config. Take note of the shared property in module federation. Instead of an array, it is now a map of npm packages and their versions.

vite.config.ts

Once you've updated your config, Vite should now restart the server and your module federation setup should work.

Refactors

Now that we got it to work, we also want to make sure that it works on both local and in production.

We know that if we're building the source files, Vite sets NODE_ENV to production and if we're using dev mode then Vite sets NODE_ENV to development. We can use this to determine whether we should be using localhost or a relative path.

Here's the complete config that works for us.

vite.config.ts


VISHAL JANGID

Frontend Engineer | JavaScript | ReactJs | NextJs

1 年

I am using vite as remote app and webpack as host app and I am getting error *scriptExternalLoadError:loading scrip failed.* Can you help me to solve this error ?

Alberto Miranda

Fullstack Engineer / Team Lead at First Arriving

1 年

Nice experience! Thanks for sharing :)

回复

要查看或添加评论,请登录

Rodo Abad的更多文章

社区洞察

其他会员也浏览了