前言
最近在做一个构思代码编辑器,遇到了一个问题就是当内置组件过多时编辑器整体代码体积过重。会存在如下两个问题(我考虑到的,也许还有其他方面):
- 如何让整个编辑器在构建和加载速度方面更加快速
- 如何增强组件可扩展性,例如随时上架和下架一下组件
针对上面两个问题,接下来来总结一下UMD远程组件的实现方式。
什么是UMD
首先我们应该先要了解一下什么UMD在其他章节开始前,我们必须先了解清楚他的定义。
UMD 模块规范: UMD模块本质就是一个JavaScript文件,它会试图去猜测该文件当前运行环境正在使用的模块系统。你可以通过script标签或者AMD、CommonJS进行加载,其内部会自行判断当前执行该文件的模块系统是哪种。这样子做的好处在于,我们不需要针对浏览器、AMD、CommonJS针对性的构建build产物、以及它也支持使用CDN的方式加载
用简短的话来说: 它是一种兼容浏览器全局变量、AMD 规范、CommonJS 规范的规范.
构建UMD模块
接下来使用vite来打包一个工具包, vite会默认生成ES module和UMD module代码文件
-
编写工具类定义一个AKclown类暴露一个sayHello方法,引用getClassName和getRandomInt方法并且进行打印 -
生成
.d.ts文件 借助tsc工具生成类型文件
// 添加typescript
pnpm add typescript -D
// 默认生成tsconfig.json
npx tsc --init
// 编译
npx tsc
tsconfig.json文件配置,如下是我按照默认选择改动后的
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"declaration": true,
"emitDeclarationOnly": true,
"declarationDir": "./dist",
"esModuleInterop": true,
"allowImportingTsExtensions": true
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
},
"include": ["./src/*"],
"exclude": []
}
- 配置
vite构建符合UMD和ES文件
import { resolve } from 'path'
import { defineConfig } from 'vite'
export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, './src/main.ts'),
name: 'clown', // 指定window挂在的名称。 window.clown
fileName: 'UMD-TEST',
formats: ['umd'],
},
},
})
通过如上配置最终生成打包后的umd代码如下:
分析UMD代码
接下来分析一下构建产物UMD-TEST.umd文件。我们先删除掉不相干代码只保留UMD基础格式
(function (e, t) {
typeof exports == "object" && typeof module < "u" ? module.exports = t() :
typeof define == "function" && define.amd ? define(t)
: (e = typeof globalThis < "u" ? globalThis :
e || self, e.AKclown = t())
})(this,
function () {
...
return 入口类型
});
- 条件
typeof exports == "object" && typeof module < "u"在Node环境打印如下:typeof module < "u"是用来检查module是否被定义,typeof module获取到的值为object然后按照字典顺序比较object和u,字典上object顺序小于u所以表达式为true
2.条件 typeof define == "function" && define.amd。先构建AMD环境然后在将这个条件进行打印:
<script data-main="./amd" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"></script>
启动浏览器打印结果:
这里可以看到关于AMD的介绍 Asynchronous Module Definition定义。判断define和define.amd是否存在,如果存在则判断为是AMD环境
- 条件
e = typeof globalThis < "u" ? globalThis : e || self。 首先我们要了解一下globalThis关键字表示是什么
globalThis提供了一个标准的方式来获取不同环境下的全局 this 对象(也就是全局对象自身)
typeof globalThis < "u"返回的字符串是否比"u"小(例如undefined),通常表示不支持globalThis的环境。
在web work中是采用self关键字获取全局变量的
总结:
首先判断是否为NODE环境,如果是那如果用module.exports = t()暴露工具类。
紧接着判断是否为AMD环境,如果是采用define(t)定义模块。
都不符合将工具类挂载到全局变量上e.AKclown = t()
组件资产Assets的定义
在完成UMD模块构建时,我们需要定义assets.json(资产)来记录包名称、版本号、组件的UMD地址等,这里推荐参考阿里低代码引擎的资产包定义
在完成如上步骤之后,就可以通过请求
assest.json文件就可以得到远程组件的基础信息。然后通过遍历该数组就实现了加载远程组件了。
总结
通过上述字段,我们学习了UMD模块的含义、vite构建UMD、解析UMD的基础结构、assests资产包定义。在项目里面如何加载UMD、如何解决UMD模块同名问题、如何结合沙箱机制加载...将在下一节解决