这个自己确实研究了蛮久了,就是如何实现远程组件的加载。
因为对于业务组件一般来说,第一选择会发npm包,但是对于产品组件的话,第一就是组件过大,与独立的项目无异,迭代很频繁,有时需要更改线上的问题,且平台有时需要支持加载客户的第三方组件等问题,可以选择一个组件远程加载的方案去实现。
因为自己现在所做的产品,为了保证项目的扩展性,是需要支持用户可以上传自己的组件,且对于新的twin相关的产品线,也是需要支持组件可以进行远程加载的,就是说平台应用和产品组件是分离的。
对于超复杂的组件,是单独的提成了一个单独的项目去进行处理的,例如easyv中的数字孪生渲染的屏。然后在平台中去做一个按需引入。
给出的技术方案:
第一个就是组件的打包
组件为独立的一个项目,在打包时需要打包为一个单文件,组件打包代码为umd格式(可以去了解下umd,amd,以及cmd,esmodule规范)。将打包组件的js上传到cdn中(这里的话其实可以推荐使用阿里云的oss服务)。
第二个的话就是组件的加载。
加载的话这里其实有多种方案去选择,自己的熟悉的有两种,第一个是放在全局对象window上,第二个的话是,基于amd规范打包,在组件的使用时,使用requirejs进行组件的注册(可以去了解下关于amd,cmd规范,以及模块的加载方案)。
还有就是基于esmodule去处理的,但是这种方案的话,自己也并没有去多了解
实现,
这里是基于vite去搭建的项目,emmmm,减少工作量,就将测试的组件及项目合为一个项目,
首先就是子组件的打包,
我的vite配置,其实主要的是在打包时,组件的输出格式为umd,且指定打包的入口,也是我测试的子组件,保证我的打包与运行是独立的。
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import {createHtmlPlugin} from "vite-plugin-html";
import { viteSingleFile } from 'vite-plugin-singlefile'
import { resolve } from "path"
export default defineConfig (({mode}) => ({
plugins: [react(),
viteSingleFile(),
createHtmlPlugin({
inject: {
data: { MODE: mode, HASH: Date.now() },
},
}),],
server: {
host: '127.0.0.1',
port: 5371,
proxy: {
'/api': {
target: '',
changeOrigin: true,
},
},
open: true,
},
define:{
'process.env':{}
},
build: {
outDir: 'lib',
lib: {
entry: resolve('./src/testComponent.ts'),
name: 'ESDrager', // 使用script标签引入时全局名称
fileName: format => `index.${format}.js`,
formats: ['umd'],
},
}
}))
第一种方案,需要将组件挂在到window上面的,所以需要一个入口,也就是testComponent,入口处做一个组件的挂载
子组件
,打包后将文件放入到bucket中去
然后就是在项目中进行一个引入,en,这里其实只能用一个类组件去承载我们远程加载的组件,使用函数组件的话,这里会直接崩掉的,具体的原因自己还没有时间去研究。
import React, { PureComponent } from 'react';
export default class InnerEasyVComponent extends PureComponent {
constructor(props) {
super(props)
this.state = {
component: null,
};
}
componentDidMount() {
const url = 'https://linzai.oss-cn-beijing.aliyuncs.com/index.umd.js';
const script = document.createElement('script');
script.src = url;
script.onload = (v) => {
console.log(window.components.testComponent,'我的组件')
setCom(window.components.testComponent)
}
document.head.appendChild(script);
}
render() {
const Com = this.state.component
return (
<div>
图书管理
{
Com && <Com/>
}
</div>
);
}
}
第二种方案的话是基于amd规范去实现的,其实打包组件的规范不用变,还是基于umd(实际的话是基于amd规范去实现的,UMD
是 AMD
和 CommonJS
的一个糅合。)然后打包的话 是不需要入口的,也就是不需要testComponent.ts
然后最大的区别在于对组件的一个加载与组件,这里的话 使用requirejs获取组件并注册,
首先需要去引入requirjs,刚开始的话直接尝试去下载的他的pnpm包,不过会有error,不能够使用,
后面的话还是通过script去做的引用,
<script src="https://requirejs.org/docs/release/2.3.6/minified/require.js"></script>
lll
😱