LowCode低码时代LowCode低码时代
  • 首页
  • 低代码/零代码动态
    低代码/零代码动态
    厂商融资信息、行业新闻、招投标、技术研究等动态
    Show More
    Top News
    AIGC点燃低/零代码市场
    3年 ago
    万字长文 | 低代码vs.传统开发:一个全面的比较
    2年 ago
    西门子Mendix低代码高级架构师卢春霖,将出席“低代码开发推动制造业数字化变革”线上研讨会
    2年 ago
    Latest News
    重磅!OpenAI开源首个Agent SDK,反击Manus
    1年 ago
    云计算巨头AI战略分化:谁将定义企业级AI的未来规则?
    1年 ago
    DeepSeek创造历史!登顶全球AI应用第2名,豆包排名第10
    1年 ago
    2025“赋能开发者”高峰论坛即将启幕,诚邀您报名参加!
    1年 ago
  • 市场研究
    市场研究Show More
    《Market Insight:中国低代码/零代码市场发展洞察 ( 2023 )》报告正式发布 | LowCode低码时代
    3年 ago
    国产大模型顶流「讯飞星火」:图片生成、代码生成,支持插件等重磅上线
    3年 ago
    报告 | 金现代:效能提升+内质跃迁,重塑电力IT领导者
    3年 ago
    Gartner:低代码的颠覆性力量
    3年 ago
    Gartner:什么是超级应用程序?
    3年 ago
  • 人物观点
    人物观点Show More
    原力CEO赵锐:ToDesk是国内唯一适合高精远程办公需求的解决方案
    2年 ago
    央视财经对话汪源:低代码最核心的是降低对写代码的人的要求
    3年 ago
    干货文章 | 低代码真的有价值吗?
    3年 ago
    壹沓科技融资近2亿元之后:以通用大语言模型赋能,构建数字机器人超级大脑
    3年 ago
    专访中银金科:数字营销成为新的增长引擎,未来业务转化是关键
    3年 ago
  • 活动
    活动
    最新活动,包含线上研讨会、技术预测峰会、线下峰会、…
    Show More
    Top News
    ISIG中国产业智能大会品牌介绍
    4年 ago
    炎黄盈动金融行业高级顾问张自刚,受邀出席“2022金融科技超自动化论坛”
    3年 ago
    超自动化·智启高效运营|艺赛旗2023年春季产品发布会成功举办
    3年 ago
    Latest News
    2024第五届ISIG产业智能大会,四大科技峰会共掀数字化创新浪潮
    1年 ago
    参赛者必看 | 拯救者杯OPENAIGC开发者大赛最全攻略指南来啦~
    2年 ago
    2024第四届ISIG产业智能大会(RPA超级自动化、AIGC大模型、低代码/零代码、流程挖掘)
    2年 ago
    超自动化·智启高效运营|艺赛旗2023年春季产品发布会成功举办
    3年 ago
  • 关于低码时代
    • LowCode原创研究
Reading: 浅谈低代码平台远程组件加载方案
Share
Notification Show More
Latest News
30部佳作突围!2025 AI视听创作嘉年华晋级名单揭晓,总决赛11月25日启幕
未分类
《2025 AI 大模型开发生态白皮书》正式发布 | 算泥社区
未分类
“AI幻想·未来亦城”2025AI视听创作嘉年华作品征集来了!
未分类
120万奖池,寻找最具想象力的AI创意开发者!2025骁龙人工智能创新应用大赛正式启动!
未分类
2025-10-21
未分类
Aa
LowCode低码时代LowCode低码时代
Aa
  • 低代码/零代码动态
  • 最新市场研究
  • 活动
  • 人物观点
  • 首页
  • 低代码/零代码动态
  • 最新市场研究
  • 人物观点
  • 活动
  • 关于低码时代
Have an existing account? Sign In
  • LowCode低码时代
Copyright©2015-2022 北京企智未来科技有限公司 All Rights Reserved.
LowCode低码时代 > Blog > 底层技术研究 > 浅谈低代码平台远程组件加载方案
底层技术研究

浅谈低代码平台远程组件加载方案

LowCode低码时代
Last updated: 2022/09/11 at 10:17 上午
LowCode低码时代 4年 ago
Share
SHARE

Contents
问题加载方案组件代码方案一:放在全局对象上步骤组件打包html 模板组件加载逻辑缺点方案二:amd步骤组件打包html 模板组件加载逻辑缺点优点方案三:ESModule步骤组件打包组件加载逻辑vite 配置缺点优点关于 Webpack 模块联邦结论参考

前言

低代码开发平台(LCDP)是无需编码(0 代码)或通过少量代码就可以快速生成应用程序的开发平台。通过可视化进行应用程序开发的方法,使具有不同经验水平的开发人员可以通过图形化的用户界面,使用拖拽组件和模型驱动的逻辑来创建网页和移动应用程序。这两年越来越多的公司和开发人员开始自研低代码平台来达到降本提效的目的。今天和大家分享一下低代码平台开发过程中遇到一个问题和对应的解决思路。

问题

低代码平台之所以不需要写代码是因为平台提供了很多可配置的组件,让平台的用户可以通过配置的方式生成自己想要的产物。那么如果想要能配置出更多的效果,就需要保证物料库足够丰富。

如果物料组件很多,就需要按需加载组件。现有的开发工具如 Webpack 也支持代码分割。但是在低代码平台的开发场景中,平台应用是和组件分离的,需要用户在选择某个组件的时候,要加载远程组件代码。

加载方案

组件代码

我们以 vue 框架为例,假如当前有一个组件 A,代码如下,如何远程加载这个组件呢?

<template>
    <div class="wp">{{text}}</div>
</template>

<script>
import { defineComponent, ref } from 'vue';
import _ from 'lodash';
  
export default defineComponent({
  setup(props) {
    console.log(_.get(props, 'a'));
    return {
      onAdd,
      option,
      size,
      text: 'hello world',
    };
  },
});
</script>

<style>
.wp {
    color: pink;
}
</style>

方案一:放在全局对象上

步骤

  1. 打包:组件代码打包为 umd 格式,打包时配置 Webpack externals, 使打包产物不包含公共的依赖;

  2. 上传:打包的组件 js 上传到 cdn;

  3. 加载:在需要使用组件时,插入一个 script ,在这个 script 中将组件放在一个全局对象上;

  4. 注册:在 script 插入完成后,从全局对象上获取组件,并进行注册;

组件打包

首先需要增加一个入口文件

import Component from './index.vue';

if(!window.share) {
  window.share = {};
}

window.share[Component.name] = Component;

以上面的入口文件为入口,用 Webpack 打包为 umd 格式

// 组件打包 Webpack 配置
const path = require('path');
const { VueLoaderPlugin } = require('vue-loader')

module.exports = {
  mode: 'production',
  entry: path.resolve(__dirname, './comps/index.js'),
  output: {
    filename: 'index.js',
    path: path.resolve(__dirname, 'dist'),
    library: { type: 'umd' }
  },
  module: {
    rules: [
      {
        test: /.vue$/,
        use: 'vue-loader',
        exclude: /node_modules/,
      },
      {
        test: /.js$/,
        loader: 'babel-loader'
      },
      {
        test: /.css$/,
        use: [
          'vue-style-loader',
          'css-loader'
        ]
      }
    ]
  },
  plugins: [
    new VueLoaderPlugin()
  ],
  externals: {
    vue: 'vue',
    lodash: 'lodash',
  }
};

html 模板

组件公共依赖都需要先加入到模板 html 中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn/vue.global.js"></script>
    <script src="https://cdn/lodash@4.17.21.min.js"></script>
</head>
<body>
    <div id="root"></div>
</body>
</html>

组件加载逻辑

const loadComponent = (name) => new Promise((resolve) => {
  const script = document.createElement('script');
  script.src=`http://xxx/${name}.js`;
  script.onload = script.onreadystatechange = function(){
     resolve();
  };
  document.querySelector('head').appendChild(script);
})

const addComp = async (name) => {
   await loadComponent(name);
   // 注册组件,其中 app 为 Vue 应用实例对象
   app.component(name, window.share[name]);
}

// 动态注册组件
addComp('A');


缺点

  1. 组件的依赖共享,需要依赖提前先放到全局,html 模板需要较频繁改动;
  2. 全局对象上要挂载的内容越来越多,影响加载性能,没有做到真正的按需加载;
  3. 依赖版本难以管理。如 A 组件依赖了 loadsh 1.0, 而 B 组件依赖了 lodash 2.0,但是全局对象上的 lodash,同时挂载两个版本就必然会有冲突,因此版本必须一致;且后续如果某个组件要升级某个依赖的版本,也势必会影响所以其他组件。

方案二:amd

amd 格式也是一种模块化方案,这里我们选择知名度比较高的 require.js 作为 amd 模块加载器。

步骤

  1. 打包:组件代码打包为 umd 或 amd 格式,打包时配置 Webpack externals,使打包产物不包含公共的依赖;
  2. 上传:打包的组件 js 上传到 cdn;
  3. 加载&注册:在需要使用组件时,用 requirejs 获取组件,并进行注册。

组件打包

用 amd 格式来做远程加载时不需要像方案一一样,增加额外的入口文件,可以直接将 .vue 文件作为入口。以下是 Webpack 打包配置示例

// 组件打包 Webpack 配置
const path = require('path');
const { VueLoaderPlugin } = require('vue-loader')

module.exports = {
  mode: 'production',
  entry: path.resolve(__dirname, './comps/index.vue'),
  output: {
    filename: 'index.js',
    path: path.resolve(__dirname, 'dist'),
    library: { type: 'umd' }  // 输出 amd 或者 umd
  },
  module: {
    rules: [
      {
        test: /.vue$/,
        use: 'vue-loader',
        exclude: /node_modules/,
      },
      {
        test: /.js$/,
        loader: 'babel-loader'
      },
      {
        test: /.css$/,
        use: [
          'vue-style-loader',
          'css-loader'
        ]
      }
    ]
  },
  plugins: [
    new VueLoaderPlugin()
  ],
  externals: {
    vue: 'vue',
    lodash: 'lodash',
  }
};

html 模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./require.js"></script>
</head>
<body>
    <div id="app"></div>
</body>
</html>

组件加载逻辑

// main.js
requirejs.config({
  baseUrl: 'https://cdn.xxx.com',
  map: {
    '*': {
      css: 'require-css',
    },
  },
  paths: {
    echarts: 'echarts@5.1.1',
    vueDemo: 'vue-demo',
    vue: 'vue@3.2.37',
    moment: 'https://cdn/moment@2.29.1.min',
  },
  shim: {
    'ant-design-vue': ['css!https://cdn/ant-design-vue@2.1.6.min.css'],
  },
});

requirejs(['vue', 'vue-demo', 'vue-app'], function (vue, vueDemoModule, VueAppModule) {
  const app = Vue.createApp(VueAppModule.default);
  app.component('vue-demo', vueDemoModule.default);
  const vm = app.mount('#app');
});

缺点

  1. 平台代码(上述代码的vue-app)也需要编译为 amd 格式,然后上传到 cdn 上,开发流程改变,需要定制化的开发平台项目的发布机制。
  2. 有些第三方库没有提供 amd 或 umd 格式,需要开发者自己开发工具去转换(此过程中可能有很多坑要踩);

优点

  1. 相比于方案一,组件的依赖可以有版本差异且互相不影响。
  2. 组件和组件的依赖都可以按需加载,真正做到按需加载。
  3. 有现成的加载 css 文件的机制;

方案三:ESModule

步骤

  1. 打包:组件代码打包为 esm 格式,打包时配置 Webpack externals, 使打包产物不包含公共的依赖;
  2. 上传:打包的组件 js 上传到 cdn;
  3. 加载&注册:在需要使用组件时,用 esm 的动态引入获取组件,并进行注册;

组件打包

这里需要注意的是,externals 配置项中直接把公共依赖配置为 cdn 地址;

import path from 'path';
import VueLoader from 'vue-loader';

const VueLoaderPlugin = VueLoader.VueLoaderPlugin;

const __dirname = path.resolve();

export default {
  mode: 'development',
  entry: path.resolve(__dirname, './src/vue-demo.vue'),
  output: {
    filename: 'vue-demo.esm.js',
    path: path.resolve(__dirname, 'components'),
    library: { type: 'module' }
  },
  experiments: { outputModule: true },
  module: {
    rules: [
      {
        test: /.vue$/,
        use: 'vue-loader',
        exclude: /node_modules/,
      },
      {
        test: /.js$/,
        loader: 'babel-loader'
      },
      {
        test: /.css$/,
        use: [
          'vue-style-loader',
          'css-loader'
        ]
      }
    ]
  },
  plugins: [
    new VueLoaderPlugin()
  ],
  externals: {
    vue: 'https://cdn.jsdelivr.net/npm/vue@3.2.37/dist/vue.esm-browser.js',
    'lodash': 'https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.js'
  }
};

使用上述配置打包后产物,中会把 'vue' 替换为 externals 中的 cdn 地址

// 输入
import Vue from 'vue';

// 输出结果
import Vue from 'https://cdn.jsdelivr.net/npm/vue@3.2.37/dist/vue.esm-browser.js';

组件加载逻辑

const list = ref([]);

const addComp = async () => {
  const VueDemo = await import(/* @vite-ignore */`http://cdn/components/vue-demo.esm.js`)
  window.app.component('vue-demo', VueDemo.default);
  list.value.push({ key: new Date().valueOf(), name: 'vue-demo' });
}

vite 配置

需要注意的是要保证本地开发时引入的 vue 也是远程的,所以需要在 vite 的配置文件中增加 alias 配置。

// vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      'vue': 'https://cdn.jsdelivr.net/npm/vue@3.2.37/dist/vue.esm-browser.js'
    }
  }
})

缺点

  1. 兼容性问题:很多 Webpack 已经支持很好的功能还没有得到主流浏览器的支持
  2. 对很多第三方依赖的转化处理不完善,缺失完善的解决机制。要将第三方依赖的加载全部交给浏览器本身来接管,那么首先开发工具要做的就是将第三方依赖全部转换为 ESModule 的模块,而现在 npm 上的绝大部分包都是只支持 CommonJS 版本的,因此这里的转换过程通常需要由开发者自己来接管,而这其中有很多底层的问题并没有得到好的解决。同时,在 ESModule 规范推进的过程中,有许多如 exports.default、exports.__esModule 等利用语法来兼容 ESModule 和 CommonJS 的废案往往也都被 babel 实现,而且被许多开发者使用并且发布到了 npm 上,这就导致了现在 npm 上的许多包中有大量的废弃兼容性代码,而这些代码往往会对开发工具的转化造成阻碍。

优点

  1. 真正的按需加载
  2. 代码上更加优雅

关于 Webpack 模块联邦

基于笔者对模块联邦的了解,笔者认为 Webpack 的模块联邦,目前更加适合微前端的场景,但是不太适用于低代码平台的场景。但是笔者对 webpack 模块联邦了解不够深入,判断不一定准确,欢迎有不同意见的小伙伴在评论区讨论。

结论

对比上面三个方案,方案一实现起来最简单,但是没有真正实现按需加载,随着项目规模和需要满足的业务场景的扩大,组件的公共依赖会越来越多。方案二 、方案三 都能实现真正的按需加载,其中 require.js 虽然听上去已经是上个世纪的东西了,但是兼容性和坑相对比较少。说到 ESModule, 虽然有兼容性和上面提到的一些格式转化的问题,但随着近些年 Vite 、Snowpack 的发展,在未来 ESModule 一定是大势所趋,目前笔者也正在将负责的我司内部大屏低代码平台改造为 ESModule 方式加载。

参考

  • requirejs 中文文档 [https://www.requirejs-cn.cn/]
  • ESModule 系列 ㈠ :演进 [https://mp.weixin.qq.com/s/0AHmP70HnLUZeJWQlRtUKw]
  • Require.js 加载 css 依赖 [https://blog.csdn.net/lihefei_coder/article/details/81333036]

– END –

You Might Also Like

低代码没有做到的事情,ChatGPT做到了

贴吧低代码高性能规则引擎设计

vivo 低代码平台【后羿】的探索与实践

vivo游戏中心低代码平台的提效秘诀

LowCode低码时代 2022-08-08
Previous Article 网易数帆陈谔:云原生“牵手”低代码,加速企业数字化转型
Next Article 浙江传媒学院,门户、办事大厅升级及无(低)代码开发平台,中标公告
Leave a comment

发表回复 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注

about us

关注中国低代码(LowCode)无代码/零代码领域,包括行业研究、市场报告、技术选型和媒体报道,推进低代码的技术普及、生态建设发展和产业应用,重塑IT开发和自动化的未来。

  • 最新市场研究
  • 人物观点
  • 低代码/零代码动态
  • 活动
  • 联系我们
  • RPA中国
  • 数字金融网
  • 信创中国
  • Xverse元宇宙

最新专家访谈

原力CEO赵锐:ToDesk是国内唯一适合高精远程办公需求的解决方案
央视财经对话汪源:低代码最核心的是降低对写代码的人的要求
干货文章 | 低代码真的有价值吗?
壹沓科技融资近2亿元之后:以通用大语言模型赋能,构建数字机器人超级大脑
专访中银金科:数字营销成为新的增长引擎,未来业务转化是关键
实现技术普惠 网易数帆轻舟低代码的差异化竞争之道
LowCode低码时代LowCode低码时代

Copyright©2015-2022 北京企智未来科技有限公司 All Rights Reserved.
京ICP备19023145号-8

  • LowCode低码时代
订阅最新动态!

订阅最新低代码/零代码市场报告、研究咨询、分析师趋势以及市场活动

Zero spam,可随时取消订阅.

Removed from reading list

Undo
欢迎回来!

登录你的账号

Lost your password?