使用 Nx 改进 React 微前端

2025-06-09

使用 Nx 改进 React 微前端

我们在技术读书俱乐部中介绍的第一篇文章之一《微前端》,这是一种在许多独立和自治的团队中扩展前端开发的方法。

虽然文章内容清晰,但示例却略显不足。它利用create-react-app 的额外包来启用 Webpack 构建,并且没有提供同时运行所有微前端应用的机制。示例虽然易于理解,但对于实际场景而言却缺乏信心。

在尝试了不同的工具和方法之后,我认为我已经构建了一个更好的微前端框架,可以提升整体开发者体验。本文将引导您了解这种方法。

您可以在此处找到完整的示例

Monorepos 与 Nx

微前端的主要缺点之一是复杂性。它不再将所有应用程序代码都集中维护,而是分散在多个应用程序中,并由不同的团队管理。这会使共享资源的协作变得困难且繁琐。

将每个微前端放在同一个代码库 (monorepo) 中是管理这种复杂性的简单方法之一。谷歌就曾使用这种技术来管理其数十亿行代码库,并依靠自动化和工具来权衡利弊。

与其使用 create-react-app 来引导微前端,不如使用Nx。Nx 是一个构建框架,提供管理多应用程序 monorepo 的工具,非常适合微前端。

以下是 Nx 帮助管理微前端的几种方法:

  • 脚本编排:使用单个命令同时运行多个微前端的服务器/构建。
  • 方便地共享通用组件和代码库,而无需引入大量的 Webpack 开销。
  • 管理一致的依赖版本。
  • 根据依赖关系图,对跨微前端的受影响更改运行构建和测试。

Nx 当然不是唯一支持 Monorepos 的工具,但我发现它非常适合微前端,因为它内置了 React 支持,并且功能强大。Lerna是一个值得关注的替代方案,它内置的功能较少,但灵活性更高。

详细示例

Nx 只需要进行少量配置更改即可支持微前端,并且您不需要诸如之类的弹出工具的帮助react-app-rewired

  1. 创建一个包含两个 React 应用程序(一个容器、一个微前端)的新 Nx 工作区。
  2. 扩展 Nx 的默认 React Webpack 配置以禁用分块并生成资产清单。
  3. 按照 Thoughtworks 文章中描述的方式实现常规的微前端组件。
  4. 用一个npm start脚本将所有内容结合在一起。

1.创建Nx工作区

首先创建一个新的 Nx 工作区:

npx create-nx-workspace@latest micronx

? What to create in the new workspace...
> empty
Use Nx Cloud?
> No
Enter fullscreen mode Exit fullscreen mode

进入新micronx目录并创建两个 React 应用:一个容器和一个微前端。务必选择styled-components(或其他 CSS-in-JS 解决方案),以便组件 CSS 包含在微前端的 JS 包中。

cd ./micronx
npm install --also=dev @nrwl/react

# Container application
nx g @nrwl/react:app container
> styled-components
> No

# Micro frontend
nx g @nrwl/react:app dashboard
> No
Enter fullscreen mode Exit fullscreen mode

到目前为止,您已经创建了一个包含两个独立 React 应用的 monorepo:容器和仪表板。每个 React 应用都可以通过各自的nx run <app>:serve脚本独立运行,但目前还没有任何机制可以让它们协同工作。

下一步将添加一些配置更改,允许您将仪表板应用程序动态加载为微前端。

2.修改微前端Webpack配置

Nx 将其大部分相关配置存储在workspace.json项目根目录下的文件中。

您需要修改workspace.json以将微前端的 Webpack 配置指向一个新文件webpack.config.js。此新文件包含支持动态加载微前端所需的配置更新。

请注意,您不需要对容器执行此操作,因为容器不是微前端。

// workspace.json
"projects": {
  "dashboard": {
    "targets": {
      "build": {
        // ...
        "webpackConfig": "webpack.config.js"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

现在您需要webpack.config.js在项目的根目录中创建该文件。

修改后的 Webpack 配置扩展了@nrwl/react的默认代码,以避免丢失任何功能。按照 Thoughtworks 的示例,需要进行两项修改才能支持常规微前端:

  1. 禁用分块,以便容器应用程序每个微前端加载一个包。
  2. 添加WebpackManifestPlugin以将生成的 JS 输出映射到一个简单的导入路径(取自react-scripts webpack 配置)。
npm install --also=dev webpack-manifest-plugin
Enter fullscreen mode Exit fullscreen mode
// webpack.config.js
const reactWebpackConfig = require('@nrwl/react/plugins/webpack')
const { WebpackManifestPlugin } = require('webpack-manifest-plugin')

function getWebpackConfig(config) {
  config = reactWebpackConfig(config)

  // Disable chunking
  config.optimization = {
    ...config.optimization,
    runtimeChunk: false,
    splitChunks: {
      chunks(chunk) {
        return false
      },
    },
  }

  // Enable asset-manifest
  config.plugins.push(
    new WebpackManifestPlugin({
      fileName: 'asset-manifest.json',
      publicPath: '/',
      generate: (seed, files, entrypoints) => {
        const manifestFiles = files.reduce((manifest, file) => {
          manifest[file.name] = file.path
          return manifest
        }, seed)
        const entrypointFiles = entrypoints.main.filter(
          fileName => !fileName.endsWith('.map'),
        )

        return {
          files: manifestFiles,
          entrypoints: entrypointFiles,
        }
      },
    }),
  )

  return config
}

module.exports = getWebpackConfig
Enter fullscreen mode Exit fullscreen mode

运行nx run dashboard:serve并访问http://localhost:4200/asset-manifest.json。请注意,仪表板应用程序现在只有一个入口点:main.js

{
  "files": {
    "main.js": "/main.js",
    "main.js.map": "/main.js.map",
    "polyfills.js": "/polyfills.js",
    "polyfills.js.map": "/polyfills.js.map",
    "assets/.gitkeep": "/assets/.gitkeep",
    "favicon.ico": "/favicon.ico",
    "index.html": "/index.html"
  },
  "entrypoints": ["main.js"]
}
Enter fullscreen mode Exit fullscreen mode

3. 添加微前端组件

正确配置 Nx 后,下一步是按照 Thoughtworks 示例并引入所有微前端功能。

以下链接与文章内容一致,但是为了完整性而包含的。

  1. MicroFrontend在容器中创建一个新组件

  2. 使用MicroFrontend组件在容器中加载仪表板微前端

  3. 导出渲染函数,以便仪表板微前端不再将自身渲染到 DOM

  4. 更新仪表板,index.html以便它仍然可以独立提供服务

4. 将所有东西联系在一起

最后一步是将微前端和容器一起提供服务。添加concurrently并修改启动脚本,以便在特定端口上提供仪表板服务。

"start": "concurrently \"nx run container:serve\" \"nx run dashboard:serve --port=3001\""
Enter fullscreen mode Exit fullscreen mode

运行npm start后您就会得到微前端。

使用 Nx

服务微前端

Nx 缺乏同时服务多个应用程序的开箱即用功能,这就是我concurrently在上面的例子中求助的原因。话虽如此,使用 Nx CLI 可以轻松运行单个微前端。

  • 通过独立开发微前端nx run <project>:serve
  • 看看它们如何通过融入整个应用程序npm start

生成器

Nx 附带了一些生成器,可以帮助你搭建应用程序。特别是库生成器,它使得共享 React 组件变得非常容易:

nx g lib common
Enter fullscreen mode Exit fullscreen mode

这将在项目libs/目录中创建一个新的 React 库,其中包含一系列预配置的构建设置。它还包含一个方便的 TypeScript 路径别名,使导入库变得简单:

// apps/dashboard/src/app/app.tsx
import { ComponentA, ComponentB } from '@micronx/common'
Enter fullscreen mode Exit fullscreen mode

Nx 通过跟踪项目的依赖关系图,为这种代码共享方式提供了额外的好处。您可以通过运行来展示各种代码库与每个依赖应用程序之间的关系nx dep-graph

在内部,Nx 使用此依赖关系图来减少引入更改时需要运行的构建/测试次数。如果您对 进行更改apps/dashboard/并运行nx affected:test,Nx 将仅针对 Dashboard 微前端运行测试。随着项目依赖关系图的复杂性不断增加,此功能将变得非常强大。

优化

微前端策略的独特之处在于生产 JS 包中常见供应商依赖项和共享代码库的重复。

Thoughtwork 的文章在“公共内容”部分中谈到了这一点,主张将公共依赖项标记为Webpack 外部依赖项,以防止它们包含在每个应用程序的最终捆绑包中。

module.exports = (config, env) => {
  config.externals = {
    react: 'React',
    'react-dom': 'ReactDOM',
  }
  return config
}
Enter fullscreen mode Exit fullscreen mode

一旦Nx 将其 React 工具升级到 Webpack 5,微前端项目将可以通过模块联合 (Module Federation)获得一种新的代码优化方法。此策略允许将共享代码库 ( libs/)构建到容器应用程序中,从而消除微前端 bundles 中的另一个常见依赖项。

鏂囩珷鏉ユ簮锛�https://dev.to/mgmarlow/better-react-micro-frontends-w-nx-5gnm
PREV
7 Python Excel Libraries: In-Depth Review for Developers
NEXT
使用 Next.js、Tinybird 和 Tremor 构建实时分析仪表盘:综合指南 您将在本文中找到什么? Papermark - 开源 DocSend 替代方案。 设置项目 构建应用程序 结论 帮帮我!