npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@kamilmac/puppeteer

v0.3.10

Published

Library for managing micro-frontends.

Readme

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

| Param | Type | | --- | --- | | config | Object |

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.

| Param | Type | Description | | --- | --- | --- | | topic | String | Event to subscribe to. | | listener | function | Callback 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.

| Param | Type | Description | | --- | --- | --- | | topic | String | Event to publish. | | payload | Object | optional 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

| Param | Type | Description | | --- | --- | --- | | action | String | Event to publish. (GET|SET|CHANGE) | | arg | String | Object | function | Depending on action. (KEY_STRING|OBJECT|CALLBACK) |

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.

| Param | Type | Description | | --- | --- | --- | | Optional | Object | initial store. |

getActiveApp() ⇒ String

Returns name of current active app.

Kind: global function