ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Stencil Mock Doc 架构解析:无浏览器环境下渲染组件的轻量 DOM 实现

Stencil Mock Doc 架构解析:无浏览器环境下渲染组件的轻量 DOM 实现 开发工具前端前端构建【免费下载链接】stencilA toolchain for building scalable, enterprise-ready component systems on top of TypeScript and Web Component standards. Stencil components can be distributed natively to React, Angular, Vue, ( more) and traditional web applications from a single, framework-agnostic codebase.项目地址https://gitcode.com/gh_mirrors/st/stencil点击查看免费下载Mock Doc 是 Stencil 编译器内置的一套轻量级 DOM 与 Web API 实现专为 Node.js 环境设计——它只实现刚刚够用的 DOM 能力让 Stencil 组件在没有真实浏览器的前提下完成服务端渲染SSR、预渲染与单元测试。本文以 docs/mock-doc.md 为骨架结合 src/mock-doc/ 目录下的真实源码逐层拆解其 Window/Document 架构、HTML 解析与序列化、事件系统、CSS 处理等核心机制并展示它如何在测试平台与 hydrate 运行时中落地帮助你理解 Stencil 组件不打开浏览器也能跑起来背后的原理以及如何在自己的工具链中复用这套 Mock DOM。一、Mock Doc 是什么解决什么问题在 Node.js 里组件代码中常见的document、window、CustomEvent、localStorage等浏览器全局对象全部不存在。Stencil 组件依赖这些 API 完成渲染、事件绑定与生命周期管理因此无论是 Jest 单元测试、stencil/core/testing的newSpecPage还是服务端预渲染prerender / hydrate都需要一个可编程的伪浏览器环境。Mock Doc 的核心定位正是如此只实现足够支撑组件渲染的最小 DOM 子集不做布局计算、不跑渲染管线、不加载异步脚本从而换取在纯 Node 进程内同步、快速、可控的渲染能力。源码位置src/mock-doc/顶层设计分三块核心对象Window/Document/Web API、DOM 实现元素与节点体系、解析与序列化字符串 ↔ DOM 树互转。二、Mock Window全局对象与浏览器 API 集合源码位置src/mock-doc/window.tsMockWindow是模拟浏览器全局对象的核心类。与文档中简化示例不同真实实现见 src/mock-doc/window.ts采用懒初始化的 getter 私有后备字段的模式location、navigator、localStorage、sessionStorage、history等均为__xxx私有字段 公开 getter/setter首次访问时才实例化对应的 Mock 类get navigator() { if (this.__navigator null) { this.__navigator new MockNavigator(); } return this.__navigator; } set navigator(nav: any) { this.__navigator nav; }其提供的浏览器能力包括能力类别提供的 API文档与视图document、window/self/top/parent/globalThis均指向自身、origin定时器setTimeout/clearTimeout/setInterval/clearInterval/requestAnimationFrame/cancelAnimationFrame/requestIdleCallback/cancelIdleCallback存储localStorage、sessionStorage均为MockStorage事件addEventListener/removeEventListener/dispatchEvent以及Event、CustomEvent、FocusEvent、KeyboardEvent、MouseEvent构造器网络与资源fetch优先转发给全局原生fetch否则抛错、Headers/Request/Response媒体查询与样式matchMedia恒返回matches: false的占位对象、getComputedStyle返回空的 CSSStyleDeclaration 占位、CSS.supports恒为true交互占位alert/confirm/prompt/open/scroll*/focus/blur等均为空实现或固定返回值视口尺寸innerWidth 1366、innerHeight 768、devicePixelRatio 1滚动偏移均为0见 resetWindowDimensions自定义元素customElementsMockCustomElementRegistry、HTMLElement/SVGElement/Element/Node/NodeList等构造器定时器的两大特殊机制超时上限约束setTimeout/setInterval在内部通过Math.min(ms ?? 0, this.__maxTimeout)把延迟钳制在__maxTimeout默认 60000ms以内见 src/mock-doc/window.ts。所有定时器 id 会被登记到__timeouts集合close()时统一清除避免 Node 进程被残留定时器卡住退出。constrainTimeouts加速模式constrainTimeouts(win)见 src/mock-doc/window.ts会把__maxTimeout设为0即 1ms 内触发并把__allowInterval设为falsesetInterval退化为只触发一次。注释明确指出这是为了让 setTimeout 仍异步但收敛到 1ms。测试场景用它显著缩短等待时间。cloneWindow 与模板复用cloneWindow 支持从已有 window 深克隆出一份新实例文档树通过documentElement.cloneNode(true)复制。这一能力是 hydrate 性能优化的基石见下文预渲染中的运用。全局环境的注入与回收MockWindow默认不污染 Node 全局对象需要显式调用 src/mock-doc/global.ts 中的工具setupGlobal(gbl)若gbl.window不存在则创建MockWindow把WINDOW_FUNCTIONS如addEventListener、getComputedStyle、requestAnimationFrame等 19 个函数绑定到全局把WINDOW_PROPS如document、localStorage、customElements等 31 个属性通过Object.defineProperty以 getter/setter 代理注入同时把GLOBAL_CONSTRUCTORSEvent、CustomEvent、DOMParser、Headers、Request、Response、ShadowRoot、HTMLInputElement等 27 个构造器挂到全局teardownGlobal(gbl)调用win.close()回收资源patchWindow(winToBePatched)把缺失的 API 逐个补丁到已存在的对象上常用于既有 window 的渐进增强。MockNavigatorsrc/mock-doc/navigator.ts与MockStoragesrc/mock-doc/storage.ts都是极简实现前者userAgent/appName等恒为MockNavigator后者基于Mapstring, string实现getItem/setItem/removeItem/clear。三、Mock Document文档对象与元素工厂源码位置src/mock-doc/document.tsMockDocument直接继承MockHTMLElement文档本身也作为一棵树节点存在构造时可传入 HTML 字符串constructor(html: string | boolean | null null, win: any null) { super(null, null); this.nodeName NODE_NAMES.DOCUMENT_NODE; this.nodeType NODE_TYPES.DOCUMENT_NODE; this.defaultView win; this.cookie ; this.referrer ; this.appendChild(this.createDocumentTypeNode()); if (typeof html string) { // 通过 parse5 解析挂载 html 根节点 } else if (html ! false) { // 创建默认结构htmlhead/headbody/body/html } }见 src/mock-doc/document.ts三种构造模式传html字符串走 parse5 解析出完整文档传false不创建 documentElement配合cloneWindow等场景clone 时手动挂载克隆树传null默认生成htmlheadbody标准骨架。head、body、documentElement、title等均实现为惰性 getter/setter访问时若不存在则动态创建并挂载到正确位置例如body不存在时会appendChild一个新的bodysrc/mock-doc/document.ts。此外还提供了cookie、referrer、baseURI读取base的href、URL代理到location.href、location代理到defaultView.location等文档级属性以及便捷集合属性styleSheets/scripts/forms/images内部基于querySelectorAll。元素工厂与自定义元素createElement(tagName)是元素体系的分发入口src/mock-doc/element.ts先把标签名转小写并做合法性校验/^[a-z0-9-_:]$/i再按标签分派到专用类switch (tagName) { case a: return new MockAnchorElement(ownerDocument); case base: return new MockBaseElement(ownerDocument); case button: return new MockButtonElement(ownerDocument); case canvas: return new MockCanvasElement(ownerDocument); case form: return new MockFormElement(ownerDocument); case img: return new MockImageElement(ownerDocument); case input: return new MockInputElement(ownerDocument); case label: return new MockLabelElement(ownerDocument); case link: return new MockLinkElement(ownerDocument); case meta: return new MockMetaElement(ownerDocument); case script: return new MockScriptElement(ownerDocument); case slot: return new MockSlotElement(ownerDocument); case style: return new MockStyleElement(ownerDocument); case template: return new MockTemplateElement(ownerDocument); case title: return new MockTitleElement(ownerDocument); case ul: return new MockUListElement(ownerDocument); }关键分支当标签名包含连字符tagName.includes(-)且ownerDocument.defaultView.customElements存在时会调用createCustomElement创建自定义元素见 src/mock-doc/element.ts这是 Stencil 组件在 Mock DOM 中能被实例化的关键通道。createElementNS则处理命名空间XHTML 走createElementSVG 命名空间会按标签返回MockSVGElement及其子类text/path/rect/svg等见 src/mock-doc/element.ts。MockDocument还实现了createComment、createAttribute/createAttributeNS、createTextNode、createDocumentFragment、createDocumentTypeNode以及深度优先递归查找的getElementByIdsrc/mock-doc/document.ts和getElementsByName。四、元素体系基础元素、专用元素与属性模型基础元素 MockElement / MockHTMLElement源码位置src/mock-doc/node.tsMockNode、MockElement、MockHTMLElement同文件基础元素以MockNode为根。MockNode持有nodeName、nodeType、ownerDocument、parentNode与私有_childNodes数组并提供childNodes/firstChild/lastChild等访问器、append/prepend自动把字符串包装为文本节点等便捷方法、isConnected沿parentNode链向上查找DOCUMENT_NODE见 src/mock-doc/node.ts以及树操作。MockElement的属性模型基于MockAttributeMapsrc/mock-doc/attribute.ts提供getAttribute/setAttribute/removeAttribute/hasAttribute/toggleAttribute等标准 API并支持attributes具名集合。核心的setAttribute在写入/移除后都会触发attributeChanged回调从而联动自定义元素注册表与属性监听见 src/mock-doc/custom-element-registry.ts 中的attributeChanged/connectNode/disconnectNode。专用元素Specialized Elements不同标签的专用类通过patchPropAttributes声明式属性反射机制实现——把属性名 ↔ 反射类型String/Number/Boolean映射到原型上自动生成 getter/setter例如patchPropAttributes( MockInputElement.prototype, { accept: String, autocomplete: String, autofocus: Boolean, capture: String, ... }, { type: text }, // 默认值 );见 src/mock-doc/element.ts。这样input的value、checked、type、disabled等属性既可通过element.getAttribute(value)读取也可通过element.value直接赋值且赋值会同步写回属性type默认值为text。注意原文档中MockInputElement私有_value/_checked并派发事件的示例是简化示意真实实现src/mock-doc/element.ts以patchPropAttributes属性反射为主并额外实现了list按list属性查getElementById与labels等表单辅助。MockAnchorElement的href走fullUrl解析相对地址基于document.baseURI拼成绝对 URL并提供pathname等 Location 片段MockImageElement的src同样做完整 URL 解析draggable默认true。Shadow DOM 支持attachShadow返回MockShadowRootsrc/mock-doc/shadow-root.ts继承自MockDocumentFragment提供host、mode恒为open、delegatesFocusfalse、activeElement/fullscreenElementnull等占位属性。MockTemplateElement则通过content持有文档片段与 parse5 的setTemplateContent/getTemplateContent配合见下文解析器。五、节点树操作插入、移除与生命周期回调源码位置src/mock-doc/node.tsMockNode提供标准的 DOM 树操作。以appendChild为例src/mock-doc/node.tsappendChild(newNode: MockNode) { if (newNode.nodeType NODE_TYPES.DOCUMENT_FRAGMENT_NODE) { // 文档片段将其所有子节点逐一转移 const nodes newNode.childNodes.slice(); for (const child of nodes) { this.appendChild(child); } } else { newNode.remove(); // 先脱离原父节点 newNode.parentNode this; this.childNodes.push(newNode); connectNode(this.ownerDocument, newNode); // 触发自定义元素 connectedCallback } return newNode; }insertBefore、removeChild、remove遵循同样的先摘除旧父节点 → 挂新父节点 → 触发connectNode/disconnectNode回调的契约。connectNode/disconnectNode实现在 src/mock-doc/custom-element-registry.ts 中负责把元素与MockCustomElementRegistry中注册的自定义元素类绑定并在节点挂载/卸载时调用connectedCallback/disconnectedCallback——这正是组件生命周期在 Mock DOM 中得以运转的底层机制。isConnected则沿父链判断节点是否已挂载到文档。六、HTML 解析器基于 parse5 的 TreeAdapter 集成源码位置src/mock-doc/parse-html.ts、src/mock-doc/parse-util.ts原文档中的MockHTMLParser属简化示意真实实现并不自研 tokenizer而是复用 HTML5 规范解析器parse5通过自定义TreeAdapter把解析结果映射到 Mock DOM 节点src/mock-doc/parse-util.ts。TreeAdapter的关键适配点createElement(tagName, namespaceURI, attrs)调用ownerDocument.createElementNS创建节点XHTML 命名空间属性走setAttribute其余走setAttributeNSinsertText/insertTextBefore与相邻文本节点合并避免产生碎片化文本节点setTemplateContent/getTemplateContent维护template的content文档片段setDocumentType把!DOCTYPE信息存入文档首个DOCUMENT_TYPE_NODEsetDocumentMode/getDocumentMode记录 quirks 模式x-mode各类isXxxNode基于nodeType常量判定节点类型。对外暴露两个入口src/mock-doc/parse-html.tsexport function parseHtmlToDocument(html: string, ownerDocument: MockDocument null) { ... } export function parseHtmlToFragment(html: string, ownerDocument: MockDocument null) { ... }两者都支持共享文档缓存未显式传入ownerDocument时复用模块级sharedDocument降低反复解析的开销。节点类型常量定义在 src/mock-doc/constants.tsELEMENT_NODE 1…DOCUMENT_FRAGMENT_NODE 11与标准一致。七、HTML 序列化器DOM 树还原为 HTML 字符串源码位置src/mock-doc/serialize-node.tsserializeNodeToHtml(node, options)是 DOM → HTML 的出口src/mock-doc/serialize-node.ts先经normalizeSerializationOptions归一化选项再遍历子节点拼接。核心实现是生成器streamToHtml以分块 yield的方式输出因此同时支撑同步序列化与流式输出Readable.from。真实选项集比原文档更丰富normalizeSerializationOptionssrc/mock-doc/serialize-node.ts中的默认值如下选项默认值说明outerHtmlfalse为true时只序列化节点自身类似outerHTML否则序列化其子节点prettyHtmlfalse是否输出带缩进换行的美化 HTMLindentSpaces0美化时2缩进空格数newLinesfalse美化时true是否输出换行pre、textarea等空白敏感节点内自动跳过approximateLineWidth-1近似行宽约束removeEmptyAttributestrue移除空属性removeAttributeQuotesfalse移除属性引号removeBooleanAttributeQuotesfalse移除布尔属性引号removeHtmlCommentsfalse移除 HTML 注释serializeShadowRootdeclarative-shadow-domShadow Root 的序列化策略fullDocumenttrue为true序列化完整文档否则只序列化body子节点excludeTags无排除指定标签序列化时 Shadow Root 节点使用内部标记标签mock:shadow-rootsrc/mock-doc/serialize-node.ts并在serializeShadowRoot: declarative-shadow-dom策略下输出声明式 Shadow DOMtemplate shadowrootmodeopen保证服务端产物可在客户端直接升级为真实 Shadow DOM。输出收集采用字符串分块数组text: []join()而非逐字符拼接规避长字符串拼接的性能陷阱——这正是文档String Building 优化在真实源码中的落地形式。八、事件系统捕获、目标与冒泡三阶段源码位置src/mock-doc/event.tsMockEvent及其子类MockCustomEvent、MockUIEvent、MockFocusEvent、MockKeyboardEvent、MockMouseEvent定义在 src/mock-doc/event.ts构造时用Object.assign(this, eventInitDict)合并初始化字典。MockEvent提供preventDefault、stopPropagation、stopImmediatePropagation与composedPath()沿parentElement链向上收集遇到HTML根时切换到ownerDocument最后把defaultViewwindow也压入路径见 src/mock-doc/event.ts。事件注册/分发实现在同一文件的函数中src/mock-doc/event.tsaddEventListener把MockEventListener(type, handler)存入目标对象的__listeners数组removeEventListener按typehandler精确移除resetEventListeners清空。分发逻辑dispatchEvent遵循标准 DOM 流程捕获阶段从事件路径顶端向下走到目标目标阶段触发目标自身监听器冒泡阶段若event.bubbles为真且未stopPropagation沿路径向上逐层触发返回!event.defaultPrevented。stopPropagation通过设置cancelBubble true生效triggerEventListener会先检查cancelBubble再执行回调同时维护ev.currentTarget。MockWindow自身也实现了addEventListener/dispatchEvent/removeEventListener把事件系统扩展到 window 对象。九、CSS 实现样式表、样式声明与计算样式MockCSSStyleSheet源码位置src/mock-doc/css-style-sheet.tsMockCSSStyleSheet以cssRules: MockCSSRule[]承载规则MockCSSRule仅记录cssText与type。核心 APIinsertRule(rule, index 0)越界索引自动收敛到[0, cssRules.length]插入后通过updateStyleTextNode(ownerNode)回写style文本节点deleteRule(index)合法索引内删除并回写replaceSync(cssText)以按}切分再补回的朴素策略整体替换规则集。MockStyleElement的innerHTMLgetter/setter 即委托给getStyleElementText/setStyleElementTextsrc/mock-doc/css-style-sheet.ts把样式文本同步到子文本节点。MockCSSStyleDeclaration源码位置src/mock-doc/css-style-declaration.tsMockCSSStyleDeclaration内部用Mapstring, string保存样式setProperty(prop, value)通过jsCaseToCssCase把驼峰转为连字符形式如backgroundColor→background-color空值即删除getPropertyValue反向查找cssTextgetter 拼成prop: value;序列setter 按;/:切分解析。element.style即该类的实例。计算样式的边界原文档中getComputedStyle会做内联样式 样式表规则合并的复杂计算真实实现则保守得多MockWindow.getComputedStylesrc/mock-doc/window.ts返回一个属性均为空值/空串的CSSStyleDeclaration占位对象。这是刻意的取舍——Mock Doc 明确不做完整 CSSOM避免为布局语义背负过重成本组件若依赖getComputedStyle做视觉判定在 Mock 环境中需自行降级。选择器基于 jQuery 的 querySelectorAllquerySelector/querySelectorAll/matches的实现位于 src/mock-doc/selector.ts底层复用third-party/jquery仓库自带裁剪版的jQuery.findselectAll全量匹配、selectOne取首个、matches判断命中。同时维护了PROBLEMATIC_SELECTORS [:scope, :where, :is]清单——这些选择器在 jQuery 中支持不佳属于已知边界。十、在测试平台中的运用Jest 单元测试的浏览器Mock Doc 是 Stencil 测试基础设施的地基测试窗口注入src/testing/platform/testing-window.ts 只有一行核心逻辑——export const win setupGlobal(global) as Window;把完整 Mock 环境装进 Node 全局Jest 框架装配src/testing/jest/jest-28/jest-setup-test-framework.ts 在jestSetupTestFramework()中调用setupGlobal(global)与setupMockFetch(global)并为每个用例注入beforeEachresetPlatform、清空 mode 解析链与afterEach清空 body 下的节点、触发disconnectedCallback、销毁 window保证用例间互不污染stencil/core/mock-doc的MockDocument、MockNode、MockWindow、setupGlobal、teardownGlobal都被直接引用组件测试newSpecPage等stencil/core/testingAPI见 src/testing/index.ts构建在MockWindow之上让组件渲染、connectedCallback、事件冒泡等行为在纯 Node 中可断言。Mock Doc 自身也配有完善的测试套件见 src/mock-doc/test/覆盖attribute、element、event、html-parse、serialize-node、selector、shadow-dom-event-bubbling、custom-elements、css-style-sheet、document-fragment、storage、location、match-media、request-response、global、dataset、token-list、clone、headers等 21 个维度。文档示例对应的典型用法如下const doc new MockDocument(); const div doc.createElement(div); expect(div.tagName).toBe(DIV); expect(div.ownerDocument).toBe(doc); const parsed new MockDocument(div idtestHello/div); expect(parsed.getElementById(test).textContent).toBe(Hello); const button doc.createElement(button); let clicked false; button.addEventListener(click, () (clicked true)); button.click(); expect(clicked).toBe(true);十一、在服务端渲染SSR / 预渲染中的运用Mock Doc 同样构成 Stencil 预渲染与 hydrate 的运行时基础窗口创建与克隆src/hydrate/runner/create-window.ts 实现createWindowFromHtml(templateHtml, uniqueId)首次以new MockWindow(templateHtml)解析模板并缓存为templateWindow后续请求通过cloneWindow深度克隆——解析一次、克隆多次避免每次渲染都重新解析模板 HTML文档解析入口src/hydrate/runner/render.ts 中hydrateDocument接收字符串时直接new MockWindow(doc)接收真实Document时则走patchDomImplementation(doc, opts)修补序列化出口渲染完成后serializeDocumentToStringsrc/hydrate/runner/render.ts把serializeNodeToHtml的各类选项prettyHtml、removeAttributeQuotes、serializeShadowRoot等与HydrateFactoryOptions一一对接产出最终 HTML 字符串streamToStringrenderToString(html, options, true)则返回Readable流配合生成器实现边渲染边吐字节渲染生命周期render()中会先执行beforeHydrate钩子、设置 mode 解析链最终由afterHydrate完成inspectElement收集诊断、清理未用样式removeUnusedStyles、设置title、可选移除脚本removeScripts、写入 canonical link 与 meta charset最后destroyWindow回收 Mock 环境src/hydrate/runner/render.ts。十二、性能优化手段Mock Doc 的性能设计贯穿于源码各处字符串分块拼接序列化输出统一收集进text: string[]数组再join()避免长字符串的重复复制src/mock-doc/serialize-node.ts解析器共享parseHtmlToDocument/parseHtmlToFragment复用模块级sharedDocument作为默认 ownergetParser以WeakMap缓存每个文档的 parse5 TreeAdapter 配置src/mock-doc/parse-util.ts模板窗口克隆hydrate 场景一次解析、多次克隆显著降低重复解析开销src/hydrate/runner/create-window.ts定时器收敛constrainTimeouts把异步等待压缩到毫秒级加速测试src/mock-doc/window.ts惰性初始化location/navigator/storage/history等对象首次访问才创建__xxx私有字段避免构造开销。十三、限制与浏览器差异以下能力Mock Doc 明确不实现文档声明且与源码边界一致布局计算getBoundingClientRect等几何信息Canvas 渲染媒体元素audio/video 的实际解码播放Intersection Observer 的真实观察逻辑src/mock-doc/intersection-observer.ts 仅为占位类MockWindow仍暴露IntersectionObserver构造器以避免组件直接崩溃Mutation Observer完整 CSSOMgetComputedStyle返回空占位异步脚本加载script不执行简化的事件循环与定时器模型无渲染管线无样式计算、无重排重绘与真实浏览器的差异点还包括matchMedia恒不命中、CSS.supports恒为真、requestIdleCallback立即以 0ms 触发、navigator恒为MockNavigator、location.href基于http://mockdoc.stenciljs.com基准 URL 解析相对地址src/mock-doc/location.ts。实用建议编写组件时应避免依赖上述能力做关键逻辑如需真实布局或媒体能力应改用浏览器端 e2e 测试如 Stencil 测试套件中的 WebdriverIO 用例见 test/wdio/。十四、小结与延伸阅读Mock Doc 的设计哲学是克制的最小实现 精准的接缝对齐对组件渲染必需的标准 DOM/Web API 尽量对齐节点树、属性、事件三阶段传播、自定义元素生命周期、Shadow DOM 基础结构、parse5 全规范 HTML 解析对布局、渲染、媒体等重能力明确放弃并以setupGlobal/patchWindow提供了灵活的全局注入方式。理解这套边界既能帮你写好 Stencil 组件的单元测试与 SSR 兼容代码也能为自研 Node 端 DOM 工具提供参考。想继续深入可以依次阅读完整实现src/mock-doc/约 30 个模块覆盖 DOM/事件/CSS/存储/请求响应等对外导出清单src/mock-doc/index.tsMockDocument、MockWindow、parseHtmlToDocument、serializeNodeToHtml、setupGlobal等测试用例src/mock-doc/test/测试平台接入src/testing/platform/testing-window.ts、src/testing/jest/预渲染接入src/hydrate/runner/create-window.ts、src/hydrate/runner/render.ts文档源码docs/mock-doc.md赞分享开发工具前端前端构建【免费下载链接】stencilA toolchain for building scalable, enterprise-ready component systems on top of TypeScript and Web Component standards. Stencil components can be distributed natively to React, Angular, Vue, ( more) and traditional web applications from a single, framework-agnostic codebase.项目地址https://gitcode.com/gh_mirrors/st/stencil点击查看免费下载相关推荐在手机上复活 FlashRuffle Android 移植完整指南在手机上复活 FlashRuffle Android 移植完整指南 初中物理课那份课件还躺在旧 U 盘里手机上打不开吗Ruffle 是一款用 Rust音视频Marko客户端渲染浏览器环境下的组件初始化终极指南Marko客户端渲染浏览器环境下的组件初始化终极指南 Marko是一款基于HTML的声明式语言让Web应用构建变得轻松有趣。在浏览器环境中Marko的组件前端后端Web框架Marko渲染器终极指南掌握不同环境下的高性能渲染实现Marko渲染器终极指南掌握不同环境下的高性能渲染实现 Marko渲染器 是现代Web开发中实现高性能应用的关键技术。作为一款声明式的HTML based语言前端后端Web框架创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表