Step 5: Routing
The second task that micro-lc accomplishes is routing.
Routing is configured via the application's route
field. Each integrationMode
has one.
Applications must be divided into two groups:
- Those that need to know where they are mounted.
- Those who don't.
We determine which group an application belongs to by examining its use of the browser's history API
.
The first group includes:
- Any
iframe
integrated application. - Any
compose
integrated application that doesn't use web components that push onto thehistory
. - Any
parcel
that doesn't have a router. - Any
parcel
that has a hash router. - Any
parcel
that has an in-memory router.
These applications either do not use the history API
or use it without causing side effects for micro-lc centralized routing.
All other applications may use the history
API, and special handling is required for them.
The Route Property
The route
property takes a string, which can have dynamic segments. Out of the registered routes, micro-lc will activate the longest match in terms of characters, excluding the dynamic segments.
For parcels, an explicit trailing slash must be placed on the route of an application that has internal routing:
{
...
"applications": {
...,
"hash": {
"route": "/hash/",
...
}
}
}
The trailing slash is not automatically added. This ensures that single-page applications without internal routing can be displayed even if the route called lacks a trailing slash. This is common when the webserver enforces the rule:
If I don't find a file or a directory, I will try to serve the
./index.html
resource from that path
micro-lc is not, by default, aware of any webserver rule and won't ever attempt to mimic it by appending slashes or automatically re-routing.
To enforce re-routing rules, nginx comes in handy with the directive:
try_files $uri $uri/index.html /index.html =404;
Base Injection
Now let's try to integrate an application with internal routing. We can use a showcase React application with browser routing
This application was developed using a micro-lc React template. By examining the repository:
{
...
"homepage": "./", 👈 relative url
...
}
We can see that local development of the application is straightforward on /
since static assets, once built, will be relative to the entry point (the index.html
).
To let micro-lc know that it should instruct this application to prepend a pathname to its current relative entry point, we use the injectBase
property.
{
...,
"applications": {
...,
"browser": {
"integrationMode": "parcel",
"route": "/browser/", 👈 notice the trailing slash
"injectBase": true,
"entry": "https://cdn.mia-platform.eu/micro-lc/examples/0.1.3/static/parcels/react-browser-router/index.html"
}
},
...,
"layout": {
"content": {
"tag": "bk-layout",
"properties": {
...,
"menuItems": [
{
...
},
{
...
},
{
"icon": {
"library": "@fortawesome/free-brands-svg-icons",
"selector": "faReact"
},
"id": "browser",
"label": "Browser",
"type": "application"
}
]
}
},
"sources": [
...
]
}
Both /hash/
and /browser/
routes are properly expanded within the parcel applications.
This is because a base tag is injected into the entry point of the application. micro-lc calculates the base path of the parcel that's about to be activated based on the route fields and any existing base tag in the main index.html, making it accessible in the application.
Applications can recover it by using the query selector qiankun-head base
.
What about applications that already come with a base tag?
The injectBase
takes options here. If true
it will attempt to add a base tag only if none is present, whereas if
override
it will remove any base tag present and inject one.
Let's add an angular application which has a base tag already. If you inspect the entry index.html you'll notice that
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Angular13</title>
<base href="/"> 👈 already set to /
...
</head>
<body>
</body>
</html>
Let's say that we'd like to expose this application under /angular/
.
We add the application:
{
...,
"applications": {
...,
"angular": {
"integrationMode": "parcel",
"route": "/angular/",
"injectBase": "override", 👈 override the base tag
"entry": "https://cdn.mia-platform.eu/micro-lc/examples/0.1.3/static/parcels/angular13/index.html"
}
},
...,
}
and the menu entry
{
...,
"layout": {
"content": {
"tag": "bk-layout",
"properties": {
...,
"menuItems": [
{
...
},
{
...
},
{
"icon": {
"library": "@fortawesome/free-brands-svg-icons",
"selector": "faAngular"
},
"id": "angular",
"label": "Angular",
"type": "application"
}
]
}
},
"sources": [
...
]
}
Let's try to make a framework-independent custom parcel application...