低代码组件的消费方式

低代码组件最终被发布成 npm 包供低代码平台消费,组件被如何消费,这取决于组件提供了哪些消费方式。不论开源组件还是内源组件,开发方在编码之前都需仔细考量组件的消费方式,如果其方式与使用方的预期严重不符,那么使用方很可能不会选择该组件。本小节介绍组件有哪些消费方式,组件要提供这些消费方式该如何实现。总体上而言,组件有静态导入和动态加载这两种消费方式:

静态导入 使用 ES6 规范引入的 import 关键字导入组件,该规范要求组件是一个 ES6 规范的模块。静态导入适用于导入确定的模块,

动态加载 动态加载指的是程序运行过程中按需加载组件。浏览器自身支持的动态加载有两种。第一种,动态嵌入脚本标签,引用远程资源的 URL,例如 JavaScript 或 CSS 文件;第二种,ES 动态导入,用法是 import('模块路径')。

组件怎么被消费?这里有一个不得不谈的问题,即:组件被打包成什么样的模块格式。在 JavaScript 中模块格式有如下 4 种:

AMD

AMD 的全称是 Asynchronous Module Definition,即异步模块定义,它是为浏览器环境设计的,采用异步方式加载模块,但浏览器自身并不支持它,要加载 AMD 模块,必须使用特定的模块加载器,例如 RequireJS 和 curl.js 等。

常见的打包工具,比如 webpack,rollup 等都能通过配置项将模块自动打包成 AMD 格式,借助这些工具,组件的开发者在编码时无须关注如何将模块定义为 AMD 格式,但组件使用方消费组件时需要引入特定的模块加载器,用特定的语法去加载组件。使用 RequireJS 加载 AMD 格式的模块,代码如下:

javascript 复制代码
require(['foo'], function(foo) {
	// 在这里使用 foo 模块中导出的内容。
});

加载AMD模块除了需要在 js 文件中写入上述代码,还需要在 HTML 文件中用 script 标签引入 RequireJS 的 js 资源。

CommonJS

CommonJS 是为服务端 JavaScript 设计的模块规范,其一大特性是同步加载模块,该特性适用于服务器端应用程序,Node.js 是主要实践者。

回到本图书介绍的案例,低代码组件应该选用 AMD 规范还是 CommonJS 规范,这取决于组件是否需要支持服务端渲染。本图书不涉及服务端渲染的知识,但不意味着低代码 APP 不能实现服务端渲染。目前,客户端渲染是 Web 应用常见的展示方式,不过,有些企业考虑到搜索引擎优化或首屏渲染时长,会采用服务端渲染,因此在这里不断言低代码组件一定只在客户端使用。

UMD

介绍完前面 2 类模块,一些读者可能会思考是否存在一种既能这样又能那样的模块,UMD 模块就是这类模块。UMD 的全称是 Universal Module Definition,即通用模块定义,它主要用来解决 CommonJS 规范和 AMD 规范不能通用的问题,同时还支持老式的全局变量。 UMD 模块的代码特征如下:

javascript 复制代码
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' 
    ? module.exports = factory(require('react')) 
    : typeof define === 'function' && define.amd 
    ? define(['react'], factory) 
    : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.vitisLowcodeInput = factory(global.React));
}(this, (function (React) { 'use strict';
  // 组件模块的代码
  return component;

})));

UMD 规范的实现原理很简单:

  1. 先判断是否存在 exports 和 module ,存在则认为这是 CommonJS 模块。
  2. 再判断是否有 define 函数并且 define.amd 为真,是则认为这是 AMD 模块。
  3. 如果前两步都不满足,则将模块公开到全局。

ES modules

ES modules 是 ECMAScript 推出的模块规范,可以将其认为是 JavaScript 的"官方"模块规范,客户端 JavaScript 环境和服务器 JavaScript 环境已相继支持。不管低代码组件需要在服务端使用还是只在客户端使用,选择 ES modules 模块规范将是一个大趋势,值得注意的是,选择它需要考虑兼容性问题。

导入 ES 模块用到的关键字是 import,它根据模块路径将模块导入当前模块,模块路径也称为模块说明符。关于模块说明符有一些令人混淆的点,模块说明符一共有 3 种类型,分别是:相对路径、绝对路径和 bare(裸露) 模式。

(1) 相对路径

模块说明符是相对路径时,导入 ES 模块的代码如下:

javascript 复制代码
import foo from './myModule.js'
import { sayName } from '../other_module.js'

相对路径的说明符以 / 、./ 、../ 开头,此时不能省略文件的扩展名。也许有读者会问,为何他开发 Web 项目时,导入模块省略了文件扩展名,程序依然能够运行?那是因为项目中使用了如 Webpack 这样的模块打包工具,它对源代码的写法做了处理。

(2) 绝对路径

模块说明符是绝对路径时,导入 ES 模块的代码如下:

javascript 复制代码
import React from 'https://cdn.skypack.dev/react'

上述代码表示从 CDN 导入模块,绝对路径是否能省略文件扩展名,这与服务器的配置相关。

(3) bare(裸露)模式

模块说明符是bare模式时,导入ES模块的代码如下:

javascript 复制代码
import React from 'react'
import Foo from 'react/lib.js'

bare 模式会从 node_module 中导入模块,在 Web 项目中,用 bare 模式导入模块很常见,但 ES modules 本身并不支持它。在代码里之所以能这样写,是因为使用了如 Webpack 这样的模块打包工具,它对源代码的写法做了处理。

前面已经提到,我们不断言低代码组件的使用环境,也就是说它既能在服务端使用也能在客户端使用,如果不考虑兼容性问题,你完全可以选用 ES modules 规范。本图书作为参考资料,希望覆盖更多的知识,因此作者在设计低代码组件的方案时,选择将组件既打包成 UMD 格式,也打包成 ES modules 格式。

从组件模块的打包结果来看,它有一个 index.min.js 文件也有一个 index.esm.js 文件,前者是符合 UMD 规范的模块,后者是符合 ES modules 规范的模块。打包组件的工作由蚂蚁金服的开源项目 father 负责,组件开发者不必过多关注,只需给 father 的特定配置项赋值即可。

组件的代码以不同的模块规范被打包在两个不同的文件中,使用方消费组件时究竟该引入哪个文件呢?

这与 package.json 文件中 main 和 module 字段相关。将 index.min.js 赋给 main 字段,而将 index.esm.js 赋给 module 字段。如果组件的使用方用 ES modules 的语法引入组件,例如:import MyComponent from '组件路径',模块系统将认为 module 字段对应的文件是组件的入口;如果用AMD/commonjs 的语法引入组件,模块系统将认为 main 字段对应的文件是组件的入口。也就说只要使用方配置好程序的运行环境,模块系统将依据组件 npm 包的 package.json 中的字段去加载最合适的文件。

相关推荐
老码沉思录1 小时前
写给初学者的React Native 全栈开发实战班
javascript·react native·react.js
我不当帕鲁谁当帕鲁1 小时前
arcgis for js实现FeatureLayer图层弹窗展示所有field字段
前端·javascript·arcgis
那一抹阳光多灿烂1 小时前
工程化实战内功修炼测试题
前端·javascript
红中马喽4 小时前
JS学习日记(webAPI—DOM)
开发语言·前端·javascript·笔记·vscode·学习
Black蜡笔小新5 小时前
网页直播/点播播放器EasyPlayer.js播放器OffscreenCanvas这个特性是否需要特殊的环境和硬件支持
前端·javascript·html
Dread_lxy6 小时前
vue 依赖注入(Provide、Inject )和混入(mixins)
前端·javascript·vue.js
奔跑草-7 小时前
【前端】深入浅出 - TypeScript 的详细讲解
前端·javascript·react.js·typescript
羡与8 小时前
echarts-gl 3D柱状图配置
前端·javascript·echarts
前端郭德纲8 小时前
浏览器是加载ES6模块的?
javascript·算法
JerryXZR8 小时前
JavaScript核心编程 - 原型链 作用域 与 执行上下文
开发语言·javascript·原型模式