logo
  • 指南
  • 配置
  • 插件
  • API
  • 示例
  • 社区
  • Modern.js 2.x 文档
  • 简体中文
    • 简体中文
    • English
    • 开始
      介绍
      快速上手
      版本升级
      名词解释
      技术栈
      核心概念
      页面入口
      构建工具
      Web 服务器
      基础功能
      路由
      路由基础
      配置式路由
      数据管理
      数据获取
      数据写入
      数据缓存
      渲染
      服务端渲染(SSR)
      服务端流式渲染(Streaming SSR)
      渲染缓存
      静态站点生成(SSG)
      渲染预处理 (Render Preprocessing)
      样式开发
      引入 CSS
      使用 CSS Modules
      使用 CSS-in-JS
      使用 Tailwind CSS
      HTML 模板
      引用静态资源
      引用 JSON 文件
      引用 SVG 资源
      引用 Wasm 资源
      调试
      数据模拟(Mock)
      网络代理
      使用 Rsdoctor
      使用 Storybook
      测试
      Playwright
      Vitest
      Jest
      Cypress
      路径别名
      环境变量
      构建产物目录
      部署应用
      进阶功能
      使用 Rspack
      使用 BFF
      基础用法
      运行时框架
      扩展 BFF Server
      扩展一体化调用 SDK
      文件上传
      跨项目调用
      优化页面性能
      代码分割
      静态资源内联
      产物体积优化
      React Compiler
      提升构建性能
      浏览器兼容性
      配置底层工具
      源码构建模式
      服务端监控
      Monitors
      日志事件
      指标事件
      国际化
      基础概念
      快速开始
      配置说明
      语言检测
      资源加载
      路由集成
      API 参考
      高级用法
      最佳实践
      自定义 Web Server
      专题详解
      模块联邦
      简介
      开始使用
      应用级别模块
      服务端渲染
      部署
      集成国际化能力
      常见问题
      依赖安装问题
      命令行问题
      构建相关问题
      热更新问题
      已下线功能
      📝 编辑此页面
      上一页文件上传下一页代码分割

      #跨项目调用

      基于 BFF 架构,Modern.js 提供了跨项目调用的能力,即在一个项目中创建的 BFF 函数可以被其他项目进行一体化调用,实现项目间的函数共享和功能复用。 跨项目调用分为 BFF 的生产端和消费端。生产端负责创建和提供 BFF 服务、生成一体化调用 SDK,而消费端通过调用 SDK 发起接口请求。

      #BFF 生产端

      升级 Modern.js 相关依赖到 x.64.4 及以上版本,通过配置即可启用跨项目调用能力。你可以将已启用 BFF 能力的项目视为 BFF 生产端,也可以单独创建独立的 BFF 应用。 当执行 dev 或 build,都会自动生成供消费端使用的产物,包括:

      • dist/client 目录下的接口函数
      • dist/runtime 目录下的运行时配置函数
      • package.json 中 exports 定义接口函数出口
      • package.json 中 files 指定发布到 npm 包的文件列表

      #已启用 BFF 的项目

      1. 开启跨项目调用

      确保当前项目已启动 BFF 能力,并在 api/lambda 目录下定义接口文件。完成如下配置:

      modern.config.ts
      export default defineConfig({
        bff: {
          crossProject: true,
        }
      });
      1. 生成 SDK 类型文件

      为一体化调用 SDK 提供类型提示,需要在 TypeScript 的 tsconfig.json 文件中打开 declaration 选项,配置如下:

      tsconfig.json
      "compilerOptions": {
          "declaration": true,
      }

      #创建 BFF 应用

      1. 执行 @modern-js/create 命令:
      npx @modern-js/create@latest myapi
      1. 可交互的问答界面中,按照默认的选择进行初始化:
      ? 请选择开发语言 TS
      ? 请选择包管理工具 pnpm
      1. 执行 new 命令,启用 BFF:
      ? 请选择你想要的操作 启用可选功能
      ? 请选择功能名称 启用「BFF」功能
      ? 请选择 BFF 类型 框架模式
      1. 执行【已启用 BFF 的项目】步骤,即可打开跨项目调用开关。 需要注意的是,当项目仅作为 BFF 生产端,其运行时不依赖 /src 源码目录。因此,移除 /src 目录可在一定程度上优化工程的编译效率。

      #BFF 消费端

      Info

      你可以在任意框架的项目中通过调用 SDK 向 BFF 生产端发起接口请求。

      #同一 Monorepo 内调用

      如果生产端和消费端在同一 Monorepo 中,可以直接引入 SDK。接口函数位于 ${package_name}/api 目录下,示例如下:

      src/routes/page.tsx
      import { useState, useEffect } from 'react';
      import { get as hello } from '${package_name}/api/hello';
      
      export default () => {
        const [text, setText] = useState('');
      
        useEffect(() => {
          hello().then(setText);
        }, []);
        return <div>{text}</div>;
      };

      #独立项目间调用

      当生产端和消费端不在同一个 Monorepo 中时,生产端需要通过 npm publish 将 BFF 生产端项目发布为包,调用方式与 Monorepo 内相同。

      #配置域名及扩展功能

      实际应用场景中,跨项目调用需要指定 BFF 服务的域名。可以通过以下配置函数实现:

      src/routes/page.tsx
      import { configure } from '${package_name}/runtime';
      
      configure({
        setDomain() {
          return 'https://your-bff-api.com';
        },
      });

      ${package_name}/runtime 目录下的 configure 函数,支持通过 setDomain 配置域名,configure 同样支持添加拦截器和自定义请求 SDK 能力。 当需要在同一页面中同时对当前项目和跨项目的一体化调用 SDK 进行扩展,建议采用以下配置:

      src/routes/page.tsx
      import { configure } from '${package_name}/runtime';
      import { configure as innerConfigure } from '@modern-js/plugin-bff/client';
      import axios from 'axios';
      
      configure({
          setDomain() {
              return 'https://your-bff-api.com';
          },
      });
      
      innerConfigure({
        async request(...config: Parameters<typeof fetch>) {
          const [url, params] = config;
          const res = await axios({
            url: url as string,
            method: params?.method as Method,
            data: params?.body,
            headers: {
              'x-header': 'innerConfigure',
            },
          });
          return res.data;
        },
      });