0.3.10 • Published 6 years ago

@kamilmac/puppeteer v0.3.10

Weekly downloads
-
License
ISC
Repository
github
Last release
6 years ago

Puppeteer

Library for managing micro-frontends.

How it works ?

Puppeteer is based on simple pub/sub pattern implementation.

By passing config object and running generateAppEvents Puppeteer creates instance of event bus with default actions responsible for dynamic mounting/unmounting of children applications.

One can also use inititateAppRouter when simple routing is needed. In this case Puppeteer observes and appends hash dynamicaly.

On top of that simple Store functionality is provided which might be usefull for keeping global app state like auth info etc.

Puppeteer uses default loader for dynamic loading of external scripts. It is possible to use custom loader by passing it as 'loader' property in config object. Just make sure it is a funtion that takes file path as argument and returns a promise.

Config

  • dev: true|false(default) flag (logs out events)
  • loader: custom loader function (consumes file string and returns a promise)
  • apps: object describing children apps. App object key is a base for route & action name.
    • appName: this object key will resolve to '#/appname' route and APPNAME prefix for events
      • bundleLocation: path to external app bundles. List is loaded sequentially.
      • domHook: document_id where app should be attached
      • mountFuncName: name of the mountung function exisiting on the window object in children app. Returns unmount function.

Installation & Simple Usage

NPM

npm i --save @kamilmac/puppeteer

YARN

yarn add @kamilmac/puppeteer

Main app - index.js

import Puppeteer from '@kamilmac/puppeteer'

const config = {
  // loader: YOUR_OPTIONAL_LOADER
  dev: true,
  apps: {
    app1: {
      bundleLocation: ['app1.js'],
      domHook: 'app1',
      mountFuncName: 'mountApp1'
    },
    app2: {
      bundleLocation: ['app2.js'],
      domHook: 'app2',
      mountFuncName: 'mountApp2'
    },
  },
}

// optional store
let store = {
  greeting: 'hello!',
}

const puppeteer = Puppeteer(config)
  .generateAppEvents() // generates actions ie. 'APP1:ACTION', 'APP2:ACTION'
  .initiateAppRouter() // (optional) attaches router and creates routes for `#/(app1|app2)`
  .attachStore(store) // (optional)

// Runs App1 with payload object
// If bundle is not loaded, Puppeteer mounts it dynamically.
// When done, mountFunc is run with (puppeteer, domHook) arguments.
// Look below for mountFunc example
puppeteer.publish('APP1:ACTION', { data })

setTimeout(() => {
  // Unmounts App1 and runs App2
  puppeteer.publish('APP2:ACTION', { data })
}, 3000)


puppeteer.store('GET', 'greeting').then(value => {
  console.log(value) // prints 'hello!'
})
// Write to store
puppeteer.store('SET', { token: 'token' })
// Read from store
puppeteer.store('GET', 'token').then(value => {
  console.log(value) // prints 'token'
})
// Subscribes to change in store
puppeteer.store('CHANGE', data => {
  console.log('Modified data', data)
})

Children app - app1.js (React example)

// Puppeteer sets puppeteerActive flag to true when initialised.
// Simple check like below allows to run the app in isolation.
if (!window.puppeteerActive) {
  ReactDOM.render(
    <App/>,
    document.getElementById('root')
  )
} else {
  // Mount function for App1. This is the glue between App1 and Puppeteer
  window.mountApp1 = (puppeteer, domHook) => {
    ReactDOM.render(
      <App puppeteer={puppeteer}/>,
      document.getElementById(domHook)
    )
    return () => {
      ReactDOM.unmountComponentAtNode(document.getElementById(domHook))
    }
  }
}

class App extends React.component {
  componentDidMount() {
    this.unsub = this.props.puppeteer.subscribe('APP1:ACTION', payload => {
      // DO YOUR THING
    })
  }

  componentWillUnmount() {
    // unsubscribe when component unmounts
    this.unsub()
  }

  runApp2(payload) {
    // Opens App2 and unmounts App1
    this.props.puppeteer.publish('APP2:ACTION', payload)
  }

  render() {
    return <h1>APP1</h1>
  }
}

API

Functions

Puppeteer(config) ⇒ Object

Consumes Config object and creates Puppeteer instance

{ loader: OPTIONAL_LOADER_FUNCTION dev: DEV_FLAG apps: { // Uppercase object key is used as a base for action type and hash name app1: { bundleLocation: 'app1.js', // document element id where app will be attached domHook: 'app1', // Mounting function accesible of window object // should return unmount function mountFuncName: 'mountApp1' }, app2: { bundleLocation: 'app2.js', domHook: 'app2', mountFuncName: 'mountApp2' }, }, }

Kind: global function
Returns: Object - Puppeteer instance

ParamType
configObject

subscribe(topic, listener) ⇒ function

Subscribes to TOPIC on event buss. Callback is executed with payload data each time 'publish' method is run.

Kind: global function
Returns: function - Unsubscribe function.

ParamTypeDescription
topicStringEvent to subscribe to.
listenerfunctionCallback function run when topic event is published.

publish(topic, payload) ⇒ Promise

Publishes event with optional payload.

Kind: global function
Returns: Promise - Resolves when all subscribed callbacks finished.

ParamTypeDescription
topicStringEvent to publish.
payloadObjectoptional payload object.

store(action, arg) ⇒ Promise | function

Wrapper for store events

Kind: global function
Returns: Promise | function - Returns Promise on GET action / Unsubscribe function on CHANGE

ParamTypeDescription
actionStringEvent to publish. (GETSETCHANGE)
argString | Object | functionDepending on action. (KEY_STRINGOBJECTCALLBACK)

generateAppEvents() ⇒ Object

Creates default actions/events for children apps in config object. It uses subscribe/publish methods. Route names are based on app keys in config object For each app TOPICs are created:

${APP}:ACTION, ${APP}:MOUNT, ${APP}:UNMOUNT

Apps should communicate by using ${APP}:ACTION topic. MOUNT/UNMOUNT actions are resolved automatically.

Kind: global function
Returns: Object - returns this instance

initiateAppRouter() ⇒ Object

Subscribes to ROUTER:CUSTOM_HASH_CHANGE event which is run each time url location changes. It publishes ROUTER:NONE_EXISTING_ROUTE event when apps dont match url. It also uses ${APP}:ACTION events for dynamic app mounting. App route names are based on app keys in config object.

Kind: global function
Returns: Object - returns this instance

attachStore(Optional) ⇒ Object

Creates simple key-value store which also uses publish/subscribe for communication. Instead of calling publish/subscribe, Puppeteer provides store wrapper for dealing with it.

Kind: global function
Returns: Object - returns this instance.

ParamTypeDescription
OptionalObjectinitial store.

getActiveApp() ⇒ String

Returns name of current active app.

Kind: global function

0.3.10

6 years ago

0.3.9

6 years ago

0.3.8

6 years ago

0.3.7

6 years ago

0.3.6

6 years ago

0.3.5

6 years ago

0.3.4

6 years ago

0.3.3

6 years ago

0.3.2

6 years ago

0.3.1

6 years ago

0.3.0

6 years ago

0.2.7

6 years ago

0.2.6

6 years ago

0.2.5

6 years ago

0.2.4

6 years ago

0.2.3

6 years ago

0.2.2

6 years ago

0.2.1

6 years ago

0.2.0

6 years ago

0.1.10

6 years ago

0.1.9

6 years ago

0.1.8

6 years ago

0.1.7

6 years ago

0.1.6

6 years ago

0.1.5

6 years ago

0.1.4

6 years ago

0.1.3

6 years ago

0.1.2

6 years ago

0.1.1

6 years ago

0.1.0

6 years ago