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 🙏

© 2024 – Pkg Stats / Ryan Hefner

tenon-maker

v1.2.6

Published

A implementation of Micro Frontends

Downloads

7

Readme

Tenon

English | 简体中文

Tenon is an implementation of Micro Frontends, which refers to single-spa and qiankun. It aims to provide a way to share business components between projects to support the decoupling and reorganization of cross-team and large-scale projects.

DEMO


Core Design Philosophy Of Tenon

Decoupling

The core goal of the micro front end is to disassemble the boulder application into several loosely coupled micro applications that can be autonomous. Tenon’s design philosophy is consistent with this. Based on this principle, the sandbox and inter-application communication are designed to ensure independent development of micro applications. Ability.

Assembly

At the same time, it is hoped that products can be customized or reorganized based on decoupled blocks. Therefore, the design is not only limited to micro-applications, but also suitable for components with business attributes. Based on this, the implementation form of JS Entry was selected, and the block design was designed. Mounting scheme.

Features

Technology Agnostic

It supports block access of various technology stacks such as React and Vue, but the v1.0 base is built on the basis of React, so the base application only supports React for the time being.

Style Isolation

Based on Shadow Dom to ensure that the styles of micro-applications do not interfere with each other.

JS Sandbox

The multi-instance sandbox based on Proxy ensures that there is no conflict between global variables/events between micro-applications.

How Does Tenon Works

flow

1. Get Configuration

Tenon will obtain block information from the configuration, including: name, block method, dependencies, business attributes, etc. You assemble this configuration through your own operating end and obtain it by providing an interface to achieve page assembly.

Load the sub-application block, import configure the entry file of the sub-application, this file can be quickly generated through tenon-webpack-plugin when self-application is packaged .

blocks: [{
  name: 'Block Name',
  key: 'Todo',
  import: 'http://xxx/entry.json',
  props: {
    id: 'ID',
  },
}],

You can also configure in the project and import the components of this project.

import { Todo } from '@/components';

blocks: [{
  name: 'Block Name',
  key: 'Todo',
  import: Todo,
}],

2. Determine the Block Type

If it is a component of the current project, it will be rendered directly;

If it is a sub-application block, create a Shadow Dom and proceed to step 3.

3. Load JS

Create a multi-instance JS sandbox based on Proxy, change the scope chain through the with method, execute the JS file associated with the block, and return to the block mount method.

4. Load CSS

Write the block style into the Shadow Dom through the Style tag, and the block content will also be rendered inside it.

There is no asynchronous loading of CSS by creating a Link tag, mainly to avoid style confusion during the one-step loading process.

5. Mount

Execute the mount method corresponding to the block Key in the configuration, and mount the block in the Shadow Dom.

6. Render

Render the block.

Contrast with qiankun

Contrast with qiankun, which is also a implementation of Micro Frontends:

Mount

The main purpose of Tenon at the beginning of the design was to assemble multi-block pages, which is more efficient in the way of mounting. You can directly assemble business components through <TenonContainer /> markup.

Communication

Taking into account the communication between blocks and the business independence from the main application, there is no need to initialize in advance when using globalState. The block can update or create new state values ​​at any time through the provided API, and monitor globalState A change in a field in.

Disadvantages

Due to the isolation of JS and CSS between blocks, resources such as third-party libraries may be loaded repeatedly when each block is loaded, which will be used as a subsequent optimization item.

Get Started

Base: React 16+

Block: React 16+ / Vue 2+ / Vue 3

Examples

Examples of React base integration of different technology stack blocks are provided in examples, currently including: React16, React17, Vue, Vue3. For detailed usage, please refer to the examples.

The root directory executes the command, depends on the installation and the sample block is packaged.

1、Installation dependencies

npm run install:all

2、Build blocks

npm run build:local-examples

3、Start the main App

npm run start:main

Installation

Pedestal

yarn add tenon-maker

or

npm install -S tenon-maker

Usage

TenonContainer

Use <TenonContainer /> in the code of the base application to pass in the configuration information (block) of the block to realize the mounting of the block, for example:


import { TenonContainer } from 'tenon';

export const Workbenh: FC = (props: Props) => {

  return (
    <div className="container">
      <TenonContainer
        key={config.key}
        block={config.block}
        style={{
          ...config.style,
        }}
        history={props.history}
        data={{
          ...config.props,
        }}
      />
    </div>
  );
};
API

| Property | Description | Type | Default | Version | | :--- | :--- | :--- | :--- | :--- | | block | Block information | Block | {} | | | style | Container style | CSSProperties | - | | | history | history | History | - | | | data | Component parameters | Record<string, any> | - | |

Inter-application Communication

Communication between applications is inevitable in the process of product assembly, including main-sub-application communication, communication between sub-applications, etc. The inter-application communication of the tenon-and-mortise joint is realized by subscribing to the global status of the base at the same time, for example:

Sub-application subscription status changes or query, modify the global status


export const Demo: FC = (props: Props) => {
  const { onGlobalStateChange, setGlobalState, getGlobalState } = props;

  // Subscribe to changes in the userInfo field in the global status
  onGlobalStateChange(
    (state, prev) => {
      if (state.userInfo) {
        setUserInfo(state.userInfo);
      }
    },
    ['userInfo'],
  );

  // Get the current global state at one time
  useEffect(() => {
    const globalState = getGlobalState();
    const { userInfo } = globalState;
  }, []);

  // Update global status value
  const setState = () => {
    setGlobalState({
      title: 'Demo'
    })
  }

  return ...
}
API

| Property | Description | Type | Default | Version | | :--- | :--- | :--- | :--- | :--- | | getGlobalState | Get global status | () => Record<string, any> | - | | | setGlobalState | Set status | (state: Record<string, any>) => boolean | - | | | onGlobalStateChange | Monitor state changes, changeKeys is the value to be monitored | (callback: (state, prev) => void, changeKeys: string[]) => void | - | |

Block Development

1、Add the package entry file and export the mount method, for example:

// React

import React from 'react';
import ReactDOM from 'react-dom';
import { Todo } from './todo';

const blocks = {
  Todo: {
    mount: (el, props) => {
      ReactDOM.render(<Todo {...props}></Todo>, el);
    },
  },
};

export default blocks;
// Vue

import Vue from 'vue';
import { default as Todo } from './todo';

const blocks = {
  Todo: {
    mount: (el, props) => {
      new Vue({
        render: (h) => h(Todo),
      }).$mount(el);
    },
  },
};

export default blocks;

2、Packaged output umd format, webpack configuration is as follows:

output: {
  ...
  globalObject: 'window', // Global object
  library: 'Library Name', // Customize the package name and expose global variables
  libraryExport: 'default', // Corresponding to the variables exported in the entry file
  libraryTarget: 'umd', // Expose global variables
}

3、Install and configure tenon-webpack-plugin, and output entry.js after packaging

4、Corresponding resources need to support cross-domain access.