低代码组件的消费方式

低代码组件最终被发布成 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 中的字段去加载最合适的文件。

相关推荐
真的很上进2 小时前
【Git必看系列】—— Git巨好用的神器之git stash篇
java·前端·javascript·数据结构·git·react.js
qq_278063712 小时前
css scrollbar-width: none 隐藏默认滚动条
开发语言·前端·javascript
.ccl2 小时前
web开发 之 HTML、CSS、JavaScript、以及JavaScript的高级框架Vue(学习版2)
前端·javascript·vue.js
小徐不会写代码2 小时前
vue 实现tab菜单切换
前端·javascript·vue.js
2301_765347542 小时前
Vue3 Day7-全局组件、指令以及pinia
前端·javascript·vue.js
喝旺仔la2 小时前
VSCode的使用
java·开发语言·javascript
辛-夷2 小时前
VUE面试题(单页应用及其首屏加载速度慢的问题)
前端·javascript·vue.js
一个很帅的帅哥4 小时前
axios(基于Promise的HTTP客户端) 与 `async` 和 `await` 结合使用
javascript·网络·网络协议·http·async·promise·await
dream_ready5 小时前
linux安装nginx+前端部署vue项目(实际测试react项目也可以)
前端·javascript·vue.js·nginx·react·html5
编写美好前程5 小时前
ruoyi-vue若依前端是如何防止接口重复请求
前端·javascript·vue.js