You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

不传递wires的同构hyperHTML组件:跨端模块共享问题

Isomorphic HyperHTML Component Solution

Awesome question! Let's get your hyperHTML components running smoothly both client-side and server-side as an isomorphic module. The key issue here is that hyperHTML's wire method is built for client-side DOM binding, while server-side rendering needs raw HTML strings instead of DOM nodes. Here's a clean, maintainable fix:

Step 1: Abstract Rendering Logic for Cross-Environment Compatibility

First, we'll create a tiny utility to detect the environment and return the right hyperHTML renderer—either the client-side wire for DOM binding or the server-side ssr function for string generation. This keeps our component logic DRY and environment-agnostic.

Step 2: Refactor Your Components

Here's the updated component.js that works everywhere:

// component.js
import hyperHTML from 'hyperhtml';

// Utility to get the correct renderer based on environment
const getRenderer = (target) => {
  // Detect if we're running on the server (no window object)
  const isServer = typeof window === 'undefined';
  
  if (isServer) {
    // Server-side: return a new SSR renderer each time to avoid cross-request pollution
    return hyperHTML.ssr();
  } else {
    // Client-side: use hyperHTML's wire for DOM binding
    return hyperHTML.wire(target);
  }
};

export function ListItem(item) {
  const html = getRenderer(item);
  
  function render() {
    return html`<li>${item.foo}</li>`;
  }
  
  return render();
}

export function List(items) {
  const html = getRenderer(items);
  
  function render() {
    // On server: maps to string array, which hyperHTML will concatenate
    // On client: maps to DOM nodes, which hyperHTML will mount
    return html`<ul>${items.map(ListItem)}</ul>`;
  }
  
  return render();
}

Step 3: Usage Examples

Server-Side (Node.js)

When rendering on the server, the components return raw HTML strings that you can send in HTTP responses:

// server.js
import { List } from './component.js';

// Sample data
const items = [{ foo: 'First Item' }, { foo: 'Second Item' }, { foo: 'Third Item' }];

// Generate full page HTML
const pageHTML = `
  <!DOCTYPE html>
  <html>
    <body>
      <h1>My Isomorphic List</h1>
      ${List(items)}
    </body>
  </html>
`;

// Send to client (e.g., via Express)
// res.send(pageHTML);

Client-Side

On the browser, the components return live DOM nodes that you can mount directly into the page—plus hyperHTML's automatic DOM diffing works as expected for updates:

// client.js
import { List } from './component.js';

const items = [{ foo: 'First Item' }, { foo: 'Second Item' }];
const listElement = List(items);

// Mount to the DOM
document.getElementById('app').appendChild(listElement);

// Later, if you update items, hyperHTML will efficiently update the DOM
// (Just re-call List with updated items and re-mount, or use hyperHTML's state patterns)

Key Notes to Avoid Pitfalls

  • Server-Side Cleanup: We create a new ssr renderer every time to prevent cross-request state leaks—critical for server scalability.
  • Client-Side Reactivity: The client-side code retains hyperHTML's full reactive capabilities, so your components will update efficiently when data changes.
  • Tooling: If you're using a bundler like Webpack or Rollup, make sure it correctly tree-shakes the hyperHTML code (most modern bundlers handle this automatically for isomorphic modules).

内容的提问来源于stack exchange,提问作者László Balogh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:25:11