背景

前端渲染模式 章节讲到了基于 React 的一体化的前端渲染模式,好处是不需要借助第三方模板引擎且无效关注静态资源注入问题,但有两个小的功能限制:

  • layout 模板数据绑定能力较弱

  • 资源注入不能自己定义,比如 async, crossorigin 等配置

针对上面问题 egg-view-react-ssr (>=2.4.0)扩展 renderAsset 方法支持基于 asset 的前端渲染模式,方便对 layout 进行定制和数据绑定。

使用

  • renderAsset 模式默认使用 egg-view-nunjucks 模板引擎对 layout 进行数据模板编译,你需要在项目 package.json 中同时安装 egg-view-react-ssregg-view-nunjucks 插件依赖。
  1. // ${root}/package.json
  2. {
  3. "dependencies": {
  4. "egg-view-nunjucks": "^2.2.0",
  5. "egg-view-react-ssr": "^2.4.0"
  6. }
  7. }
  1. // ${root}/config/plugin.json
  2. exports.reactssr = {
  3. enable: true,
  4. package: 'egg-view-react-ssr'
  5. };
  6. exports.nunjucks = {
  7. enable: true,
  8. package: 'egg-view-nunjucks',
  9. };
  • 配置 layout.html 模板

模板默认路径:${root}/app/view/layout.html, 你可以通过 egg-view-react-ssr 的 layout 属性配置指定模板位置。

  1. **渲染上下文暴露全局 asset 对象,参数如下:**

asset.js { Array } 页面依赖的静态 JS 资源 URL 列表, 来自 config/manifest.json 具体见 资源依赖
asset.css { Array } 页面依赖的静态 JS 资源 URL 列表,来自config/manifest.json具体见 资源依赖
asset.state { Object } 页面渲染原始数据,用于 MV 框架初始化 state

以下就是基于 nunjucks 的语法的 layout 模板配置, 你可以根据指定渲染引擎编写 layout 文件。

  1. <!DOCTYPE html>
  2. <html lang='en'>
  3. <head>
  4. <title>{{title}}</title>
  5. <meta name='keywords'>
  6. <meta name='description'>
  7. <meta http-equiv='content-type' content='text/html;charset=utf-8'>
  8. <meta name='viewport' content='initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui'>
  9. <link rel='shortcut icon' href='/favicon.ico' type='image/x-icon' />
  10. {% for item in asset.css %}
  11. <link rel="stylesheet" href='{{item}}' />
  12. {% endfor %}
  13. </head>
  14. <body>
  15. <div id='app'></div>
  16. <script type="text/javascript">
  17. window.__INITIAL_STATE__ = {{ asset.state | safe }};
  18. </script>
  19. {% for item in asset.js %}
  20. <script type="text/javascript" src="{{item}}"></script>
  21. {% endfor %}
  22. </body>
  23. </html>
  • renderAsset 默认调用,使用 nunjucks 模板引擎
  1. const egg = require('egg');
  2. module.exports = class AppController extends egg.Controller {
  3. async home(ctx) {
  4. await ctx.renderAsset('app.js', { title: 'egg-react-asset' });
  5. }
  6. }
  • renderAsset 自定义模板引擎(支持两种方式, 注意要安装指定模板引擎)
  1. 可以通过 egg-view-react-ssr 的 viewEngine 配置全局渲染引擎

  2. 通过 renderAsset 的第三个参数 viewEngine 配置对应渲染引擎,只在当前渲染生效

  1. const egg = require('egg');
  2. module.exports = class AdminController extends egg.Controller {
  3. async home(ctx) {
  4. // 使用 ejs 引擎,注意项目请安装 https://github.com/eggjs/egg-view-ejs 依赖
  5. await ctx.renderAsset('admin.js', { title: 'egg-react-asset' }, { viewEngine: 'ejs' });
  6. }
  7. }

骨架项目

https://github.com/easy-team/egg-react-webpack-boilerplate/tree/feature/green/asset

参考实现

https://github.com/eggjs/egg-view-assets