@polyfea/core
v1.3.1
Published
Polyfea Core Library
Readme
Polyfea microfrontend core library and browser driver
This package is the backbone of the Polyfea microfrontend framework. It manages the lifecycle of microfrontends. It also includes a browser driver for interfacing with the Polyfea microfrontend controller.
Installation
npm install @polyfea/coreDocumentation
- The polyfea-context element loads microfrontends into the document, replacing itself (by
display: contents) with the microfrontend's content. - The Polyfea class is for advanced use cases, providing control over the loading of microfrontends and elements.
- The Navigation polyfill intercepts navigation events and enables programmatic navigation in browsers that don't yet support the Navigation API. Deprecated for direct usage as most of modern browsers already support Navigation API
- The href function helps with navigation in the single page application.
Usage
The core library enables the Polyfea microfrontend controller to manage microfrontends. Use the <polyfea-context name="my-context"></polyfea-context> element to load resources and elements for a specific context.
Example: Using Boot Script from NPM Package
This example is useful for testing microfrontends with the standalone Polyfea driver during development. Set up your index.html file as follows:
<!DOCTYPE html>
<html dir="ltr" lang="en">
<head>
<base href="/ui/">
<title>Sample polyfea microfrontend</title>
<!-- Alows for repeated registration of the same custom elements.
Possible values are: verbose, silent, warn, error -->
<meta name="polyfea.duplicit-custom-elements" content="verbose">
<!-- Microfrontend configuration is taken from the backend.
You may specify the static configuration.
It will expect StaticConfig json resource to be available
at document.baseURI relative path ./polyfea/static-config
See https://github.com/polyfea/browser-api/blob/main/docs/interfaces/StaticConfig.md
-->
<meta name="polyfea.backend" content="static://">
<!-- Load polyfea driver-->
<script type="module" src="node_modules/@polyfea/core/dist/boot.mjs"></script>
<!-- you may replace above line with a a loading from release assets -->
<!-- <script type="module" src="https://cdn.jsdelivr.net/npm/@polyfea/core@1/dist/boot.mjs"></script> -->
</head>
<body></body>
</html>The code above loads the Polyfea driver and dynamically inserts the <polyfea-context name="shell" take="1"></polyfea-context> element into the document body. This element is populated with microfrontend content from the backend.
Your static configuration should be in the /ui/polyfea/static-config JSON file, served by your development server. For more information, see StaticConfig.
{
"microfrontends": {
"my-fea": {
"module": "./dist/myfea.esm.js",
"resources": [
{
"kind": "stylesheet",
"href": "./build/material-shell-webc.css"
}
]
},
"my-other-fea": {
"dependsOn": [
"my-fea"
],
"module": "./build/material-shell-webc.esm.js",
"resources": [
{
"kind": "stylesheet",
"href": "./build/material-shell-webc.css"
}
]
}
},
"contextAreas": [
{
"name": "shell",
"contextArea": {
"elements": [
{
"tagName": "my-shell-element",
"microfrontend": "my-fea"
}
]
}
},
{
"name": "my-context",
"contextArea": {
"elements": [
{
"tagName": "my-other-element",
"microfrontend": "my-other-fea"
}
]
}
}]
}Use the polyfea-context element in your document to dynamically load elements and microfrontends based on your configuration. This element will be replaced with the loaded microfrontend content. It's ideal for loading elements developed by other teams or subprojects with separate development and release cycles. Avoid using polyfea-context for custom elements in the same repository.
Configuration
You can influence the behavior of the package by setting the <meta> tags in the <head> of your document. Below is a list of supported meta tag names and their contents:
| Attribute Name | Default | Description |
|----------------------------- | ------- | ----------- |
| polyfea.backend | ./polyfea | Specifies the API URL for retrieving information about configured context areas. If preceded with static://, then the static-config API path is called at module load instead of calling context-area queries for each context area. |
| polyfea.cyclic-context-areas | error | Determines behavior when cyclic nested context areas are used to avoid infinite recursion. Possible values are error (displays an error in the document flow), silent (provides no output), and allow (allows areas recursion). |
| polyfea.context-verbosity| error | Value of silent|verbose|error indicating how polyfea-context logs the activity and loading issues. |
| csp-none | | Nonce to use for dynamically inserted scripts and styles. This nonce must match the nonce used in the Content-Security-Policy header. This method is safe, as scripts must be secured before being able to read the DOM. |
| polyfea.duplicit-custom-elements | warn | Behavior when duplicate custom elements are registered at window.customElements. Possible values are silent, verbose, warn, and error. |
customElements.defineLazy
The core driver also adds customElements.defineLazy(tag: string, loadFn: string | async ()=> Promise) method to enable lazy loading of custom element modules in polyfea controller. The DOM mutations are observed (deeply, accross shadowDOM) when there is pending, not yet use registration of the custom element, and as soon as the element with the registered tag is used in the document (including nested shadow documents) its module is loaded. The loaded module (or loadFn) for registering the actual element with customELementDefine. The loadFnmay be string, in this case it is translated into import(loadFn) call. Do not use relative paths in this case, and ensure the module may be loaded either from absolute path/URL or you have importmaps provided to load the module. See also Create the microfrontend resource in polyfea documentation on how to declare importmaps for Polyfea Controller.
In your microfrontend module you can then use code like this:
// assuming /my-element.js calls customElement.define('my-element', MyElement)
if( (customElements as any).defineLazy !== undefined ) {
(customElements as any).defineLazy(
'my-element', await import('./my-element.js')
);
} else {
import('./my-element.js');
}Developing
To begin development on this package, follow these steps:
- Clone the repository to your local machine.
- Run
npm installto install the necessary dependencies. - Execute
npm run storybookto start the Storybook server.
With these steps, you can easily set up your development environment and make changes to the package as needed.
Run npm run build before commiting to ensure up-to-date documentation in the repository. Alternatively you may use taskfile runner with some efficiency improvements for regular development
