如何为启用SSR的Angular应用配置Stencil Web Components水合
在Angular Universal SSR中启用Stencil Web Components水合功能
核心问题分析
你当前的实现存在两个关键错误:
- 直接将
indexHtml(文件名)传入hydrate.renderToString,但该方法需要的是HTML字符串而非文件名 - 执行顺序颠倒:应先让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
相关产品推荐
相关产品推荐

