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

如何为启用SSR的Angular应用配置Stencil Web Components水合

在Angular Universal SSR中启用Stencil Web Components水合功能

核心问题分析

你当前的实现存在两个关键错误:

  1. 直接将indexHtml(文件名)传入hydrate.renderToString,但该方法需要的是HTML字符串而非文件名
  2. 执行顺序颠倒:应先让Angular Universal完成页面渲染,生成包含Stencil组件标签的HTML,再用Stencil的hydrate工具处理这些标签,完成服务端组件渲染与水合准备

修正后的server.ts代码

import { promisify } from 'util';
import { hydrate } from '@stencil/core/hydrate'; // 若使用自定义组件库,替换为你的组件库hydrate路径,如'your-component-lib/hydrate'

export function app(): express.Express {
  const server = express();
  const distFolder = join(process.cwd(), 'dist/angular/browser');
  const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';

  server.engine('html', ngExpressEngine({
    bootstrap: AppServerModule,
  }));

  server.set('view engine', 'html');
  server.set('views', distFolder);

  server.get('*.*', express.static(distFolder, {
    maxAge: '1y'
  }));

  server.get('*', async (req, res) => {
    // 将res.render转为Promise形式,捕获Angular渲染后的HTML字符串
    const renderToHtml = promisify(res.render.bind(res));
    const angularRenderedHtml = await renderToHtml(indexHtml, {
      req,
      providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }]
    });

    // 使用Stencil Hydrate处理HTML,完成服务端组件渲染
    const hydratedResult = await hydrate.renderToString(angularRenderedHtml);

    // 返回处理后的最终HTML
    res.send(hydratedResult.html);
  });

  return server;
}

function run(): void {
  const port = process.env['PORT'] || 4000;
  const server = app();
  server.listen(port, () => {
    console.log(`Node Express server listening on http://localhost:${port}`);
  });
}

关键配置与注意事项

  • Stencil组件库构建配置:确保你的Stencil组件库在stencil.config.ts中配置了hydrate输出目标:
    export const config: Config = {
      outputTargets: [
        {
          type: 'dist-hydrate-script',
          dir: 'dist/hydrate'
        },
        // 其他输出目标(如dist)
      ]
    };
    
  • Angular端组件引入:在Angular应用的main.ts或app.module.ts中引入Stencil组件定义,确保客户端能识别自定义元素:
    import { defineCustomElements } from 'your-component-lib/loader';
    
    // 在bootstrap之后调用
    defineCustomElements(window);
    
  • 服务端依赖:确保服务端打包时包含了Stencil的hydrate模块,避免出现模块找不到的错误。

内容的提问来源于stack exchange,提问作者Paweł Gucio

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 15:03:07