Microfrontends

In this Microfrontends app we have a Monorepo with multiple packages, each using TypeScript and going through a different Microfrontend tehnique:

apps/main

This is the current Next.js site you're looking at. It uses next-transpile-modules to enable CSS Modules and HMR for packages that ship uncompiled code, like is the case for packages/acme-pages which contains the pages used in this application.

packages/acme-design-system

Example of how you could build a Design System, it's a set of React Components that ship with CSS Modules.

This is the Quote component in the design system.

packages/acme-pages

Works in the same way as packages/acme-design-system but instead of building a design system it's about having shared components that represent pages.

You're currently looking at the Home page, defined in packages/acme-pages/src/home and imported by apps/main/pages/index.tsx.

packages/acme-utils

This package exports utility functions, the package ships transpiled code so it's not needed to use next-transpile-modules in this case.

The button below uses an utility function from this package to change its color when clicked:

apps/docs (Multi Zones)

Next.js application that takes care of handling the pages for /docs/**.

This example shows how Multi Zones can be managed in Next.js to merge multiple Next.js applications in the same domain.

Compared with the approaches above, there's an actual UX impact when doing multi zones because Next.js assets of different builds can't be shared so they have to be downloaded again and transitions are a full page refresh.

Local development can also be affected by HMR because changes to one app outside its domain don't live reload (apps/main lives in port 3000, and apps/docs in 3001).

packages/acme-tailwind-config

Exports the Tailwind CSS configuration that will be used by every app:

mmodule.exports = {
  presets: [
    require('@vercel/examples-ui/tailwind'),
    require('@acme/design-system/tailwind'),
  ],
}

Every app then has a tailwind.config.js with:

const { getContent } = require('@acme/tailwind-config/content')

module.exports = {
  presets: [require('@acme/tailwind-config')],
  content: getContent([
    './pages/**/*.{js,ts,jsx,tsx}',
    './components/**/*.{js,ts,jsx,tsx}',
  ]),
}

getContent will append the packages that use Tailwind CSS so that they're scanned properly. Those packages are @vercel/examples-ui, @acme/design-system and @acme/pages.

packages/acme-storybook

This packages takes the stories in packages/acme-design-system and opens them in Storybook.

packages/eslint-config-acme

Exports the Eslint configuration that will be used by all apps and packages:

module.exports = {
  extends: ['next/core-web-vitals', 'prettier'],
  rules: {
    '@next/next/no-html-link-for-pages': 'off',
  },
}

Every package then has a .eslintrc with:

module.exports = {
  root: true,
  extends: ['acme'],
}