0.0.19 • Published 2 years ago

bluebell v0.0.19

Weekly downloads
-
License
MIT
Repository
-
Last release
2 years ago

bluebell

English | 简体中文


A high concurrency micro-frontend framework inspired by and compatible with single-spa.

features

  • Compatible with single-spa
  • Support multiple instances
  • Support router & manual modes
  • Support safe destroying
  • Support safe nested
  • Support async navigation cancelation
  • Fast reaction in concurrency
  • Multiple types of application entry
  • Support built-in ESM loading
  • Support unified resources management
  • Support more chances for retry
  • Support keep alive
  • Support preload(intelligent optional)
  • Support dead loop detect
  • Support sandbox
  • Support shadow DOM
  • Support iframe

usage

router mode

const { RouterContainer } from 'bluebell';

const container = new RouterContainer({
    name: 'top',
    root: '#app',
    fallbackUrl: '/foo',
    fallbackOnlyWhen: loc => loc.pathname === '/',
    cancelActivateApp: (app) => Promise.resolve(false),
});

const [fooApp, barApp, bazApp] = container.registerApps([
    {
        // use entry
        name: 'foo',
        entry: '/foo-config/assets.json',
        activeWhen: '/foo',
    },
    {
        // use assetsMap
        name: 'bar',
        entry: '/foo-config/assets.json',
        assetsMap: { module: 'esm', initial: {}, async: {} },
        activeWhen: (location: Location) => location.pathname.startsWith('/foo'),
    },
    {
        // use lifecycle
        name: 'baz',
        lifecycle: {
            mount: async () => {},
            unmount: async () => {},
            bootstrap: async () => {},
        },
        activeWhen: ['/baz', '/bas'],
    }
]);

container.on('appactivating', ({ appname }) => {});
container.on('appactivated', ({ appname }) => {});
container.on('appactivateerror', ({ appname, error }) => {});
container.on('noappactivated', ({ error }) => {}); // No emitted if fallback.

container.run();

await container.destroy();

💡 Once a RouterContainer starts running, a popstate event will be dispatched after pushState or replaceState called, which changes the default behavior of browser.

manual mode

const { ManualContainer } from 'bluebell';

const container = new ManualContainer({
    name: 'top',
    root: '#app',
});

const [fooApp, barApp, bazApp] = container.registerApps([
    {
        // use entry
        name: 'foo',
        entry: '/foo-config/assets.json',
    },
    {
        // use assetsMap
        name: 'bar',
        entry: '/foo-config/assets.json',
        assetsMap: { module: 'esm', initial: {}, async: {} },
    },
    {
        // use lifecycle
        name: 'baz',
        lifecycle: {
            mount: async () => {},
            unmount: async () => {},
            bootstrap: async () => {},
        },
    }
]);

container.on('appactivating', ({ appname }) => {});
container.on('appactivated', ({ appname }) => {});
container.on('appactivateerror', ({ appname, error }) => {});
container.on('noappactivated', ({ error }) => {});

await container.activateApp('foo');

await container.destroy();

events

fooApp.on('beforestart', () => {});
fooApp.on('afterstart', () => {});
fooApp.on('starterror', ({ error: AppError; prevState: AppState }) => {});
fooApp.on('beforestop', () => {});
fooApp.on('afterstop', () => {});
fooApp.on('stoperror', ({ error: AppError; prevState: AppState }) => {});
fooApp.on('beforeupdate', () => {});
fooApp.on('afterupdate', () => {});
fooApp.on('updateerror', ({ error: AppError; prevState: AppState }) => {});
fooApp.on('beforeunload', () => {});
fooApp.on('afterunload', () => {});

fooApp.lifecycle.on('beforeload'), () => {});
fooApp.lifecycle.on('afterload'), () => {});
fooApp.lifecycle.on('loaderror'), ({ error: AppError }) => {});
fooApp.lifecycle.on('beforebootstrap'), () => {});
fooApp.lifecycle.on('afterbootstrap'), () => {});
fooApp.lifecycle.on('bootstraperror'), ({ error: AppError }) => {});
fooApp.lifecycle.on('beforemount'), () => {});
fooApp.lifecycle.on('aftermount'), () => {});
fooApp.lifecycle.on('mountinterrupted'), ({ error: AppError }) => {});
fooApp.lifecycle.on('mounterror'), ({ error: AppError }) => {});
fooApp.lifecycle.on('beforeunmount'), () => {});
fooApp.lifecycle.on('afterunmount'), () => {});
fooApp.lifecycle.on('unmounterror'), ({ error: AppError }) => {});
fooApp.lifecycle.on('beforeupdate'), () => {});
fooApp.lifecycle.on('afterupdate'), () => {});
fooApp.lifecycle.on('updateinterrupted'), ({ error: AppError }) => {});
fooApp.lifecycle.on('updateerror'), ({ error: AppError}) => {});

strict vs loose

container.registerApps([
    {
        name: 'foo',
        strict: true,
        // HTML entry
        entry: 'http://localhost:9000',
    },
]);

In loose mode, app tries to load CSS and JavaScript by creating HTML tags, otherwise by loading and evalating source code.

App is in loose mode by default.

contributors

0.0.14

2 years ago

0.0.15

2 years ago

0.0.16

2 years ago

0.0.17

2 years ago

0.0.18

2 years ago

0.0.19

2 years ago

0.0.12

2 years ago

0.0.13

2 years ago

0.0.10

2 years ago

0.0.11

2 years ago

0.0.9

2 years ago

0.0.8

2 years ago

0.0.5

2 years ago

0.0.4

2 years ago

0.0.7

2 years ago

0.0.6

2 years ago

0.0.3

2 years ago

0.0.2

2 years ago

0.0.1-alpha.3

2 years ago

0.0.1-alpha.2

2 years ago

0.0.1-alpha.1

2 years ago

0.0.1

2 years ago