前端不同仓库之间联调方法

背景

A项目要使用B包,B包处在研发阶段。A和B组件之间传递数据还比较复杂,AB还属于不同地域。

简单粗暴方法,就是直接把代码搞在本地,然后去调试。 那除了这种粗暴方法其他有高端的办法吗?

模块联邦

项目采用的是vite+react。(和当前技术栈保持一致)

app-A 项目将会引用app-B 项目(组件

app-B 项目配置

  1. 首先创建两个项目,并安装两个包
pnpm create vite app-B --template react-ts


pnpm create vite app-A --template react-ts
  1. 首先配置 app-graph 项目下的 vite.config.ts 配置,如下
import { defineConfig } from 'vite'

import react from '@vitejs/plugin-react'

import federation from "@originjs/vite-plugin-federation";



// https://vitejs.dev/config/

export default defineConfig({

    build:{
      target:['edge90','chrome90','firefox90','safari15']
    },
    esbuild: {
      target: "es2020"
    },
    optimizeDeps: {
      esbuildOptions : {
          target: "es2020"
    }


  },
  plugins: [react(),
    federation({    // 重点关注这里配置
      name: "app-B",    // App名称
      filename: "remoteEntry.js", // 生成文件名称
      remoteType:  "module",  //生成包类型
      exposes: {
        "./App": "./src/App.tsx", // 输出组件
      },
      shared: ["react"],
    })
  ],
})

完成app-B项目组件 App.tsx

import './App.css'

interface dataProps{
  name: string
}
function App(props: dataProps) {

  return (
    <>
      <div>
      .ʕ◔ϖ◔ʔ.. Yeap... I'm Here! --- from {props.name}
      </div>
    </>
  )
}

export default App
  1. 先执行 pnpm run build 将包打出来,会生成一个 /app-B/dist/assets/remoteEntry.js 的入口文件。
  2. 执行 pnpm run preview
  3. 可以验证下入口文件是否被打包ok http://localhost:3002/assets/remoteEntry.js

Tips: 修改端口的方法是:"preview": "vite preview --port=3002"

app-A项目配置

配置 app-A项目下的 vite.config.ts文件,如下:

import { defineConfig } from 'vite'

import react from '@vitejs/plugin-react'

import federation from "@originjs/vite-plugin-federation";



// https://vitejs.dev/config/

export default defineConfig({

  plugins: [
    react(),
    federation({
      name: "app1",
      remotes: {
        AppGraph: "http://localhost:3002/assets/remoteEntry.js",
      },
      shared: ["react"],
    }),
  ],
})

App.tsx 文件中引入外部组件如下:

import React, { Suspense } from "react";
const RemoteApp = React.lazy(() => import("AppGraph/App"));

function App() {
  return (
    <>
      <div>
        <div
          style={{
            margin: "10px",
            padding: "10px",
            textAlign: "center",
            backgroundColor: "greenyellow",
          }}
        >
          <h1>Risk</h1>
        </div>
        <Suspense fallback={"loading..."}>
         {/* 这里是组件引入方法,以及对应的参数 */}    
          <RemoteApp name="app-A"/> 
        </Suspense>
    </div>
    </>

  )

}



export default App

运行app-A就可以看到app-B作为一个组件引入进来了。

小结

模块联邦需要阶段性的完成工作,然后去build产物。(这样也符合预期)
那有没有办法实时同时开发的?看下面iframe形式。

万能的iframe

app-B 组件

import './App.css'

import {useEffect,useState} from 'react'
interface dataProps{
  name: string
}
function App(props: dataProps) {
  const [message, setMessage] = useState<string>('')
  const messageHandler = (event) => {
    console.log(event);
    setMessage(event.data) // 接收来自外部数据,也就是图漏出的参数
  }
  useEffect(()=>{
    window.addEventListener("message", messageHandler);
    return ()=>{
      window.removeEventListener("message", messageHandler);
    }


  },[])
  return (
    <>
      <div>
      .ʕ◔ϖ◔ʔ.. Yeap... I'm Here! --- from {message} 
      </div>
    </>

  )

}



export default App

app-A 组件

import React, { useEffect, useRef } from "react";


function App() {
  const iframeRef = useRef();
  const postMessage = () => {
    setTimeout(()=>{
       {/* 把组件所需要的参数传递进去*/}
      iframeRef.current?.contentWindow.postMessage('app-A', 'http://127.0.0.1:3002/')
    },0)  
  }

  useEffect(() => {
    const iframe = iframeRef.current;
    if(!iframe){
      return
    }


    iframe.addEventListener('load', postMessage);
    return () => {
      iframe.removeEventListener('load', postMessage);
    };
  }, [iframeRef.current]);

  return (
    <>
      <div>
        <div
          style={{
            margin: "10px",
            padding: "10px",
            textAlign: "center",
            backgroundColor: "greenyellow",
          }}
        >
          <h1>Risk</h1>
        </div>
          {/* 这里是iframe引入方法 */}
          <iframe  
            id="app-B" 
            name="app-B" 
            ref={iframeRef}  
            scrolling="yes" 
            frameBorder="0"
            style={{height:400, width:400, overflow:'visible'}}
            src={"http://127.0.0.1:3002/"}
          />
    </div>
    </>
  )
}

export default App

小结

这种方法iframe用的是开发的热更新地址,所有对面一保存,这边就可以刷新了。两个人相互同步调试。 这种方法在项目开发初期比较适用。

其他方法

  1. pnpm link 本质是本地上的软链,需要拉取到对方代码。 soft link 也是支持热更新的。
  2. 使用grafish微前端框架,没错这个是个微前端。www.garfishjs.org/guide
    可以做进一步的完善,增加新的ruouter,注册子应用,应用上线周期更加灵活化。

这些方法就有点麻烦了。

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYEnzql1' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片