How to use with Module Federation
The first thing you will need to do when implementing Federated Capacitor is choose a web based micro frontend solution. The most common is Module Federation.
Module Federation Implementation
The most common use case for module federation is sharing modules across web applications. This allows you to stitch together micro frontends from many different applications into your own. The caveat with this approach is that you become dependent on network access and latency. On web this isn't a problem but within mobile applications it can create a poor user experience.
We aim to solve this problem with Federated Capacitor. You are still using module federation to stitch together independent modules, but the modules are located physically on the mobile device. Updates are pushed to the device using AppFlow and Live Updates to update each of these modules independently.
Serving the files from the local device vs serving from a remote location creates a dramatically improved First Contentful Paint (FCP) and it also allows for an offline experience.
Local vs Mobile Configuration
After you have chosen and setup module federation between your apps you will need to configure it for Capacitor. One way to do this is to add an environment variable to your npm build script.
In this case we are setting the variable CAP_BUILD
to true. In the example below we are using cross-env
to set the environment variable within our npm build script.
"scripts: {
"build": "cross-env CAP_BUILD=true nx run-many --target=build --all",
...
}
This variable is then accessed within your module federation configuration as a way to identify when to use the Capacitor paths for your remotes. You can see below that we have three different MFEs that we are pulling into our primary Capacitor application (account
, checkout
, helpinfo
).
const isCapBuild = process.env.CAP_BUILD;
const remotes =
isCapBuild == null
// Configuration for when developing locally
? {
account: 'account@http://localhost:3004/remoteEntry.js',
checkout: 'checkout@http://localhost:3005/remoteEntry.js',
helpinfo: 'helpinfo@http://localhost:3006/remoteEntry.js',
}
// Configuration for when building for capacitor
: {
account: `account@account/remoteEntry.js`,
checkout: `checkout@checkout/remoteEntry.js`,
helpinfo: `helpinfo@helpinfo/remoteEntry.js`,
};
module.exports = {
name: 'shell',
remotes,
...
}
Now when you run npm run build
it will generate a build that is built to work with Federated Capacitor.
Capacitor Configuration
The next step is to configure Capacitor so that it knows where these files exist on the initial application build. You can see that there is configuration for the shell or main application and then config for the MFEs that are separate.
Monorepo
The webDir
paths are relative your the base directory of the shell application (where this configuration file lives). The names correspond to how you named the directories within the module federation config (account
, checkout
, helpinfo
). The shell application webDir is defined at the top-level as is customary for vanilla Capacitor applications
const capacitorConfig: CapacitorConfig = {
appId: "io.ionic.fedcap.ecommercewebapp",
appName: "FederatedCapacitor Web App",
webDir: "./build",
plugins: {
// Federated Capacitor configuration
FederatedCapacitor: {
shell: {
name: "shell",
},
apps: [
{
name: "account",
webDir: "../account/build",
},
{
name: "checkout",
webDir: "../checkout/build",
},
{
name: "helpinfo",
webDir: "../helpinfo/build",
},
],
},
},
};
After this configuration is complete you should be able to build the shell application and see everything tied together in your native emulator. To test in iOS run npx cap open ios
and then build in Xcode.
Polyrepo
Having your applications in separate repos requires additional setup for each individual application:
1. Add the web applications to Appflow
After logging into your Appflow account go to the Apps page.
In the upper right hand corner you will be able to select Import existing app
.
- Provide an
App Name
. Capacitor
, as the mobile architecture- Choose your git host. In this example we have selected
Github
2. Web application builds
After the app has been created you will want to go to the Builds
page. This is where you will create new builds and see previous builds. Anytime you want to deploy a new version of the web application you will need to create a build from this screen or by using the Ionic Cloud CLI (which we will cover later).
Also in the top left corner of these screens you will see the Appflow App id. In this case it is 11a0971f
. This id will be used when we configure FederatedCapacitor in the Capacitor configuration.
3. Build the connected application
After the application has been added to Appflow you will need to create your first build so that it is available to seed the Microfrontend in the Native App.
This can be done by hitting the New Build
button on the 'Builds' page. Then you will choose a the most recent commit to create the build from.
When creating a new build there are a few values that we need to change on the initial build for the app.
Target Platform
should beWeb
Build Stack
should just be the default which is the latest.Live update
should be turned on andChannel
should be set toproduction