十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ice.js 的 JSX Runtime 深入解析:`@ice/jsx-runtime` 的原理、安装与使用指南

ice.js 的 JSX Runtime 深入解析:`@ice/jsx-runtime` 的原理、安装与使用指南 前端Web框架SSR前端构建插件系统微前端跨平台【免费下载链接】ice ice.js: The Progressive App Framework Based On React基于 React 的渐进式应用框架项目地址https://gitcode.com/gh_mirrors/ice1/ice点击查看免费下载ice/jsx-runtime是 ice.js 框架自带的 JSX 运行时包它在 React 官方react/jsx-runtime与react/jsx-dev-runtime之上做了一层轻量封装让 ice.js 应用在自动 JSX 转换automatic runtime模式下拥有统一的入口、开发/生产双通道以及rpx等单位转换能力。本文将围绕packages/jsx-runtime/README.md的安装说明展开并结合 packages/jsx-runtime 包的源码、测试与框架接入代码讲清它的设计动机、内部实现、接入方式与典型使用场景。为什么 ice.js 需要自己的 JSX RuntimeJSX 是 React 生态的语法糖浏览器无法直接执行需要先经编译器转换成jsx()/jsxs()生产或jsxDEV()开发函数调用。从 React 17 开始官方提供了新的 JSX 转换方式——自动运行时automatic runtime编译器不再需要显式import React而是自动从指定的 import source 引入上述函数。ice.js 在此基础上更进一步它希望 JSX 转换后的产物能够统一框架内的 JSX 入口便于后续升级与兼容支持样式属性的单位自动转换如rpx→vw面向小程序、多端等场景区分开发dev与生产prod两套运行时保证开发期的 HMR、SourceMap 与生产期的性能优化互不干扰兼容 webpack 4 等旧构建链路保持向后兼容CHANGELOG 0.2.0 明确提到 Allow directly use of ice/jsx-runtime, also compatible with webpack 4。这些诉求正是 packages/jsx-runtime 这个包存在的意义它不是重新实现一套 JSX 引擎而是对 React 官方运行时的高质量封装。安装与包结构按照官方文档packages/jsx-runtime/README.md安装只需一条命令$ npm i ice/jsx-runtime --save包本身是 ESM 模块type: module由 packages/jsx-runtime/package.json 定义其关键字段如下字段值说明main/module./esm/index.js默认入口同时导出createElement与生产环境产物types./esm/index.d.ts类型声明exports[.]./esm/index.js包根路径导出exports[./jsx-runtime]./esm/prod.js生产 JSX 运行时exports[./jsx-dev-runtime]./esm/dev.js开发 JSX 运行时peerDependencies.react^16 \|\| ^17 \|\| ^18兼容 React 16/17/18sideEffects含dist/*与样式文件告知打包器样式不可 tree-shaking同时包根目录还提供两个 CommonJS 兼容入口packages/jsx-runtime/jsx-runtime.jsmodule.exports require(./esm/prod)packages/jsx-runtime/jsx-dev-runtime.jsmodule.exports require(./esm/dev)这意味着无论构建器采用 ESM 还是 CJS 解析方式都能正确命中对应的运行时实现。源码结构一图流packages/jsx-runtime/src 目录下共 5 个文件职责清晰文件职责index.ts包总入口导出prod全部内容并向后兼容导出createElementcreateElement.ts兼容React.createElement的封装向后兼容prod.ts生产环境jsx/jsxs/Fragment实现dev.ts开发环境jsxDEV/Fragment实现style.ts核心工具hijackElementProps负责样式单位转换入口文件 packages/jsx-runtime/src/index.ts 只有两行export * from ./prod.js; export { createElement } from ./createElement.js;CHANGELOG 0.3.1 中 export createElement for backward compatibility 正是对这一向后兼容导出的说明——老项目如果仍然直接调用createElement无需改动即可迁移到新入口。核心实现开发/生产双通道生产运行时 prod.tspackages/jsx-runtime/src/prod.ts 从react/jsx-runtime引入官方实现再包裹一层自己的hijackElementProps// ts-ignore import { jsx as _jsx, jsxs as _jsxs, Fragment } from react/jsx-runtime; import { hijackElementProps } from ./style.js; function jsx(type: any, props: object, maybeKey: string, source: object, self: any) { return _jsx(type, hijackElementProps(props), maybeKey, source, self); } function jsxs(type: any, props: object, maybeKey: string, source: object, self: any) { return _jsxs(type, hijackElementProps(props), maybeKey, source, self); } export { Fragment, jsx, jsxs };关键点签名与官方对齐jsx接收type、props、maybeKey、source、self完全遵循 React RFC 107代码注释中明确引用了 React JSX transform RFC 的思路确保编译产物兼容jsxs是静态子节点特化源码注释 special case jsxs internally to take advantage of static children 说明jsxs对应静态子节点场景官方实现内部有专门的优化路径透明代理除hijackElementProps之外其余行为 100% 委托给官方react/jsx-runtime因此 React 16/17/18 的行为差异完全由官方运行时保证。开发运行时 dev.tspackages/jsx-runtime/src/dev.ts 对应react/jsx-dev-runtime导出jsxDEV// ts-ignore import { jsxDEV as _jsxDEV, Fragment } from react/jsx-dev-runtime; import { hijackElementProps } from ./style.js; function jsxDEV(type, props, key, isStaticChildren, source, self) { return _jsxDEV(type, hijackElementProps(props), key, isStaticChildren, source, self); } export { jsxDEV, Fragment };jsxDEV的source/self参数在开发环境下会携带组件源码位置信息供 React DevTools 与错误堆栈使用isStaticChildren则让编译器提前告知运行时子节点是否静态便于官方实现优化。ice.js 框架会根据构建模式自动选择入口CHANGELOG 0.3.0use jsx-dev-runtime when development实现开发体验与生产体积的平衡。灵魂所在hijackElementProps 与单位转换packages/jsx-runtime/src/style.ts 是本包最核心的业务逻辑也是与纯 React 运行时最大的差异点// ts-ignore import { convertUnit } from style-unit; const STYLE style; function isObject(obj: any): obj is object { return typeof obj object; } // Support rpx unit. export function hijackElementProps(props: { style?: object } | object): object { if (props STYLE in props) { const { style } props; if (isObject(style)) { const result Object.assign({}, props); const convertedStyle {}; for (const prop in style) { // ts-ignore convertedStyle[prop] typeof style[prop] string ? convertUnit(style[prop]) : style[prop]; } result[style] convertedStyle; return result; } } return props; }它的工作流程检查props是否存在style属性仅当style是对象时执行转换字符串形式的 style 如font-size: 12px不处理通过style-unit包的convertUnit对每个字符串类型的样式值做单位转换非字符串如数字fontSize: 14原样保留返回一份浅拷贝的新propsObject.assign({}, props)避免原地修改。单元测试 packages/jsx-runtime/tests/hijackElememt.test.ts 给出了非常直观的验证// 不带 style 的 props 原样返回 const props hijackElementProps({ data: , number: 1, fontSize: 12rpx }); expect(props).toStrictEqual({ data: , number: 1, fontSize: 12rpx }); // style 对象中的字符串单位会被 convertUnit 转换 const props hijackElementProps({ style: { fontSize: 14, height: 12px, with: 12rpx } }); expect(props).toStrictEqual({ style: { fontSize: 14, height: 12px, with: 1.6vw }, });从测试可以看到12rpx被转换为1.6vwrpx 与 vw 的换算关系由style-unit的convertUnit内部规则决定通常以 750 设计稿为基准而数字fontSize: 14与普通 px 值12px保持不变。这正是 ice.js 面向多端小程序、H5、PHA 等场景时的关键能力——开发者书写rpx单位运行时自动换算为vw。仓库中 packages/plugin-miniapp/src/miniapp/index.ts 的enableRpx2Vw: false配置也印证了 rpx ↔ vw 转换是 ice.js 体系的通用能力只是在小程序端无需再做此转换。注意convertUnit的换算基准与style-unit版本相关若你的项目对 rpx→vw 换算比例有强约束建议通过单元测试固化预期值如上测试所示。createElement 向后兼容封装packages/jsx-runtime/src/createElement.ts 提供了对老式React.createElement的兼容import { createElement as reactCreateElement } from react; import { hijackElementProps } from ./style.js; export function createElement(type: any, props: any, ...children: any[]) { return reactCreateElement(type, hijackElementProps(props), ...children); }它把hijackElementProps的能力同样注入到 classic 模式的createElement调用中配合 CHANGELOG 0.3.1 的 export createElement for backward compatibility旧代码可以平滑迁移而无需重写 JSX 转换方式。在 ice.js 框架中的接入方式ice/jsx-runtime不是孤立存在的包它与 ice.js 的构建链路紧密集成1. 运行时重导出层ice.js 在 packages/runtime/src/jsx-runtime.ts 和 packages/runtime/src/jsx-dev-runtime.ts 中分别重导出export * from ice/jsx-runtime/jsx-runtime; export * from ice/jsx-runtime/jsx-dev-runtime;这样框架内部统一使用ice/runtime作为 JSX 的 import source对外暴露稳定接口。2. 构建期自动注入在 packages/shared-config/src/unPlugins/compilation.ts 的getJsxTransformOptions中ice.js 通过 SWC 配置将 JSX 转换指向框架自己的运行时const reactTransformConfig: ReactConfig { development: mode development, refresh: fastRefresh, runtime: automatic, importSource: ice/runtime/react, // The exact import source is ice/runtime/react/jsx-runtime };runtime: automatic启用自动 JSX 运行时importSource决定了编译器生成的jsx等函数从哪个模块导入。而 packages/runtime/src/react.ts 则保证即使 import source 解析到ice/runtime/react也能正确导出createElement供框架使用。由此开发者的所有 JSX 编译产物都会经过ice/jsx-runtime的处理链进而获得rpx单位转换等框架级能力。3. 客户端入口中的配合在 packages/ice/templates/core/entry.client.tsx.ejs 中可以看到框架对 Fragment 使用的谨慎处理import { createElement, Fragment } from react; ... // Add react fragment for split chunks of app. // Otherwise chunk of route component will pack ice/jsx-runtime and depend on framework bundle. const App /;模板注释明确说明通过在入口显式引用Fragment来自react而非ice/jsx-runtime避免路由组件的 chunk 把ice/jsx-runtime打包进业务代码从而消除对框架 bundle 的运行时依赖。这从侧面反映了 JSX 运行时在分包、按需加载场景下的重要性——它应当属于框架基础设施而不是被业务 chunk 重复携带。构建与发布packages/jsx-runtime/package.json 中的构建脚本使用ice/pkg{ watch: cross-env NODE_ENVdevelopment ice-pkg start, build: cross-env NODE_ENVproduction ice-pkg build, prepublishOnly: npm run build }开发期用ice-pkg start启动监听构建配合NODE_ENVdevelopment产出 dev 版本发布前prepublishOnly自动执行生产构建确保esm/目录产物与jsx-dev-runtime.js、jsx-runtime.js两个 CJS 转发入口始终同步最新代码。版本节奏方面从 packages/jsx-runtime/CHANGELOG.md 可以梳理出它的演进脉络0.1.0初始版本0.2.0允许直接使用ice/jsx-runtime并兼容 webpack 40.2.1修复对象 style 值转换不正确的问题0.3.0开发环境改用jsx-dev-runtime0.3.1为向后兼容重新导出createElement0.3.2升级swc/helpers至 0.5.17。典型使用场景小结综合文档与源码ice/jsx-runtime适合以下使用方式框架内部使用ice.js 的构建链路通过 SWCimportSource自动注入开发者无需手动 import这是最常见的形态手动指定 JSX runtime如果项目自行配置 TS 或 Babel 的 automatic runtime可将jsxImportSource指向ice/jsx-runtime即可享受统一的单位转换能力{ compilerOptions: { jsx: react-jsx, jsxImportSource: ice/jsx-runtime } }独立 npm 包使用按文档执行npm i ice/jsx-runtime --save然后从ice/jsx-runtime/jsx-runtime生产或ice/jsx-runtime/jsx-dev-runtime开发导入运行时函数多端单位换算需要rpx→vw自动换算的 H5/多端项目style对象中的字符串单位会被hijackElementProps自动处理。总结ice/jsx-runtime以薄封装、强兼容为设计哲学底层完整复用 React 官方的jsx/jsxs/jsxDEV/Fragment实现上层通过hijackElementProps注入rpx单位转换等 ice.js 体系特有的样式能力同时以createElement向后兼容与 CJS/ESM 双入口保证迁移平滑。它既是 ice.js 自动 JSX 转换链路的统一收口也是多端样式能力在运行时层面的落地点。结合 packages/jsx-runtime/tests/hijackElememt.test.ts 的测试用例你可以非常清晰地验证其行为边界并在自己的 ice.js 项目中放心依赖这套运行时。赞分享前端Web框架SSR前端构建插件系统微前端跨平台【免费下载链接】ice ice.js: The Progressive App Framework Based On React基于 React 的渐进式应用框架项目地址https://gitcode.com/gh_mirrors/ice1/ice点击查看免费下载相关推荐ice/jsx-runtime 深入解读ice.js 的 JSX 运行时实现与版本演进全解析ice/jsx runtime 深入解读ice.js 的 JSX 运行时实现与版本演进全解析 ice/jsx runtime 是 ice.js 面向 Re前端Web框架SSR前端构建插件系统微前端跨平台TOMLKit扩展开发指南如何为特定场景创建自定义插件TOMLKit扩展开发指南如何为特定场景创建自定义插件 TOMLKit是一个Style preserving的Python TOML库它允许开发者在解析和生前端Web框架SSR前端构建插件系统微前端跨平台【亲测免费】 Vue.js JSX 插件安装与使用指南Vue.js JSX 插件安装与使用指南 1. 项目目录结构及介绍 Vue.js 的 JSX 插件—— babel plugin jsx 的主要目录结构如下创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表