结合React和Jade模板的使用方法

23

我正在使用express+react开发一个同构JavaScript应用。我们最初使用jade来生成静态内容的服务器端模板,但将两者结合起来变得越来越难以管理。我们最终得到了类似于这样的结果:

在express路由中:

router.get("/", function(req, res) {
  var webpackStats = require('../../config/webpack-stats.json');
  var reactHtml = React.renderToString(HiwApp({}));
  var slideshowHtml = React.renderToString(slideshowApp({}));
  var config = {
    webpackStats: webpackStats,
    reactOutput: reactHtml,
    slideshowHtml: slideshowHtml
  };
  res.render("how_it_works/howitworks", config);
});

在 Jade 中:

body
  .company-logo.center
  #react-main-mount
    != reactOutput
  include ./content_block_1.jade

  include ./content_block_2.jade

  #slideshow-main-mount
    != slideshowHtml

这很脆弱 - 如果我们想要jsx,然后是jade模板,再然后是更多的jsx,我们必须确保正确排序。

我的想法是全部使用jsx。我知道有React.renderToStaticMarkup可以解决这类问题,但这并不能解决混合动态和静态页面的问题。

最重要的问题是:如果我们决定全部使用jsx(比如包含所有组件的layout.jsx),然后调用React.renderToString(App({}),这会对性能产生重大影响吗?如果有,是否有更好的方法来轻松地组合静态和动态块?


完全可以用 React 的 renderToString 方法来渲染整个文档。尽管初始页面加载时会有一定的渲染时间,但这种时间是非常短暂的。考虑到你很可能正在构建一个单页应用程序,这实际上只是一个微不足道的问题,因为用户只会在初始页面构建时访问它一次。 - AndrewMcLagan
2个回答

6
尽管这可能有点偏题:我们坚持使用jade模板。
基本上,我们想要灵活地使用非React+flux架构来处理站点的某些部分,如果需要的话。我们的站点基本上由多个较小的SP应用程序组成:站点、用户帐户、团队和管理员。
为什么我们这样做?
- 对于不访问站点所有部分的用户来说,文件大小和开销更小。 - 如果需要,可以选择“退出”React和flux。 - 更简单的服务器端认证。

不错。你大概花了多少时间?架构的表现让你满意吗? - Ashley Coolman
10
实际上,最终我们采用了100%的React构建。后端API使用PHP编写,并通过JWT进行身份验证。 - AndrewMcLagan
好的回答,我有同样的问题,你前两个论点也在我脑海中出现了。但是:服务器端身份验证与您的模板引擎有什么关系? - Mathias Vonende
这更多关乎应用程序架构,SP应用程序中的身份验证可能会很复杂。尽管自从发布此帖子以来,React已经提供了许多选项来简化此过程。 - AndrewMcLagan

2
我们成功实现的方法是使用React.renderToStaticMarkup()在服务器上呈现JSX shell模板(Html.jsx),然后将其作为响应发送到每个服务器端的express路由请求,以便向浏览器传递一些HTML。 Html.jsx只是一个包含html头信息和GA脚本等内容的外壳,不应包含任何布局。
// Html.jsx
render(){
  return (
    <html>
      <head>
        // etc.
      </head>
      <body>
        <div
          id="app"
          dangerouslySetInnerHTML={{__html: this.props.markup}}>
        </div>
      </body>
      <script dangerouslySetInnerHTML={{__html: this.props.state}</script>
      <script>
        // GA Scripts etc.
      </script>
    </html>
  )
}

记住,在为您的应用程序进行混合时,完全可以使用dangerouslySetInnerHTML,这是非常正常的甚至推荐的做法。
动态布局应该通过基于它们的状态/属性配置的组件层次结构来完成。如果您正在使用React Router,则路由器将根据提供的路由呈现视图处理程序,因此您不需要自行管理。
我们使用这种技术的原因是将“App”与服务器端模板外壳分开,后者只是一种传递机制,实际上是样板文件。我们甚至在我们的应用程序中将Html.jsx模板与所有express组件放在一起,并且不让它与其他混合React组件混合。
我发现用于解决React/混合体系结构问题的最有用资源之一是 https://github.com/yahoo/flux-examples/tree/master/react-router ,这也是我们从中借鉴了这种技术。
我们探索了将handlebars集成为客户端未来使用我们产品的模板引擎的想法,但决定编写我们自己的JSX DSL并使用一些简单的解析例程将类似HTML的DSL解析为JSX,例如在模板的开头添加export default(ES6模块语法),然后将模板导入到渲染组件中。
当然,您可以遵循这种思路,并使用jade编译器来输出模板,然后在其周围添加模块语法,如果您认为单独的jade文件是必要的。我还注意到了这个项目,尽管我没有深入探索它: https://github.com/jadejs/react-jade

我们最终使用 react-router 为所有内容做了类似于你的 html.jsx 的东西。对于所有使用 jade 但未使用 react router 的内容,我们将其转换为 jsx,在一个节点上挂载,并没有注意到巨大的性能损失。 - johnnyutah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接