Skip to content

Commit

Permalink
Merge pull request #652 from smapiot/develop
Browse files Browse the repository at this point in the history
Release 1.4.0
  • Loading branch information
FlorianRappl authored Dec 12, 2023
2 parents b3347df + 412ac3b commit 62db2ec
Show file tree
Hide file tree
Showing 152 changed files with 2,710 additions and 3,032 deletions.
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Piral Changelog

## 1.4.0 (tbd)

- Fixed issue when target tarball is part of tarball content in `pilet pack` (#642)
- Fixed issue in `piral-translate` replacing falsy values with empty string (#651)
- Moved `piral-jest-utils` and `piral-ie11polyfills-utils` into a separate repository
- Updated documentation on `piral-ng` (#646)
- Updated dependencies (#641)
- Updated `piral-cli` compatibility with Bun as runtime
- Updated generated code to fully use ES2020
- Updated to latest version of `dets`
- Added support for nested translations in `piral-translate` (#648)
- Added support for Angular 17 in `piral-ng`
- Added possibility to publish emulator as a website (#644)
- Added support for micro frontends based on module federation (#643)
- Added isolation mode option in *piral.json* to opt-in for `piral-component` boundary
- Added option to specify runtime execution path for bundler plugins

## 1.3.3 (November 2, 2023)

- Fixed inlined source maps for CSS files of Angular components
Expand Down
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ variables:
- name: documentBranch
value: 'documentation'
- name: nodeVersion
value: '16.20.0'
value: '20.10.0'

stages:
- stage: Build
Expand Down
135 changes: 135 additions & 0 deletions docs/concepts/I09-web-components.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
---
title: Web Components
description: Information about the used and available web components.
section: Internals
---

# Web Components

Piral comes with a set of web components that are partially used internally and partially can used from you directly in your app shell or micro frontends.

The available web components are:

- `piral-extension`: This one is used to declare a Piral extension slot. You can use it.
- `piral-component`: This one is used to mark the area for a component to render into. You should not use it as it's inserted and removed by Piral.
- `piral-portal`: The one is used to create a rendering spot for non-React components in the React component tree. You should not use it as it's inserted and removed by Piral.
- `piral-slot`: This one is used to have a clean unobtrusive container element for frameworks that cannot reuse exist elements. You can use it.
- `piral-content`: This one is used to show the content of a React component in a non-React component. You can use it.

Let's look into each one with an example.

## Extension Slots

The `piral-extension` web component gives you the possibility of declaring an extension slot in th DOM tree, i.e., essentially from any framework. Almost all the possibilities of an extension slot are available.

The most straight forward usage is just with a name:

```html
<piral-extension name="name-of-extension-slot"></piral-extension>
```

If you want to transport in parameters you need to use either the `params` property or the `params` attribute. The latter uses a JSON value, while the former allows you to pass in an object with any kind of values (incl. function references) in it.

Using the params attribute:

```html
<piral-extension name='name-of-extension-slot' params='{"foo":"bar"}'></piral-extension>
```

Using the params property:

```html
<piral-extension name="name-of-extension-slot" id="my-extension"></piral-extension>
```

combined with the JavaScript code to set the property

```js
document.querySelector('#my-extension').params = {
foo: 'bar',
log: (str) => console.log(str),
};
```

The component emits some events:

- `render-html`, emitted from the `piral-extension` instance in bubbling mode to indicate that the extension slot should be handled (i.e., populated with components as registered) by the orchestrator
- `extension-props-changed`, emitted from the `piral-extension` instance when a params change should lead to an immediate re-rendering

## Component Boundaries

The `piral-component` web component provides an indicator that an area is reserved for the component coming from a micro frontend. The name of component can be declared using the `name` attribute, while the micro frontend is specified in the `origin` attribute.

```html
<piral-component name="name-of-component" origin="my-awesome-pilet">
<!-- here comes the rendered content -->
</piral-component>
```

This component is only used within the framework. It will be inserted as a natural component boundary and has no impact on styling.

The component emits some events:

- `add-component`, emitted from `window` when a new `piral-component` instance has been connected to the DOM (usually after mounting / rendering)
- `remove-component`, emitted from `window` when an existing instance has been removed (usually after unmounting)

For Piral to use this as a boundary you need to be in the (opt-in) "modern" isolation mode. To active this mode you need to change the *piral.json*:

```json
{
"isolation": "modern"
}
```

::: tip: Visualize component origins
For the visualization feature of the Piral Inspector (a freely available browser extension) you'll need to have the `isolation` mode set to `modern`. Otherwise, this feature will not work as expected.
:::

The element instances and their attributes have to be preserved as they are managed by Piral itself.

## Rendering Portals

The `piral-portal` web component repersents a non-visual anchor point for the React rendering tree. As access to the DOM tree requires a `ref` on a real element the `piral-portal` was introduced.

It has a single attribute `pid` that contains the internally used portal ID. Using the portal ID the main React rendering tree can trigger rendering of anything with a proper projection. This way, a single React render tree can exist even though foreign elements may occupy full or partial sub-trees of it.

The element instances and their attributes have to be preserved as they are managed by Piral itself.

## Container Elements

The `piral-slot` web component can be used as an unobtrusive container. Like the other elements it uses a CSS display mode that makes it non-visual, i.e., it is just a plain container element without intrinsic styling properties.

You can use this one for a framework that requires to change the attributes of the hosting element. Usually, for non-React components the hosting element is already a `piral-portal`, however, this one needs to be kept (with its provided attributes). If the rendering framework wants to change this hosting element then having a nested hosting such as:

```html
<piral-portal pid="abc">
<piral-slot>
<!-- rendering of foreign framework happens in here using outerHtml -->
</piral-slot>
</piral-portal>
```

In most cases you'll not want to use this element directly even though it could come in handy.

## Content Views

The `piral-content` web component is a non-visual container that acts as a portal for React content to be rendered. Whenever you receive React content in your non-React components (e.g., via the `children` prop) you can use a `piral-content` element to display it.

For using the element correctly you also need to use the global `assignContent` function. First, you'd assign the content (e.g., after you received it) using this function:

```js
window.assignContent("123", myReactContent)
```

Then you can create the `piral-content` instance using the same content ID (`cid`):


```html
<piral-content cid="123"></piral-content>
```

At this time the Piral orchestrator will take the assigned content and render it into the element using React.

The component emits some events:

- `render-content`, emitted from `window` when a `piral-content` instance was connected and rendering should begin
65 changes: 60 additions & 5 deletions docs/concepts/T01-emulator.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,64 @@
---
title: Emulator
description: Details on how an emulator package is created and used.
description: Details on how an emulator is created and used.
section: Tooling
---

# Emulator Package
# Emulator

To make developing pilets as easy and intuitive as possible, the app shell can be packaged to serve as an emulator.
To make developing pilets as easy and intuitive as possible, the app shell can be distributed as a so-called emulator. For this distribution there are right now 3 different models:

1. Package - a tarball (npm package) is used (use case: a (private) npm registry exists)
2. Source - the app shell's source code is directly referenced (use case: monorepo)
3. Website - a special build of the app shell is uploaded to some static storage (use case: the emulator can be public)

The emulator is essentially the app shell with special debug helpers (e.g., allowing usage with the Piral Inspector), source maps, and non-production sources (e.g., shipping with the full React error explanations and development warnings).

## Building

The emulator is built via the `piral-cli` using the command `piral build --type emulator`. The result is a `tgz` located in the `dist/emulator` folder that could be published to an npm registry.
### Package Emulator

The emulator is built via the `piral-cli` using the command `piral build --type emulator-package`. The result is a `tgz` located in the `dist/emulator` folder that could be published to an npm registry.

In case you want to inspect the files contained in the emulator package (without opening / unpacking the tarball) you can use the `--type emulator-sources` flag for the `piral-cli`: `piral build --type emulator-sources`.

This type of emulator is the default. In case you want to be explicit about this being the default you can change the *piral.json* to be:

```json
{
"$schema": "https://docs.piral.io/schemas/piral-v0.json",
"emulator": "package"
}
```

Alternatively, if you want to have the emulator package, but not already packaged but rather in form of its sources, you can change that default to be:

```json
{
"$schema": "https://docs.piral.io/schemas/piral-v0.json",
"emulator": "sources"
}
```

### Source Emulator

In this variation no build step is necessary. This is the case in a monorepo where your app shell is just one of the "packages" / directories along your pilets. Alternatively, you could also just package or distribute the app shell's source code with no build step. In this case your app shell is already an emulator, however, the build of this emulator is still necessary and might fail if certain dependencies are not available in the pilet's directory.

### Website Emulator

In this variation the emulator is built via the `piral-cli` using the command `piral build --type emulator-website`. The result quite similar to the release build, with the artifacts placed in `dist/emulator` instead of `dist/release`. The files located in `dist/emulator` can then be uploaded to some static storage that can be referenced by an URL.

In case you want to always produce this kind of emulator when you call `piral build` you can adjust the *piral.json* to be:

```json
{
"$schema": "https://docs.piral.io/schemas/piral-v0.json",
"emulator": "website"
}

## Package Definition

The generated tarball contains a pre-bundled version of the sources, together with a modified version of the app shell repository's original *package.json*.
In case of a emulator package the generated tarball contains a pre-bundled version of the sources, together with a modified version of the app shell repository's original *package.json*.

The following properties are taken over:

Expand Down Expand Up @@ -59,6 +101,19 @@ If you build your emulator package on your own incl. already pre-bundled sources
This makes sure to avoid running a `piral debug` on the sources.
:::

## Emulator Manifest

The emulator website comes with a special file called `emulator.json` that contains all information to be used by pilets. This file contains the following information:

- `name` has the name of the app shell
- `description` contains the description given for the app shell
- `version` specifies the currently used version of the app shell
- `timestamp` defines the point in time when the emulator was created
- `scaffolding` information with the defined pilets info and used version of the `piral-cli`
- `files` referencing essential files for typings, the app (HTML and JS), as well as all assets
- `importmap` having the exposed importmap (centrally shared dependencies)
- `dependencies` goes into details on the used optional and included dependencies

## Declaration

Usually, only the `PiletApi` and its used types are exported from the app shell.
Expand Down
9 changes: 9 additions & 0 deletions docs/specs/cli-specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,15 @@ System.register([],function(e,c){var dep;return{setters:[function(_dep){dep = _d

The `$pr_name` has to be replaced with the globally used name for other (lazy loaded) chunks of the pilet. The `$shared_dependencies` represent the used shared dependencies. This is a JSON object mapping the identifiers used for the shared dependencies to their bundles.

**`mf`**

The bundled code follows the specification and implementation of Module Federation. While originated at Webpack ("Webpack Module Federation") it is now also ported over to other bundlers. In supported bundlers the `mf` format can be used to produce compatible pilets.

Pilets that are compatible must have:

- Exposed entry point `./pilet` leading to the module with a `setup` function
- Accepting a share scope with name `default` (this is also the default, so no changes required here)

## Limitations

The specification does not cover things like validation, declaration generation, scaffolding, or upgrading.
Expand Down
8 changes: 7 additions & 1 deletion docs/specs/pilet-specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,13 @@ The script for the partial resource has to be loaded from the same base URL as t

### `v2` Format

This code in this section works exclusively for `v2` pilets. `v2` pilets are using the [SystemJS format](https://github.com/systemjs/systemjs/blob/main/docs/system-register.md). For conformance to this format the SystemJS specification should be considered.
The code in this section works exclusively for `v2` pilets. `v2` pilets are using the [SystemJS format](https://github.com/systemjs/systemjs/blob/main/docs/system-register.md). For conformance to this format the SystemJS specification should be considered.

### `mf` Format

The code in this section works exclusively for `mf` pilets. `mf` pilets are using [Module Federation](https://module-federation.io/) for exposing their API and taking part in (distributed) sharing of dependencies. For conformance to this format the Module Federation specification should be considered.

The `mf` format does not require a spec version marker. By detecting a script that uses module federation the `mf` format is assumed.

## Package Keys

Expand Down
20 changes: 18 additions & 2 deletions docs/static/schemas/pilet-v0.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,24 @@
"properties": {
"schemaVersion": {
"type": "string",
"enum": ["none", "v0", "v1", "v2", "v3"],
"enum": [
"none",
"v0",
"v1",
"v2",
"v3",
"mf"
],
"description": "The default output schema to be used when building the pilet."
},
"importmapVersions": {
"type": "string",
"enum": ["all", "match-major", "any-patch", "exact"],
"enum": [
"all",
"match-major",
"any-patch",
"exact"
],
"description": "The default behavior for implicitly defined versions of shared dependencies."
},
"piralInstances": {
Expand All @@ -36,6 +48,10 @@
"path": {
"type": "string",
"description": "Defines the path to the emulator package of this app shell. If not given, the emulator package is resolved by the name of the given app shell key."
},
"url": {
"type": "string",
"description": "Defines the URL to the emulator website of this app shell. If provided, the emulator package is downloaded and updated automatically from the source."
}
},
"required": []
Expand Down
23 changes: 20 additions & 3 deletions docs/static/schemas/piral-v0.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,34 @@
"platform": {
"type": "string",
"description": "The platform where the Piral instance is to be run.",
"enum": ["web", "node"]
"enum": [
"web",
"node"
]
},
"options": {
"type": "object",
"description": "Further platform-specific options to use."
}
}
},
"emulatorStartup": {
"emulator": {
"type": "string",
"description": "Defines the script file to use when the emulator should start. By default, a web server serving the contents from 'app' is started."
"enum": [
"package",
"website",
"sources",
"none"
],
"description": "Defines what the type of the emulator artifact used by the build command is. 'none' skips implicit building of the emulator."
},
"isolation": {
"type": "string",
"enum": [
"classic",
"modern"
],
"description": "Defines what isolation / component wrapper is used for components of micro frontends. By default, the 'classic' isolation mode is used."
},
"pilets": {
"type": "object",
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
},
"devDependencies": {
"@jsenv/file-size-impact": "12.1.1",
"@testing-library/react": "^14.1.0",
"caniuse-lite": "^1.0.30001341",
"esbuild": "^0.13.6",
"lerna": "^6.0.1",
Expand All @@ -61,7 +62,7 @@
"tslint-plugin-prettier": "^2.0.1",
"typedoc": "0.25.2",
"typescript": "5.2.2",
"vitest": "^0.34.6"
"vitest": "^1.0.4"
},
"resolutions": {
"ansi-html": "0.0.9",
Expand All @@ -85,6 +86,7 @@
"set-value": "4.0.1",
"shell-quote": "1.7.3",
"ssri": "8.0.1",
"tar": "^6.2.0",
"trim-newlines": "3.0.1",
"tslib": "2.5.2",
"ws": "7.4.6"
Expand Down
2 changes: 0 additions & 2 deletions src/converters/piral-cycle/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
"extends": "../../../tsconfig.json",
"compilerOptions": {
"skipLibCheck": true,
"target": "ES6",
"lib": ["dom", "es2015", "es2018"],
"jsx": "react",
"importHelpers": true
},
Expand Down
Loading

0 comments on commit 62db2ec

Please sign in to comment.