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

mariner-fe

v1.0.1

Published

Mariner Framework

Downloads

3

Readme

⚓ Mariner

Mariner is a free and open-source framework offering an intuitive and extendable approach to the modern microfrontend architecture.

It provides a number of ways it can be used while maintaining performance, scale, extendibility by being highly agnostic and only enforcing best practices

  • Backend template language integration
  • Standalone app islands
  • Microfrontend federations

Table of Contents


⛵ How it works

Mariner is a framework built on top of Vite but unlike module federation it doesn't mandate the developer to opt into a framework per say. Everything which works with Vite has a pretty good chance to work with Mariner microfrontend. Mariner is framework agnostic. Microfrontend is whatever you decide microfrontend is.

What it does is force modern technological conventions:

Monorepo

Mariner scans the folder structure and will pick up all the microfrontends inside regardless of the level. Monorepos are not mandatory but they make dependency management easier.

ES modules

Through aliasing it is enabling the microfrontend coupling and communication assuring the deterministic execution of microfrontends. Everything working on your machine should work on the cloud too.

Typescript

Although not mandatory it offers type generation that you can easily include into your framework for type safe microfrontends.

Static builds

Mariner makes microfrontends work like SPA meaning it's full client side rendering.

🚀 Getting Started

To start with Mariner just install the package with any of the package managers locally or globally.

npm install mariner-fe

Open up any vite project or scaffold a new one, Mariner is framework agnostic. As long as it can be built as ES module its supported.

Create two files in the root project directory:

  • mariner.config.js|ts
  • navigator.js|ts

For the config just import the vite.config inside your mariner.config only mandatory field is mariner where you need to give a name to the microfrontend for the registration. If you want to use Vue for example just add vue plugin and you are good to go

/* mariner.config.ts */
import { defineMarinerConfig } from 'mariner-fe'
import vue from '@vitejs/plugin-vue'

export default defineMarinerConfig({
  mariner: 'app1',
  plugins: [vue()],
})

The navigator will build as an ES module so you can auto mount a whole app, expose only a few components or make it read the data from the DOM. The choice is full on the developer

/* navigator.ts */
import { createApp } from 'vue'
import './src/style.css'
import App from './src/App.vue'

const app = createApp(App)

export { app }

After that you can import it into your DOM any way you see fit (keep in mind of ES module)

<script type="module">
  import { app } from 'http://localhost:3000/app1/navigator.js'
  app.mount('#app1')
</script>

or mount it from inside the navigator

<script type="module" src="http://localhost:3000/app1/navigator.js"></script>

💻 Framework Development

Mariner is framework agnostic although it does bundle a Vue and React helpers if you need a XSS safe way to expose your micro apps to the runtime environment. Always be aware when exposing an ES module especially if the DOM is not fully in your control (3rd party integration).

Vue

/* navigator.ts */
import { createVueNavigator } from 'mariner-fe/navigator'
import { createApp } from 'vue'
import './src/style.css'
import App from './src/App.vue'

const app = createApp(App)

export const navigator = createVueNavigator(app)

React

/* navigator.ts */
import { createReactNavigator } from 'mariner-fe/navigator';
import { NavigatorApp } from './src/main-navigator'
import ReactDOM from 'react-dom/client'

export const navigator = createReactNavigator(ReactDOM.createRoot, NavigatorApp())

🧩 Combine microfrontends

Mariner exposes a mechanism of combining microfrontends through module aliasing in build time. The mechanism is quite simple: If the name of the microfrontend is for example app1 then it is going to be prefixed with navigator: resulting in an navigator:app1 import that gets transformed into /app1/navigator.js in dev and build. You can add rootBase if you need to shift the hosting to for example /microfe. You can do pretty much everything you can do in your code editor. Beware of extensive granularity because it will make a difference in your network speed and unintentional bundle size.

<template>
  <button type="button" @click="counterStore.update">
    Shared store count is {{ counterStore.counter }}
  </button>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { useCounter } from 'navigator:shared'

const counterStore = useCounter()
</script>

<style scoped>
button {
  color: #888;
}
</style>

🚢 Fleets

Because the microfrontend workflow can extend to 1k+ developers it can encompass an infinite number of microfrontends. Because this architecture is hard to scale, more dev than build mariner offers an extensive CLI journey for selecting which microfrontends to run.

Also you can predefine a subset of microfrontends to run together via fleet.config.json

{
  "team-A": ["app1", "app2"],
  "team-B": ["auth", "app3"]
}

Mariner will try to read it in the root of where it was called and has it's own selection journey if the file is detected.

🌓 Modes

Mariner can build with modes. It leverages the vite modes enabling the .env files to pull specific configurations.

This can be a very powerful feature combined with aliases where you can expose entire configuration in a single microfrontend to the rest of your federation.

Add fleets to the mix and it makes for a really nice CI/CD workflow where you can reduce the amount of builds by just rebuilding the configuration microfrontend and moving it to the rest of the built fleet.

🏠 Local development

There are couple of workflows that are available when using Mariner locally. You can host everything locally in dev mode or you can combine from other sources like your test/stage environment or prebuilt microfrontends (static hosting). In case you need combination of sources the importmap is a great native DOM solution to this problem.

For example:

<script type="importmap">
  {
    "imports": {
      "/app1/navigator.js": "http://localhost:3000/app1/navigator.js"
      "/app2/navigator.js": "/app2/navigator.js"
    }
  }
</script>
<script type="module" src="/app1/navigator.js"></script>
<script type="module" src="/app2/navigator.js"></script>

This way you can locally host only affected microfrontends and not put such a heavy load to your local machine.

Also you can use this mechanism to override certain microfrontends and redirect to a different build for a specific market you are supporting.

🚧 HMR

Hmr is available for most Vite supported frameworks although it requires a bit of manual setup (refer to playground) and launches one WS connection per micro app. It's WIP.

🔧 Build

Build and type generation are done by node workers meaning they run in parallel. Mariner generally tries to decouple dependencies, runtime, build time as much as possible in dev and build. Although the dev server is inefficient to spawn as different processes the build and type generation benefit from parallelization. There is no golden number of threads so the CLI adds the --threads flag which enables you to fine tune performance for your fleet and CI/CD.

🧰 Type generation

Mariner takes typescript as a first class citizen and exposes a command generate which will ,as long as the navigator is in typescript, generate a folder from the microfrontend selection named .mariner which will contain all the exposed types.

From there you can opt-in into using those types by importing them to your local tsconfig file

❤️ Contribute

We invite you to contribute and help improve Mariner 💚

⚖️ License

MIT