ifs-code-tools
v1.0.11
Published
IFS Code - tools for embedding widgets in third-party platforms
Readme
ifs-code-tools
轻量级 Widget 嵌入工具库,用于在第三方平台加载并渲染由 IFS Code / Mixo 平台生产的 Widget。
支持两种加载方式: 通过
appId(推荐)或url加载 Widget,内置资源缓存、超时控制和错误处理。
安装
npm install ifs-code-tools| 环境要求 | 版本 | | --- | --- | | 浏览器 | 支持 ES2020 的现代浏览器 | | React(宿主页面提供) | 16 / 17 / 18,react 与 react-dom 版本需一致 |
前置条件:宿主页面需提供 React 全局
Widget 产物不自带 React,运行时依赖宿主页面的 UMD 全局 window.React / window.ReactDOM。
即使通过 npm 安装本库、业务代码使用的是 npm 版 React,也仍需在页面中通过 <script> 引入一份 React UMD(供 Widget 产物复用,全页面共享同一实例):
<script crossorigin src="https://g.alicdn.com/code/lib/react/18.3.1/umd/react.production.min.js"></script>
<script crossorigin src="https://g.alicdn.com/code/lib/react-dom/18.3.1/umd/react-dom.production.min.js"></script>- 缺失时
loadWidget/preloadWidget/WidgetRender会直接失败并在控制台报错,不会静默加载第二份 React(避免多实例共存导致 hooks / Context / 事件系统错串的隐蔽故障)。 - 不支持 React 19+:React 19 起官方不再提供 UMD 构建,无法产生
window.React/window.ReactDOM全局。
快速开始
import { loadWidget } from 'ifs-code-tools';
const instance = await loadWidget({
appId: 'my-app-id',
container: '#widget-container',
props: { theme: 'dark' },
});
instance.update({ theme: 'light' }); // 更新属性
instance.unmount(); // 卸载API
loadWidget(options): Promise<WidgetInstance>
加载并挂载 Widget 到指定容器,返回可控制的实例对象。
import { loadWidget } from 'ifs-code-tools';
// 方式一:通过 appId 加载(推荐)
const instance = await loadWidget({
appId: 'my-app-id',
container: '#widget-container',
props: { theme: 'dark' },
});
// 方式二:通过 url 加载(产物压缩包地址)
const instance = await loadWidget({
url: 'https://cdn.example.com/widgets/my-widget.zip',
container: document.getElementById('widget-container'),
});Options (LoadWidgetOptions):
| 参数 | 类型 | 必填 | 默认值 | 说明 |
| --- | --- | --- | --- | --- |
| appId | string | 二选一 | — | Widget 应用 ID |
| url | string | 二选一 | — | Widget 产物压缩包地址 |
| platform | 'mixo' \| 'ifs' \| 'external' | 否 | 自动判断 | Widget 所属平台,仅 appId 方式生效(见下方说明) |
| container | HTMLElement \| string | 是 | — | 挂载容器(DOM 元素或 CSS 选择器) |
| props | WidgetProps | 否 | {} | 传递给 Widget 的属性 |
| timeout | number | 否 | 30000 | 加载超时时间(ms) |
| onLoad | () => void | 否 | — | 加载成功回调 |
| onError | (error: Error) => void | 否 | — | 加载失败回调 |
appId和url必须提供其中一个,同时提供时appId优先。
关于 url: 与 appId 走完全相同的解析逻辑,区别只在于压缩包地址的来源:
| 入参 | 压缩包地址来源 | 后续处理 |
| --- | --- | --- |
| appId | 按 platform 请求接口换取 | 下载压缩包,解析包内 widget/index.js、widget/index.css、widget/schema.json |
| url | 就是传入的 url | 同上 |
url不要求.zip后缀,发布后的产物链接(包含无扩展名、带签名参数的 OSS 地址)直接传入即可;请确保该地址开启了 CORS。
关于 platform:一键对外的小部件必须传 'external',其余大多数情况不用传。
通过 appId 加载时,库会先请求一个接口换取 Widget 产物地址。三个取值的流程完全一致,只是接口地址不同:
| 传入值 | 请求地址 |
| --- | --- |
| 'mixo' | https://mixo.alibaba-inc.com/mixo/open/getPublishFileUrlOpen(内网) |
| 'ifs' | https://code.iconfont.cn/ifs/open/getPublishFileUrlOpen(外网) |
| 'external' | https://code.iconfont.cn/ifs/api/app/getExternalRenderUrl(一键对外) |
一键对外发布的小部件换取地址的接口不同,必须显式指定:
const instance = await loadWidget({
appId: 'my-app-id',
platform: 'external',
container: '#widget-container',
});
// 实际请求:https://code.iconfont.cn/ifs/api/app/getExternalRenderUrl?appId=my-app-id不传 platform 时会根据当前页面域名在 'mixo' / 'ifs' 之间自动判断,典型需要显式指定的场景:
- 一键对外的小部件:自动判断不会选到
'external',必须手传 - 本地开发(
localhost)加载 Widget:自动判断会走公共接口,如果 Widget 属于 mixo 平台需要传'mixo' - 跳平台加载:页面所在平台与 Widget 所属平台不一致时
注意:
'mixo'对应的是内网地址,仅内网环境可访问;'external'固定请求正式外网地址。
返回值 (WidgetInstance):
| 方法 | 说明 |
| --- | --- |
| update(newProps) | 更新 Widget 属性(不会重新加载) |
| unmount() | 卸载 Widget 并清理资源 |
preloadWidget(options): Promise<void>
提前加载 Widget 资源到缓存(不挂载),后续调用 loadWidget 时可跳过网络请求,实现秒开。
import { preloadWidget, loadWidget } from 'ifs-code-tools';
// 页面初始化时预加载
preloadWidget({ appId: 'my-app-id' });
// 用户交互时快速挂载(命中缓存,无需等待网络)
const instance = await loadWidget({
appId: 'my-app-id',
container: '#container',
});| 参数 | 类型 | 说明 |
| --- | --- | --- |
| appId | string | Widget 应用 ID(与 url 二选一) |
| url | string | Widget 产物压缩包地址(与 appId 二选一) |
| platform | 'mixo' \| 'ifs' \| 'external' | Widget 所属平台,仅 appId 方式生效,同 loadWidget |
预加载失败时静默处理,不会抛出异常。
<WidgetRender /> React 组件
声明式的 React 组件,封装了 Widget 的加载、更新和卸载生命周期。
import { WidgetRender } from 'ifs-code-tools';
function App() {
return (
<WidgetRender
appId="my-app-id"
widgetProps={{ theme: 'dark' }}
loading={<div>加载中...</div>}
fallback={(error) => <div>加载失败: {error.message}</div>}
onLoad={() => console.log('Widget 已加载')}
onError={(err) => console.error(err)}
/>
);
}Props (WidgetRenderProps):
| 参数 | 类型 | 必填 | 默认值 | 说明 |
| --- | --- | --- | --- | --- |
| appId | string | 二选一 | — | Widget 应用 ID |
| url | string | 二选一 | — | Widget 产物压缩包地址,同 loadWidget |
| platform | 'mixo' \| 'ifs' \| 'external' | 否 | 自动判断 | Widget 所属平台,仅 appId 方式生效,同 loadWidget |
| widgetProps | WidgetProps | 否 | {} | 传递给 Widget 的属性 |
| timeout | number | 否 | 30000 | 加载超时时间(ms) |
| className | string | 否 | — | 容器 CSS 类名 |
| style | React.CSSProperties | 否 | — | 容器内联样式 |
| loading | ReactNode | 否 | — | 加载中占位内容 |
| fallback | ReactNode \| ((error: Error) => ReactNode) | 否 | — | 加载失败兜底内容 |
| onLoad | () => void | 否 | — | 加载成功回调 |
| onError | (error: Error) => void | 否 | — | 加载失败回调 |
组件行为:
url/appId/platform变化时自动卸载旧实例并重新加载widgetProps变化时通过instance.update()增量更新,不触发重新加载- 组件卸载时自动清理 Widget 实例
TypeScript 支持
本库使用 TypeScript 编写,开箱即用地提供完整类型定义,支持类型检查和 IDE 智能提示。
核心类型导出:WidgetProps、WidgetInstance、LoadWidgetOptions、WidgetPlatform。
License
MIT
