”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 使用 Rspack 和 Modern.js 的微前端

使用 Rspack 和 Modern.js 的微前端

发布于2024-11-04
浏览:546

Photo by Markus Spiske on Unsplash

Introduction

Web developers are beginning to take a strong interest in the idea of Micro-Frontends. Remix and Next.js are two examples of React meta-frameworks that have a lot of useful capabilities, but they don't always give complete support for creating micro-frontends. By providing built-in support for micro-frontends, Modern.js fills this gap and enables developers to design modular, scalable, and flexible apps.

Modern.js Framework

ByteDance created Modern.js, a progressive web framework built on React. Giving developers an outstanding development experience and empowering applications to provide better user experiences simplifies the process of creating contemporary web applications. In addition to having built-in state management, data gathering, and routing capabilities, Modern.js offers all required setups and tools for React applications.

Key features of Modern.js include:

  • Rust Bundler: The primary bundler is Rspack, however, it can be switched to Webpack.
  • Progressive: Facilitates the incremental integration of features via templates and plugins.
  • Integration: Offers isomorphic CSR and SSR development in a unified development and production environment.
  • Out of the Box: Provides debugging tools, ESLint, default TypeScript support, and integrated build tools.
  • Ecology: Module packaging, micro-frontend support, and integrated state management.
  • Routing Modes: Allows for file-convention-based and self-controlled routing.
  • With integrated micro-frontend functionality, Modern.js facilitates scalable, maintainable, and flexible apps while streamlining the development process.

Rspack

Rspack is a high-performance JavaScript bundler written in Rust, designed to be compatible with the webpack ecosystem while providing significantly faster build speeds.

Why Rspack?
Rspack was created to solve performance issues at ByteDance, where large app projects had excessively long build and startup times. Rspack addresses these problems with:

  • Fast Dev Mode Startup: Ensures quick startup to maintain developer productivity.
  • Quick Builds: Reduces CI/CD pipeline build times, improving productivity and application delivery.
  • Flexible Configuration: Maintains webpack's flexibility, easing the transition for legacy projects.
  • Optimized Production Builds: Enhances production optimizations with Rust's multithreading capabilities.

Let's start

This guide will walk us through setting up a Modern.js project, enabling micro-frontend capabilities, and configuring multiple applications to work together seamlessly. We will use pnpm as our package manager and Rspack as the bundler. The shell app will act as the main application that dynamically loads micro-frontends.

Step-by-Step Instructions

1. Initialize the Repository
Start by initializing a new pnpm project in the root directory.

pnpm init

This will create a package.json file to manage dependencies and scripts for your project.

2. Create the Shell Application
Next, create the shell application using Modern.js.

npx @modern-js/create@latest shell-app

( Note: npx @modern-js/create@latest will also commit new changes. So you might have to manually remove .git folder and keep it only on the top level: rm -rf .git )

Select the following options:

  • Project type: Web App
  • Programming language: TS (TypeScript)
  • Package manager: pnpm

  • In the latest versions, Rspack is used as the default bundler.

3. Run the Shell Application
Navigate into the shell application directory and start the development server.

cd shell-app
pnpm start

Running the application ensures everything is set up correctly. You should see the default Modern.js application running in your browser.

4. Enable Micro-frontend Features
Enable micro-frontend features for the shell application.

pnpm run new

Select the following options:

  • Operation: Enable Features
  • Feature: Enable Micro Frontend

Enabling micro-frontend features configures the project to support dynamic loading and micro-frontend integration, allowing us to build modular and scalable applications.

5. Update modern.config.ts
Modify the configuration file to include necessary plugins and runtime settings.

// shell-app/modern.config.ts
import { appTools, defineConfig } from '@modern-js/app-tools';
import { garfishPlugin } from '@modern-js/plugin-garfish';

export default defineConfig({
  runtime: {
    router: true,
    state: true,
    masterApp: {},
  },
  plugins: [appTools(), garfishPlugin()],
});

This configuration enables the router and sets up the shell app as a main application using the garfishPlugin.
(Garfish, developed by the ByteDance team, is a micro-frontend framework similar to single-spa. Modern.js handles the rest under the hood, so we don't need to focus much on it.)

6. Create Custom Entry and Update App.tsx
Remove the default routes folder and create a new App.tsx file in the src directory.

// shell-app/src/App.tsx
import { Suspense } from 'react';
import { defineConfig } from '@modern-js/runtime';
import {
  BrowserRouter as Router,
  Routes,
  Route,
} from '@modern-js/runtime/router';
import styled from '@modern-js/runtime/styled';

const AppContainer = styled.div`
  text-align: center;
  padding: 20px;
  background-color: #f5f5f5;
`;

const Title = styled.h1`
  color: #333;
`;

const Loading = styled.div`
  font-size: 1.2em;
  color: #666;
`;

const App: React.FC = () => {
  return (
    Loading...}>
          Welcome to the Shell Application}
            />
          
  );
};

export default defineConfig(App, {
  masterApp: {
    manifest: {
      getAppList: async () => {
        // here we will add our mfe
        return [];
      },
    },
  },
});

Here, we set up the main component for the shell application, configuring it as the master application that will manage micro-frontends.

7. Create the First Micro-frontend Application
Navigate back to the root directory and create the first micro-frontend.

cd ..
npx @modern-js/create@latest mfe1

Select the following options:

  • Project type: Web App
  • Programming language: TS (TypeScript)
  • Package manager: pnpm

8. Enable Micro-frontend Feature for mfe1
Enable micro-frontend features for the first micro-frontend application.

cd mfe1
pnpm run new

Select the following options:

  • Operation: Enable Features
  • Feature: Enable Micro Frontend

9. Update modern.config.ts for mfe1
Update the configuration file for the micro-frontend.

// mfe1/modern.config.ts
import { appTools, defineConfig } from '@modern-js/app-tools';
import { garfishPlugin } from '@modern-js/plugin-garfish';

export default defineConfig({
  server: {
    port: 8081,
  },
  deploy: {
    microFrontend: true,
  },
  plugins: [appTools(), garfishPlugin()],
});

This configuration sets the port and enables micro-frontend features.

10. Create Custom Entry and Update App.tsx for mfe1
Remove the default routes folder and create a new App.tsx file in the src directory.

// mfe1/src/App.tsx
import React from 'react';
import {
  BrowserRouter as Router,
  Routes,
  Route,
  Link,
} from '@modern-js/runtime/router';
import styled from '@modern-js/runtime/styled';

const Container = styled.div`
  font-size: 1.2em;
  color: #333;
`;

const AppContainer = styled.div`
  text-align: center;
  padding: 20px;
  background-color: #f5f5f5;
`;

const NavBar = styled.nav`
  margin-bottom: 20px;
  a {
    margin: 0 10px;
    color: #007acc;
    text-decoration: none;
  }
`;

const Contact: React.FC = () => {
  return Contact Page;
};

const Home: React.FC = () => {
  return Home Page;
};

const About: React.FC = () => {
  return About Page;
};

const App: React.FC = () => {
  return (
    Home
          About
          Contact
        } />
          } />
          } />
        
  );
};

export default App;

Here, we set up the micro-frontend application with its routes and navigation.

11. Update the Root package.json
Add a start script in the root package.json to run both the shell app and the micro-frontend simultaneously.

{
  "name": "micro-frontends-with-modern.js-and-rspack",
  "version": "1.0.0",
  "description": "",
  "scripts": {
     "start": "pnpm --filter shell-app --filter mfe1 --parallel start"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

12. Update App.tsx in shell-app to Load mfe1
Modify the App.tsx file in the shell application to dynamically load and integrate the micro-frontend.

// shell-app/src/App.tsx
import React, { Suspense } from 'react';
import { useModuleApps } from '@modern-js/plugin-garfish/runtime';
import { defineConfig } from '@modern-js/runtime';
import {
  BrowserRouter as Router,
  Routes,
  Route,
  Link,
} from '@modern-js/runtime/router';
import styled from '@modern-js/runtime/styled';

const AppContainer = styled.div`
  text-align: center;
  padding: 20px;
  background-color: #f5f5f5;
`;

const Title = styled.h1`
  color: #333;
`;

const Loading = styled.div`
  font-size: 1.2em;
  color: #666;
`;

const App: React.FC = () => {
  const { MApp } = useModuleApps();
  return (
    Welcome to the Shell ApplicationLoading...}>
          
MFE1
> } />
); }; export default defineConfig(App, { masterApp: { manifest: { getAppList: async () => { return [ { name: 'mfe1', entry: 'http://localhost:8081/index.js', activeWhen: path => path.includes('mfe1'), }, ]; }, }, }, });

The useModuleApps hook returns sub-app components and gives us full control of routing.

13. Run Both Applications
Navigate back to the root directory and run the start script to launch both applications.

pnpm start

This command will start both the shell-app and mfe1 concurrently, allowing you to access mfe1 inside the shell-app and navigate its subroutes.

Vertical vs Horizontal splits for micro-frontends

We looked at the vertical split of micro-frontends in the previous section. The horizontal divide with module federation will be discussed in the following section. What do these splits indicate, though?

A horizontal split is a pattern in which various application components—manufactured by separate teams—are merged into a single view or path. Every team is in charge of particular features or portions of the page, which are then smoothly integrated. Because teams may operate independently without impacting the program as a whole, this enables parallel development and speedier deployment.

On the other hand, a vertical split separates the application into discrete micro-frontends, each in charge of a separate feature or area of the system as a whole. These micro-frontends operate as distinct, feature-rich programs that can be accessed via several URLs. Because each micro-frontend can be designed, deployed, and updated individually, this approach improves modularity and scalability.

Micro-frontends with Rspack and Modern.js

Adding mfe2 with Module Federation for Horizontal Split

This section will create mfe2 using Module Federation, focusing on a horizontal split. This means mfe2 will handle a specific part of the application's UI, such as a shared component or feature, that can be dynamically loaded and shared across different parts of the shell application.

1. Create the Second Microfrontend Application
Navigate back to the root directory and create the second micro-frontend ( since it's module-federation we can use not only Modern.js ):

cd ..
npx @modern-js/create@latest mfe2

Select the following options:

  • Project type: Web App
  • Programming language: TS (TypeScript)
  • Package manager: pnpm

2. Update modern.config.ts for mfe2
Update the configuration file to include module federation settings.
We added some additional configurations to make module federation work with Modern.js. You can use a regular React app with Rspack instead of Modern.js as well. Additional examples you can find here module-fedration examples.

// mfe2/modern.config.ts
import { appTools, defineConfig } from '@modern-js/app-tools';

export default defineConfig({
  server: {
    port: 8082,
  },
  source: {
    enableAsyncEntry: true,
  },
  plugins: [appTools({ bundler: 'rspack' })],
  tools: {
    rspack: (config, { rspack, appendPlugins }) => {
      // just to remove noise form ts
      if (config.output) {
        config.output.publicPath = 'auto';
        config.output.uniqueName = 'mfe2';
      } else {
        config.output = {
          publicPath: 'auto',
          uniqueName: 'mfe2',
        };
      }

      if (config.optimization) {
        delete config.optimization.splitChunks;
        delete config.optimization.runtimeChunk;
      }

      appendPlugins([
        new rspack.container.ModuleFederationPlugin({
          name: 'mfe2',
          library: { type: 'var', name: 'mfe2' },
          filename: 'static/js/remoteEntry.js',
          exposes: {
            './MFE2Component': './src/MFE2Component.tsx',
          },
          shared: {
            react: { singleton: true },
            'react-dom': { singleton: true },
          },
        }),
      ]);
    },
  },
});

3. Create MFE2Component
Create a new component that will be exposed via module federation.

// src/MFE2Component.tsx
import React from 'react';
import styled from '@modern-js/runtime/styled';

const Container = styled.div`
  font-size: 1.2em;
  color: #007acc;
`;

const MFE2Component: React.FC = () => {
  return This is MFE2 Component!;
};

export default MFE2Component;

4. Update the Shell App modern.config.ts
We need to add module fedration configuration in the Shell App to consume what mfe2 produce.

import { appTools, defineConfig } from '@modern-js/app-tools';
import { garfishPlugin } from '@modern-js/plugin-garfish';

export default defineConfig({
  runtime: {
    router: true,
    state: true,
    masterApp: {},
  },
  source: {
    // automatically generated asynchronous boundary via Dynamic Import, allowing the page code to consume remote modules generated by the module federation.
    enableAsyncEntry: true,
  },
  output: {
    disableTsChecker: true,
  },
  tools: {
    rspack: (config, { rspack, appendPlugins }) => {
      appendPlugins([
        new rspack.container.ModuleFederationPlugin({
          name: 'host',
          remotes: {
            mfe2: 'mfe2@http://localhost:8082/static/js/remoteEntry.js',
          },
          shared: {
            react: { singleton: true },
            'react-dom': { singleton: true },
          },
        }),
      ]);
    },
  },
  plugins: [
    appTools({
      bundler: 'rspack',
    }),
    garfishPlugin(),
  ],
});

5. Update the Shell App to Load mfe2
Update the App.tsx in the shell-app to dynamically load mfe2.

// shell-app/src/App.tsx
...
import MFE2Component from 'mfe2/MFE2Component';
...
 Welcome to the Shell Application

In this updated App.tsx, we've added a link to mfe2 and included it in the manifest configuration.

6. Run Both Applications
Navigate back to the root directory, and update the script.

// package.json
...
"scripts": {
    "start": "pnpm --filter shell-app --filter mfe1  --filter mfe2 --parallel start"
  },
...

Run the start script to launch all applications.

pnpm start

This command will start both the shell-app, mfe1, and mfe2 concurrently, allowing you to access mfe2 inside the shell-app and navigate its subroutes.

Conclusion

We have barely scratched the surface of Modern.js by concentrating on just a couple of its features: integrated micro-frontend capabilities and module federation using Rspack. This is merely a simple illustration to help you get ideas for using Modern.js and creating micro-frontends for your applications.

? Find the code for this article on GitHub.

版本声明 本文转载于:https://dev.to/kyrylobashtenko/micro-frontends-with-rspack-and-modernjs-2l2d?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 使用 VAKX 构建您的无代码 AI 代理
    使用 VAKX 构建您的无代码 AI 代理
    If you’ve been keeping up with the AI space, you already know that AI agents are becoming a game-changer in the world of automation and customer inter...
    编程 发布于2024-11-05
  • 这里是我如何在 jQuery Datatable 中实现基于游标的分页。
    这里是我如何在 jQuery Datatable 中实现基于游标的分页。
    在 Web 应用程序中处理大型数据集时,分页对于性能和用户体验至关重要。标准的基于偏移量的分页(通常与数据表一起使用)对于大型数据集可能效率低下。 基于游标的分页提供了一种性能更高的替代方案,特别是在处理实时更新或大量数据加载时。在本文中,我将引导您了解如何在 jQuery DataTable 中...
    编程 发布于2024-11-05
  • 为什么同步引擎可能是 Web 应用程序的未来
    为什么同步引擎可能是 Web 应用程序的未来
    在不断发展的 Web 应用程序世界中,效率、可扩展性和无缝实时体验至关重要。传统的 Web 架构严重依赖于客户端-服务器模型,这些模型可能难以满足现代对响应能力和同步的需求。这就是同步引擎发挥作用的地方,它为开发人员当今面临的许多挑战提供了一个有前途的解决方案。但同步引擎到底是什么?为什么它们可能是...
    编程 发布于2024-11-05
  • Python 计算机视觉简介(第 1 部分)
    Python 计算机视觉简介(第 1 部分)
    注意:在这篇文章中,我们将仅使用灰度图像以使其易于理解。 什么是图像? 图像可以被认为是值的矩阵,其中每个值代表像素的强度。图像格式主要分为三种类型: Binary:此格式的图像由值为 0(黑色)和 1(白色)的单个二维矩阵表示。这是最简单的图像表示形式。 Grey-Scale:在此...
    编程 发布于2024-11-05
  • 网站 HTML 代码
    网站 HTML 代码
    我一直在尝试建立一个与航空公司相关的网站。我只是想确认我是否可以使用人工智能生成代码来生成整个网站。 HTML 网站是否兼容博客,或者我应该使用 JavaScript?这是我用作演示的代码。 <!DOCTYPE html> <html lang="en">[](url) &l...
    编程 发布于2024-11-05
  • 像程序员一样思考:学习 Java 基础知识
    像程序员一样思考:学习 Java 基础知识
    本文介绍了 Java 编程的基本概念和结构。它首先介绍了变量和数据类型,然后讨论了操作符和表达式,以及控制流流程。其次,它解释了方法和类,然后介绍了输入和输出操作。最后,本文通过一个工资计算器的实际示例展示了这些概念的应用。像程序员一样思考:掌握 Java 基础1. 变量和数据类型Java 使用变量...
    编程 发布于2024-11-05
  • PHP GD 可以比较两个图像的相似性吗?
    PHP GD 可以比较两个图像的相似性吗?
    PHP GD 可以确定两个图像的相似度吗?正在考虑的问题询问是否可以使用以下命令确定两个图像是否相同PHP GD 通过比较它们的差异。这需要获取两个图像之间的差异并确定它是否完全由白色(或任何统一的颜色)组成。根据提供的答案,散列函数(如其他响应所建议的那样)不适用于此语境。比较必须涉及图像内容而不...
    编程 发布于2024-11-05
  • 使用这些键编写高级测试(JavaScript 中的测试需求)
    使用这些键编写高级测试(JavaScript 中的测试需求)
    在本文中,您将学习每个高级开发人员都应该了解的 12 个测试最佳实践。您将看到 Kent Beck 的文章“Test Desiderata”的真实 JavaScript 示例,因为他的文章是用 Ruby 编写的。 这些属性旨在帮助您编写更好的测试。了解它们还可以帮助您在下一次工作面试中取得好成绩。 ...
    编程 发布于2024-11-05
  • 通过将 matlab/octave 算法移植到 C 来实现 AEC 的最佳解决方案
    通过将 matlab/octave 算法移植到 C 来实现 AEC 的最佳解决方案
    完毕!对自己有点印象。 我们的产品需要回声消除功能,确定了三种可能的技术方案, 1)利用MCU检测audio out和audio in的音频信号,编写算法计算两侧声音信号的强度,根据audio out和audio in的强弱在两个通道之间进行可选的切换,实现半双工通话效果,但现在市场上都是全双工通话...
    编程 发布于2024-11-05
  • 逐步构建网页:探索 HTML 中的结构和元素
    逐步构建网页:探索 HTML 中的结构和元素
    ?今天标志着我软件开发之旅的关键一步! ?我编写了第一行代码,深入研究了 HTML 的本质。涵盖的元素和标签。昨天,我探索了构建网站的拳击技术,今天我通过创建页眉、页脚和内容区域等部分将其付诸实践。我还添加了各种 HTML 元素,包括图像元素和链接元素,甚至尝试在单页网站上进行内部链接。看到这些部分...
    编程 发布于2024-11-05
  • 项目创意不一定是独特的:原因如下
    项目创意不一定是独特的:原因如下
    在创新领域,存在一个常见的误解,即项目创意需要具有开创性或完全独特才有价值。然而,事实并非如此。我们今天使用的许多成功产品与其竞争对手共享一组核心功能。让他们与众不同的不一定是想法,而是他们如何执行它、适应用户需求以及在关键领域进行创新。 通讯应用案例:相似但不同 让我们考虑一下 M...
    编程 发布于2024-11-05
  • HackTheBox - Writeup 社论 [已退休]
    HackTheBox - Writeup 社论 [已退休]
    Neste writeup iremos explorar uma máquina easy linux chamada Editorial. Esta máquina explora as seguintes vulnerabilidades e técnicas de exploração: S...
    编程 发布于2024-11-05
  • 强大的 JavaScript 技术可提升您的编码技能
    强大的 JavaScript 技术可提升您的编码技能
    JavaScript is constantly evolving, and mastering the language is key to writing cleaner and more efficient code. ?✨ Whether you’re just getting starte...
    编程 发布于2024-11-05
  • 如何在 ReactJS 中创建可重用的 Button 组件
    如何在 ReactJS 中创建可重用的 Button 组件
    按钮无疑是任何 React 应用程序中重要的 UI 组件,按钮可能用于提交表单或打开新页面等场景。您可以在 React.js 中构建可重用的按钮组件,您可以在应用程序的不同部分中使用它们。因此,维护您的应用程序将变得更加简单,并且您的代码将保持 DRY(不要重复自己)。 您必须首先在组件文件夹中创建...
    编程 发布于2024-11-05
  • 如何在 Apache HttpClient 4 中实现抢占式基本身份验证?
    如何在 Apache HttpClient 4 中实现抢占式基本身份验证?
    使用 Apache HttpClient 4 简化抢占式基本身份验证虽然 Apache HttpClient 4 已经取代了早期版本中的抢占式身份验证方法,但它提供了替代方法以实现相同的功能。对于寻求直接抢占式基本身份验证方法的开发人员,本文探讨了一种简化方法。为了避免向每个请求手动添加 Basic...
    编程 发布于2024-11-05

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3