react-router-composer
v1.0.3-alpha.0
Published
Build Time Micro-Frontends: Orchestrate multiple React Router (^7.0) applications into a single application
Readme
react-router-Composer
react-router-composer is a build time microfrontend tool that merges multiple React Router applications into a single unified wrapper application. This simplifies management and deployment while supporting environment-specific configurations for branches and applications.
Installation
Install react-router-composer as a development dependency in your wrapping application:
npm install -D react-router-composerConfiguration
Create a configuration file named react-router-composer.config.json in the root of your parent project (child projects do not need this config file). This file defines the applications to merge and their respective settings.
Example Configuration
{
"subApplications": [
{
"name": "dashboard",
"repo": "https://github.com/foo/bar.git",
"envConfig": [
{
"NODE_ENV": "development",
"branch": "dev"
},
{
"NODE_ENV": "qa",
"branch": "qa"
},
{
"NODE_ENV": "production",
"branch": "prod"
}
]
}
]
}Configuration Options
subApplications
An array of objects, each representing a sub-application to merge.
name(string): The name of the sub-application.repo(string): The Git repository URL of the sub-application.envConfig(array): Defines environment-specific configurations.NODE_ENV(string): The environment name (e.g.,development,qa,production).branch(string): The branch to use for the specified environment.
Notes:
- All configuration options are required.
Usage
Run the tool using the following command:
react-router-composerYou can also specify an environment flag to select a specific branch and configuration:
react-router-composer --env qaHow It Works
The --env flag maps to the envConfig specified in your configuration file. For example, running react-router-composer --env qa will:
- Set
NODE_ENVtoqa - Use the
qabranch as defined in the example configuration.
File Structure After Merging
When react-router-composer runs, all subApplications are merged into the wrapper application as follows:
- Routes: Sub-application routes are added under
app/routes/<subApplications.name>.<file-name>.tsx. - Imports:
react-router-composeranalyzes and resolves project-specific imports marked with"@/"(e.g.,import Header from "@/components/Header").- These components, utilities, or dependencies are copied into subdirectories within the wrapper application, such as
app/components/<subApplication.name>/Header.tsx. - Import statements are updated to reflect the new locations.
- These components, utilities, or dependencies are copied into subdirectories within the wrapper application, such as
- Dependencies: Sub-application
package.jsonfiles are analyzed, and theirdependencies,peerDependencies, anddevDependenciesare merged into the wrapper application. If two sub-applications declare the same dependency with different versions, the newest version will be used.
Key Notes:
- Original code in the sub-application repositories remains untouched.
- All modifications occur on copied files inside the parent (wrapper) application.
Route Manifest Configuration
Ensure that routes.manifest.json is configured on all applications that require composition. This file should list all the routes that need to be composed into the wrapper application.
Example routes.manifest.json
[
{
"path": "/home",
"filePath": "routes/home.tsx",
"index": true
},
{
"path": "/settings",
"filePath": "routes/settings.tsx"
}
]path(string): The route path.filePath(string): The file path to the route component.index(boolean, optional): Indicates if this is an index route.parentApp(boolean, optional): Should only be used in the wrapping project and defines the root routes. Each item in the manifest of the wrapper project should have this flag:
Example Wrapper routes.manifest.json
[
{
"path": "/home",
"filePath": "routes/home.tsx",
"index": true,
"parentApp": true
},
{
"path": "/settings",
"filePath": "routes/settings.tsx",
"parentApp": true
}
]Important Notes:
Any items in the manifest that use the index flag will use the index function from import { index } from "@react-router/dev/routes". Otherwise, they will use import { route } from "@react-router/dev/routes".
The path defines the application route path. The filePath defines the relative location of the route component file. The parentApp flag should only be used in the wrapping project and defines the root routes (otherwise the wrapping app will also be placed in a subdirectory).
Key Features
- Environment Mapping: Seamlessly map environments to specific branches using the
envConfigoption. - Multi-App Merging: Easily merge multiple React Router applications into one.
- Automatic Import Updates: Resolve and adjust project-specific imports for a unified structure.
- Dependency Resolution: Automatically merge and deduplicate dependencies across sub-applications.
- Non-Intrusive: Sub-application repositories remain unmodified; all changes are scoped to the wrapper application.
- Custom Configuration: Fully customizable via a simple JSON configuration file.
Caveats
THIS PROJECT IS STILL ALPHA
Currently it only merges package.json, routes, components
To Dos:
- Migrate to React Router v7.x
- Shared state between subApplications and wrapper application
- Expand the merge to include: typeDefs, stores, hooks, APIs/Middleware, Contexts etc...
This package is highly opiniated around the project structure and will probably become even more so in later versions. It is designed to only work with a group of applications running on the same React/React Router versions. The purpose is to have invidual siloed projects that can be developed and deployed in isolation but then also deployed via a single unified wrapper application, i.e. you can have a Header component in the wrapper which links to the individual subApplication routes.
Why?
This significantly improves performance and developer experience compared to module federation. If you are building applications as part of a larger application suite. You can work in isolation in lower environments, and then deploy to a single unified application in the upper environments for simpler user experience and end to end testing.
License
This project is licensed under the ISC License.
Copyright 2024 Hassan Mehdi
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
