React远程组件

什么是远程组件?

远程组件指的是从远程服务器动态加载的组件,这些组件可以是React、Vue等框架的组件。

为什么需要远程组件

本质上就是为了解决复用问题,那引出新的问题有几种公共项目代码复用方式?

Git仓库

将公共代码单独抽到一个仓库去维护
优点如下

版本控制: 可以精确控制每个子模块的版本,避免不同项目使用不同版本的共同代码。

独立性: 子模块可以独立于主项目进行开发和发布。

清晰结构: 项目结构清晰,易于管理和理解。
缺点如下

管理复杂: 每次都需要手动更新。

npm包

发布到仓库中,需要的项目npm install

缺点:每次更新版本都需要重新publish

Monorepo

优点

统一管理: 所有相关项目都在同一个仓库中,便于统一管理和版本控制。

原子提交: 可以进行跨项目的原子提交,确保所有相关更改都是一致的。

代码共享: 共享代码可以直接引用,无需额外的包管理或子模块配置。
缺点

仓库大小: 单个仓库可能会变得非常大,影响克隆和拉取的速度。

复杂性: 需要更复杂的工具和流程来管理大型仓库,如 Lerna、Nx 等。

权限管理: 需要更细致的权限管理,确保不同团队成员只能访问他们需要的部分。

使用场景

有些公共组件会频繁的根据需求变更,对于多个项目共用的组件库来说,修改组件其影响范围是不可控的。此外,每次修改公共代码后需要更新版本,有时候可能只是个很小的更新没必要更新整个代码库版本。

因此对于某个经常需要迭代的公共代码/组件可以单独打包放到CDN上动态加载。

优点

1、方便的版本控制 。多个项目依赖不同版本,可以打包多分放到CDN上,对应项目加载即可;

2、高效率 。通过动态加载,可以在不重新构建和部署整个应用的情况下,更新和扩展前端功能 ,用户体验也好,可保证用户体验到最新的代码;

3、代码复用,多个项目使用可以有加载;

缺点

1、需要请求对应文件,如果组件太大,加载速度就会慢;

2、如果组件服务崩溃,可能导致组件加载错误,从而使整个业务不可用;

简陋版代码展示

要远程加载的组件源码,写完后建议打包成umd格式。

typescript 复制代码
import { Button, Form } from 'antd/es';
import React from 'react';

const YuButton = (props:{
  p_click?:()=>void
  m_click?:()=>void
})=>{
  const style = { marginRight: 5 };
  return (
    <>
      <Button type="primary" onClick={props.p_click} style={style}>
        主要按钮
      </Button>
      <Button type="primary" onClick={props.m_click} style={style} loading>
        主要按钮
      </Button>
      <Button type="primary" style={style} disabled>
        禁用
      </Button>
    </>
  );
}
const YuText = (props:{
  Items:{label: string, content:string}[]
})=>{
return props?.Items?.length > 0 ? (
  <Form
  name="basic"
  labelCol={{ span: 8 }}
  wrapperCol={{ span: 16 }}

  autoComplete="off"
  >
    {props.Items.map((item)=>{
      return <Form.Item  label={item.label}>
        {item.content}
      </Form.Item>
    })}
  </Form>
) : <div>暂无数据</div>
}



export default {
  YuButton,
  YuText
}
typescript 复制代码
function App() {
  return (
    <div className="App">
      <header className="App-header">
        <RemoteComponent  name='YuButton'>Click Me</RemoteComponent>
        <RemoteComponent  name='YuText' Items={[{label:'label', content:"12312"}]}>Click Me</RemoteComponent>
        <RemoteComponent  name='YuText1' Items={[{label:'label', content:"12312"}]}>Click Me</RemoteComponent>
      </header>
    </div>
  );
}
typescript 复制代码
const RemoteComponent = ({name, children, ...props}) => {
  const Component = useMemo(() => {
    return React.lazy(() => fetchComponent(name))
  }, [name])

  return (
    <Suspense
      fallback={
        <div style={{alignItems: 'center', justifyContent: 'center', flex: 1}}>
          <span style={{fontSize: 50}}>Loading...</span>
        </div>
      }>
      <Component {...props}>{children}</Component>
    </Suspense>
  )
}

const fetchComponent = async (name) => {
  const text = await fetch(
    `/index.umd.js?ts=${Date.now()}` // 将打包的放到CDN上,这里填写CDN的地址加载这个打包后的js文件
  ).then((res) => {
    if (!res.ok) {
      throw new Error('Network response was not ok')
    }
    return res.text()
  })
  const module = getParsedModule(text, name)
  if(Object.keys(module.exports).includes(name)){
    return {default: module.exports[name]} // 这里我们可以得到打包后的组件
  }
  return {default: ()=> <div style={{color:'red'}}>加载失败</div>}
}

const packages = { // 需要什么包传什么包(为了减小打包体积),或者在打包的时候将这些需要的包一起打包进去
  react: React,
  'antd/es': {Button, Form}
}
const getParsedModule = (code) => {
  let module = {
    exports: {},
  }
  const require = (name) => {
    return packages[name]
  }
  Function('require, exports, module', code)(require, {}, module)// 打包UMD格式的话把这些传进去
  return module
}

效果展示

相关推荐
寻找沙漠的人30 分钟前
前端知识补充—CSS
前端·css
GISer_Jing42 分钟前
2025前端面试热门题目——计算机网络篇
前端·计算机网络·面试
m0_7482455243 分钟前
吉利前端、AI面试
前端·面试·职场和发展
理想不理想v1 小时前
webpack最基础的配置
前端·webpack·node.js
pubuzhixing1 小时前
开源白板新方案:Plait 同时支持 Angular 和 React 啦!
前端·开源·github
2401_857600951 小时前
SSM 与 Vue 共筑电脑测评系统:精准洞察电脑世界
前端·javascript·vue.js
2401_857600951 小时前
数字时代的医疗挂号变革:SSM+Vue 系统设计与实现之道
前端·javascript·vue.js
GDAL1 小时前
vue入门教程:组件透传 Attributes
前端·javascript·vue.js
2402_857583491 小时前
基于 SSM 框架的 Vue 电脑测评系统:照亮电脑品质之路
前端·javascript·vue.js
web150850966412 小时前
在uniapp Vue3版本中如何解决webH5网页浏览器跨域的问题
前端·uni-app