alibaba / lowcode-engine

An enterprise-class low-code technology stack with scale-out design / 一套面向扩展设计的企业级低代码技术体系
https://lowcode-engine.cn
MIT License
14.5k stars 2.52k forks source link

动态加载自定义物料时,自动加载其附带的自定义setter #1898

Open sy296565890 opened 1 year ago

sy296565890 commented 1 year ago

大佬好,请教下怎么在独立的一个物料工程里(类似 lowcode-materials) ,同时 【导出】自定义的setter 并使其伴随物料一起加载 不需要额外的setter加载代码,或者说大佬您推荐如何动态加载物料关联的自定义setter

尝试了一些方法

  1. 在物料库的index.tsx 文件中 使用如下代码
    
    import * as React from "react";
    import { ProFormDigit } from '@ant-design/pro-components';  // ProFormDigit 样式异常了

export default class CustomSetter extends React.PureComponent { static displayName = 'CustomSetter ';

render() { return (

);

} }

const registerSetter = window.top.AliLowCodeEngine.setters.registerSetter registerSetter('CustomSetter', CustomSetter)

2. 注册官方setter后面加入
  //  注册官方的setterMap【低代码主应用】
  setters.registerSetter(setterMap);
  setters.registerSetter('CustomSetter', CustomSetter);
  // 虽然可以使用  但没办法做到不更新低代码主应用的时候  动态加入新的物料和setter

3. 期望setter可以像动态加载 assets一样 或者有近似的办法
sy296565890 commented 1 year ago

在自定义物料库尝试了 const registerSetter = window.top.AliLowCodeEngine.setters.registerSetter registerSetter('CustomSetter', CustomSetter) 虽然组件能加载出来但是css丢失了 使用了antd5【 cssinjs】 却依然没有样式

sy296565890 commented 1 year ago

已经尝试了下面几种办法 操作方式1 【css缺失,且弹框控件被局限在模拟器里面】 const registerSetter = window.top.AliLowCodeEngine.setters.registerSetter registerSetter('CustomSetter', CustomSetter) 操作方式2 【正常可用 但低代码主应用不支持动态加载自定义setter】 setters.registerSetter(setterMap); // 挂在官方setters setters.registerSetter('CustomSetter', CustomSetter); // 正常使用 操作方式3 【无法使用antd组件库】 自定义物料库 src同级文件夹lowcode下加入_setter

sy296565890 commented 1 year ago

力皓大佬建议: 我建议就是在 plugin 去注册,在外层注册,把 setter 跟物料写在一起不太优雅,耦合了

  1. setter 是在外层使用,组件是在渲染器使用,没必要一起加载,然后强行再让部分css内部iframe生效,部分外部生效(我估计你也不好分开,混一起了);
  2. simulator iframe的一大作用就是让渲染环境更纯碎,不被设计器相关的css影响,setter css强行混入干扰,算负向优化了;
sy296565890 commented 1 year ago
1681802705172_A072975E-BF75-4a42-8075-97C4C77DF84E
sy296565890 commented 1 year ago

这个时候的业务setter本身就是个强耦合组件同时跟函数服务进行了强关联 貌似不分开也是合理的 只是在强耦合的情况下 如何优雅的加载是个问题

sy296565890 commented 1 year ago

力皓大佬的建议虽然能解决setter样式问题,但是低代码主应用不停机的情况下动态加载新增的自定义setter的问题依然存在,还望大佬们能指点一二

liujuping commented 1 year ago
setter: CustomSetter,

如果是物料自定义的 setter,不是全局通用的,直接在使用到的物料配置 setter 的时候通过这种方法使用即可,没有必要再注册到全局。

如果必须要注册到全局,那就应该像是资产包一样,可以开发一个插件

1.找到这个资产包依赖的 setter, 2.请求 setter 的 js / css, 3.并使用 api 注入到全局。

不建议在物料代码里面再处理 setter。

sy296565890 commented 1 year ago

setter: CustomSetter, 没太明白这个在哪使用,方便给个示例吗

hzd822 commented 1 year ago

这块引擎上目前是没有处理的,你可以基于上面的思路扩展一下,主要还是将setter和物料分离,并且在适当的时候加载专属的setter,防止放全局影响资源

sy296565890 commented 1 year ago

首先 上面所说的setter是业务setter,属于强耦合类型,不是全局通用的 物料配置是说的meta.ts文件吗? meta.js 引用不了src里面的组件

sy296565890 commented 1 year ago

这块引擎上目前是没有处理的,你可以基于上面的思路扩展一下,主要还是将setter和物料分离,并且在适当的时候加载专属的setter,防止放全局影响资源 看了上面的解释 依然没法吧这个强耦合类型的setter进行分开 除非使用单仓多包 否则开发一个插件 要维护两套代码
但是单仓多包 开发一个插件依然是耦合的

sy296565890 commented 1 year ago

现在的物料包也没有view.css了 强制导入view.js还不够 有点懵 image

liujuping commented 1 year ago

meta.ts 为什么要引入 src 里面的文件?应该放到 lowcode 目录下呀。

jinchanz commented 1 year ago

dev 模式没有 view.css ,build 的时候是有的

jinchanz commented 1 year ago

@sy296565890

我理解你是想把 setter 列表放到资产包里,后面可以动态修改资产包里的 setter 数据,而不需要更新低代码应用的代码是吧;

我建议用资产包里的这个字段 AssetsExtConfig(这是扩展字段,你自己定义就行) ,把 setter 列表写在里面,然后在低代码主应用里获取这里的 setter 列表进行注册就行了。

jinchanz commented 1 year ago

你说的方案3其实也行,就是把 setter 写到 lowcode 目录下,最后打包进 meta.js 里,但是你说不能用 antd ,但是应该是可以的,我没验证过。不过这个确实不是推荐做法,这会导致 meta.js 比较大并且可能影响低代码主应用的样式。

sy296565890 commented 1 year ago

由于antd v5 是cssinjs v4直接引入资源后可以通过【const { Button, InputNumber } = window.antd;】使用

sy296565890 commented 1 year ago

v5也是可以使用的 但是有很多的问题,貌似不是最佳实践

import { createElement } from 'react';
import { ProFormDigit } from '@ant-design/pro-components';
import { InputNumber } from 'antd';
import { default as DigitalSignature } from './components/signature-digital'
window.okok = {
  ProFormDigit, // 可以使用
  InputNumber, // 可以使用
  DigitalSignature // 不能使用
}
// export { ProFormDigit } from '@ant-design/pro-components';
// //@ts-ignore
const registerSetter = window.top.AliLowCodeEngine.setters.registerSetter
// setTimeout(() => {
//   registerSetter('CustomSetter', CustomSetter)
// }, 0);

const NumberSetter2: React.FC<any> = () => {
  const { Button, InputNumber } = antd;
  // const {ProFormDigit} = ProComponents;
  const aa  = createElement(window.okok.ProFormDigit, {})
  const bb  = createElement(window.okok.DigitalSignature, {})
  return (
    <>
      <Button>ssssssss</Button>
      <InputNumber />
      {/* <ProFormDigit /> */}
      {aa}
      {bb}
    </>
  )
}
jinchanz commented 1 year ago

哦,明白了,在 lowcode 目录写组件确实可能遇到各种各样的问题,因为它设计出来只是为了写组件的配置描述信息的。

jinchanz commented 1 year ago

v5也是可以使用的 但是有很多的问题,貌似不是最佳实践

import { createElement } from 'react';
import { ProFormDigit } from '@ant-design/pro-components';
import { InputNumber } from 'antd';
import { default as DigitalSignature } from './components/signature-digital'
window.okok = {
  ProFormDigit, // 可以使用
  InputNumber, // 可以使用
  DigitalSignature // 不能使用
}
// export { ProFormDigit } from '@ant-design/pro-components';
// //@ts-ignore
const registerSetter = window.top.AliLowCodeEngine.setters.registerSetter
// setTimeout(() => {
//   registerSetter('CustomSetter', CustomSetter)
// }, 0);

const NumberSetter2: React.FC<any> = () => {
  const { Button, InputNumber } = antd;
  // const {ProFormDigit} = ProComponents;
  const aa  = createElement(window.okok.ProFormDigit, {})
  const bb  = createElement(window.okok.DigitalSignature, {})
  return (
    <>
      <Button>ssssssss</Button>
      <InputNumber />
      {/* <ProFormDigit /> */}
      {aa}
      {bb}
    </>
  )
}

嗯,这样太 hack 了,如果带来的理解成本和研发成本大于把 setter 拆分出来,还是拆分出来的好,哈哈

sy296565890 commented 1 year ago

是的 这样写太怪异了,拆出来的话可以使用lerna或pnpm 一仓多包的方式共享自定义组件部分的代码,但是如何动态引入呢 或者说 仅仅引入链接 可以做到自动 registerSetter(setterMap)吗

sy296565890 commented 1 year ago

@sy296565890

我理解你是想把 setter 列表放到资产包里,后面可以动态修改资产包里的 setter 数据,而不需要更新低代码应用的代码是吧;

我建议用资产包里的这个字段 AssetsExtConfig(这是扩展字段,你自己定义就行) ,把 setter 列表写在里面,然后在低代码主应用里获取这里的 setter 列表进行注册就行了。

AssetsExtConfig 这个方便写个使用示例吗, 我的理解 Assets 仅仅只是json对象, 还是说渲染之前需要自定义解析一下这一段?

jinchanz commented 1 year ago

image 看看这个回复,我没有具体想好,可以类似这样:

// assets.json

{
  packages: [],
 components: [],
  ......
  ......
  AssetsExtConfig: {
    // 类似官方 setter 打包好的资源
    setters: [
      //  'https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine-ext/1.0.5/dist/css/engine-ext.css',
      // 'https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine-ext/1.0.5/dist/js/engine-ext.js',
    ]
  }

}

低代码应用获取到资产包里的 AssetsExtConfig.setters ,然后动态把这里的资源加到 html 里就行了,你可以试试

sy296565890 commented 1 year ago

image 看看这个回复,我没有具体想好,可以类似这样:

// assets.json

{
  packages: [],
 components: [],
  ......
  ......
  AssetsExtConfig: {
    // 类似官方 setter 打包好的资源
    setters: [
      //  'https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine-ext/1.0.5/dist/css/engine-ext.css',
      // 'https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine-ext/1.0.5/dist/js/engine-ext.js',
    ]
  }

}

低代码应用获取到资产包里的 AssetsExtConfig.setters ,然后动态把这里的资源加到 html 里就行了,你可以试试

这个做法似乎是可行的,但是setter项目支持npm run dev吗,否则的话貌似不便于调试

jinchanz commented 1 year ago

setter 其实也就是组件,总有办法的,去试试吧,哈哈

sy296565890 commented 1 year ago

@jinchanz 大佬 这一部分 这样加载可行吗?

var link = window.top.document.createElement('link');
link.rel = "stylesheet";
link.href = 'https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine-ext/1.0.5/dist/css/engine-ext.css';
window.top.document.head.appendChild(link);

var script = window.top.document.createElement('script');
script.src = 'https://uipaas-assets.com/prod/npm/@alilc/lowcode-engine-ext/1.0.5/dist/js/engine-ext.js';
window.top.document.head.appendChild(script);
sy296565890 commented 1 year ago
// lowCodeExternals
"@alilc/lowcode-engine-ext": "AliLowCodeEngineExt",
// "@alilc/lowcode-engine-ext": "window.AliLowCodeEngineExt",
// 
import AliLowCodeEngineExt from '@alilc/lowcode-engine-ext';

const { setterMap, pluginMap } = AliLowCodeEngineExt;
// const { setterMap, pluginMap } = window.AliLowCodeEngineExt;

// 注册setterMap
setters.registerSetter(setterMap);

感觉万变不离其宗,又回来了 哈哈

sy296565890 commented 1 year ago

做个记录 image

sy296565890 commented 1 year ago

@jinchanz 大佬 有时间了再帮忙看看呀~ 感谢~

xiaochena commented 1 year ago

@jinchanz 大佬 有时间了再帮忙看看呀~ 感谢~

怎么样、、你那边现在是怎么处理的

sy296565890 commented 1 year ago

@jinchanz 大佬 有时间了再帮忙看看呀~ 感谢~

怎么样、、你那边现在是怎么处理的 没有理想的解决方案非常期待金蝉大佬帮忙出个动态加载接口

xiaochena commented 1 year ago

@jinchanz 大佬 有时间了再帮忙看看呀~ 感谢~

怎么样、、你那边现在是怎么处理的 没有理想的解决方案~非常期待金蝉大佬帮忙出个动态加载接口~

这个能够帮到你嘛、我目前的方式 https://github.com/alibaba/lowcode-engine/issues/1944

jinchanz commented 1 year ago

我正在肝一个平台来解决这类问题🫠,再等等我

或者想看看这个 https://github.com/AwesomeLowcode/lowcode-boot

sy296565890 commented 1 year ago

我正在肝一个平台来解决这类问题🫠,再等等我

或者想看看这个 https://github.com/AwesomeLowcode/lowcode-boot

感谢大佬支持,耐心等待中~~

sy296565890 commented 1 year ago

@jinchanz 大佬 有时间了再帮忙看看呀~ 感谢~

怎么样、、你那边现在是怎么处理的 没有理想的解决方案~非常期待金蝉大佬帮忙出个动态加载接口~

这个能够帮到你嘛、我目前的方式 #1944

感谢哥们的帮助,我需要在低代码主应用不重启的情况下动态加载设置器,期待金蝉大佬的解决方案~

jinchanz commented 1 year ago

image

可以先大概看看效果,plugin、setter、组件、主题都可以动态挑选,最后打包成一个 assets.json,然后项目直接引用就行;

我会同时给出平台打包,和线下自己打包的方案

sy296565890 commented 1 year ago

大佬太有心了,感谢大佬的支持!

jinchanz commented 1 year ago

@sy296565890 线下构建方案已经写好了,你可以试试看

https://github.com/AwesomeLowcode/build-plugin-assets

sy296565890 commented 1 year ago

@sy296565890 线下构建方案已经写好了,你可以试试看

https://github.com/AwesomeLowcode/build-plugin-assets

收到,太感谢大佬了~赶紧试试去~

MoLinJie commented 1 year ago

@sy296565890 大佬组件怎么用antd v5来开发啊,能给个简单的示例仓库吗

sy296565890 commented 1 year ago

@sy296565890 大佬组件怎么用antd v5来开发啊,能给个简单的示例仓库吗 第一步 物料库 安装"antd": "^5.4.5" 第二步 assets 中引入资源

{
"package": "antd",
"version": "5.4.5",
"urls": [
`https://unpkg.com/antd@5.4.5/dist/antd.min.js`,
],
"library": "antd"
},

其他步骤跟常规操作一致

MoLinJie commented 1 year ago

@sy296565890 大佬组件怎么用antd v5来开发啊,能给个简单的示例仓库吗 第一步 物料库 安装"antd": "^5.4.5" 第二步 assets 中引入资源

  {
   "package": "antd",
   "version": "5.4.5",
   "urls": [
   `https://unpkg.com/antd@5.4.5/dist/antd.min.js`,
   ],
   "library": "antd"
  },

其他步骤跟常规操作一致

按照您的方式我新建了一个组件库,组件提示异常了,请帮我看下哪个步骤不对呢 image

package.json

{
  ...
 "devDependencies": {
    "@alib/build-scripts": "^0.1.3",
    "@alifd/build-plugin-lowcode": "^0.3.0",
    "@alifd/theme-2": "^0.4.0",
    "@types/react": "^16.14.24",
    "@types/react-dom": "^16.9.4",
    "build-plugin-component": "^1.12.1",
    "build-plugin-fusion": "^0.1.0",
    "cross-env": "^7.0.3",
    "@umijs/plugin-sass": "^1.1.1",
    "dumi": "^1.1.49",
    "dumi-theme-default": "^1.1.24",
    "f2elint": "^1.2.0"
  },
  "dependencies": {
    "@alifd/next": "^1.25.27",
    "antd": "^5.4.5",
    "moment": "^2.29.4",
    "prop-types": "^15.5.8",
    "react": "^16.x",
    "react-dom": "^16.x"
  },
 ...
}

组件代码

import {Button} from "antd";
import React, {createElement} from "react";

export interface AntdButtonProps {
  type: string
}

const AntdButton: React.FC<AntdButtonProps> = (props) => {
  return (
    <Button>按钮</Button>
  )
}

export default AntdButton;

build.lowcode.js

const {library} = require('./build.json');

module.exports = {
  alias: {
    '@': './src',
  },
  plugins: [
    [
      '@alifd/build-plugin-lowcode',
      {
        library,
        engineScope: "@alilc",
        builtinAssets: [
          {
            packages: [
              {
                "package": "antd",
                "version": "5.4.5",
                "urls": [
                  `https://unpkg.com/antd@5.4.5/dist/antd.min.js`,
                ],
                "library": "antd"
              },
            ]
          }
        ]
      },
    ],
  ],
};
sy296565890 commented 1 year ago

@MoLinJie build.lowcode.js 中 builtinAssets 不需要加入

{
            packages: [
              {
                "package": "antd",
                "version": "5.4.5",
                "urls": [
                  `https://unpkg.com/antd@5.4.5/dist/antd.min.js`,
                ],
                "library": "antd"
              },
            ]
          }

可以参考 https://git.egdmail.cn/cy296565890/mateantdv5.git 【master 分支】

image 上图 assets中需要加入

"packages": [
    {
      "package": "dayjs",
      "version": "1.11.7",
      "urls": [
        `https://unpkg.com/dayjs@1.11.7/dayjs.min.js`,
        `https://unpkg.com/dayjs@1.11.7/locale/zh-cn.js`,
        // `//lcs.${domain}/lowcode/assets/npm/dayjs@1.11.7/myjs.js`,
      ],
      "library": "dayjs"
    },
    {
      "package": "@ant-design/icons",
      "version": "5.0.1",
      "urls": [
        `https://unpkg.com/@ant-design/icons@5.0.1/dist/index.umd.js`,
      ],
      "library": "icons"
    },
    {
      "package": "antd",
      "version": "5.4.5",
      "urls": [
        `https://unpkg.com/antd@5.4.5/dist/antd.min.js`,
        // `//lcs.${domain}/lowcode/assets/npm/antd@4.24.4/dist/antd.min.js`,
        // `//lcs.${domain}/lowcode/assets/npm/antd@4.24.4/dist/antd.min.css`,
      ],
      "library": "antd"
    },
   .......
sy296565890 commented 1 year ago

image

image

sy296565890 commented 1 year ago

我使用了node v20.x image

sy296565890 commented 1 year ago

该示例使用了 windows环境 【安装依赖】tyarn 【启动项目】tyarn dev

MoLinJie commented 1 year ago

@sy296565890 如果不替换builtinAssets中的antd版本,其实就是用v4的版本来开发,样式都是v4的,部分组件会直接报错(测试了导航菜单)。

sy296565890 commented 1 year ago

image image image

sy296565890 commented 1 year ago

image @MoLinJie 物料开发端确实也是v4 但我没用常规的开发方式 ,我直接引用了物料开发npm run lowcode:dev 的 view.js文件 image

MoLinJie commented 1 year ago

assets.json

"packages": [
    {
      "package": "demo-material",
      "version": "0.1.0",
      "library": "demoMaterials",
      "urls": [
        "http://localhost:3333/render/default/view.js"
      ],
      "editUrls": [
        "http://localhost:3333/view.js"
      ],
      "advancedUrls": {
        "default": [
          "http://localhost:3333/render/default/view.js"
        ]
      },
      "advancedEditUrls": {}
    },
   {
      "package": "dayjs",
      "version": "1.11.7",
      "urls": [
        "https://unpkg.com/dayjs@1.11.7/dayjs.min.js",
        "https://unpkg.com/dayjs@1.11.7/locale/zh-cn.js"
      ],
      "library": "dayjs"
    },
    {
      "package": "@ant-design/icons",
      "version": "5.0.1",
      "urls": [
        "https://unpkg.com/@ant-design/icons@5.0.1/dist/index.umd.js"
      ],
      "library": "icons"
    },
    {
      "package": "antd",
      "version": "5.4.5",
      "urls": [
        "https://unpkg.com/antd@5.4.5/dist/antd.min.js"
      ],
      "library": "antd"
    },
],
"components": [
    {
      "exportName": "DemoMaterialMeta",
      "npm": {
        "package": "demo-material",
        "version": "0.1.0"
      },
      "url": "http://localhost:3333/meta.js",
      "urls": {
        "default": "http://localhost:3333/meta.js"
      },
      "advancedUrls": {
        "default": [
          "http://localhost:3333/meta.js"
        ]
      }
    }
],

@sy296565890 请问是在编辑端这样添加吗?然后一边运行物料开发端,在编辑端预览?我这样尝试之后拖出来的组件渲染异常了呢