limenius/symfony-react-sandbox

Symfony React Sandbox,探索React与Symfony的集成,实现同构或通用React渲染,并利用Webpack获得收益

安装次数: 1

依赖关系: 0

建议者: 0

安全性: 0

星标: 337

关注者: 18

分支: 77

开放问题: 31

语言:JavaScript

类型:项目

dev-master 2020-09-17 13:04 UTC

README

此沙盒提供了使用 ReactBundle 的示例,包括服务器端和客户端React渲染(通用/同构)以及与Webpack Encore配置的集成。它还提供了一个使用 LiformBundle 从Symfony表单生成json-schema的示例,并从该schema生成React表单和验证。

注意:如果你是React.js的新手,请注意,这个沙盒或捆绑包并不是使用React与Symfony的必需品。这展示了如何进行一些高级功能,如服务器端渲染、更好的表单集成、直接从Twig标签注入组件,这可能比较困难。

你可以在 http://symfony-react.limenius.com/ 上看到这个示例的实时效果

它也是一个功能齐全的Symfony应用程序,你可以将其用作新项目的骨架。

它有三个主要兴趣点

  • src/app/config 配置下的服务器端代码。
  • assets/ 下的JavaScript和CSS(SCSS)代码。
  • webpack.config.jswebpack.config.serverside.js 下的Webpack Encore配置,用于客户端和服务器端渲染。

注意,你不需要运行外部node服务器来执行服务器端渲染,因为我们使用 PhpExecJs,尽管如果需要该设置,ReactBundle也可以使其成为可能。

如果你对此感兴趣,请也查看Shakacode的 React on Rails,因为我们在这里基本上是在复制他们的出色工作。

如何运行它

要求:你需要一个最新的node版本,并且安装了Webpack(你可以使用 npm install -g webpack webpack-dev-server 安装)。

git clone https://github.com/Limenius/symfony-react-sandbox.git
cd symfony-react-sandbox
composer install
npm install # or yarn install if you use yarn

配置你的数据库,编辑 .env 并设置你的数据库名、用户和密码。然后,创建模式并加载固定数据。

bin/console doctrine:database:create --if-not-exists
bin/console doctrine:schema:create
bin/console doctrine:fixtures:load

这将使用一些美味的样本数据填充你的数据库。

为了方便,我们在 config/jwt 目录中包括了公钥和私钥。它们的密码是“potato”。当然,如果你计划在生产环境中使用此应用程序,请使用不同的密码生成新的密钥 :)。有一个名为 .env.dist 的文件,你可以将其重命名为 .env,或者将其相关部分复制到你的 .env

JWT_PRIVATE_KEY_PATH=config/jwt/private.pem
JWT_PUBLIC_KEY_PATH=config/jwt/public.pem
JWT_PASSPHRASE=potato

然后,使用Webpack热重载运行实时服务器

  • 构建服务器端react Webpack捆绑包。

    ./node_modules/.bin/encore dev --config webpack.config.serverside.js --watch

或简单地 npm run webpack-serverside

  • 在另一个终端/屏幕/tmux中,运行客户端资源的热重载Webpack服务器

    ./node_modules/.bin/encore dev-server

或简单地 npm run webpack-dev

(注意,你需要将生成的构建捆绑包加载到模板中,正如我们在这里 这样做

  • 此外,你可能还想运行Symfony服务器

    bin/console server:start

之后,访问 http://127.0.0.1:8000

为什么使用Webpack?

Webpack用于生成两个独立的JavaScript包(它们共享一些代码)。一个是用于服务器端渲染的上下文。第二个将包含您的客户端前端代码。鉴于这一点,我们可以编写Twig代码来渲染React组件,例如

{{ react_component('RecipesApp', {'props': props}) }}

它将在客户端和服务器端进行渲染。

我们已经为这两个包以及package.json依赖项(如Twitter Bootstrap等)提供了我们认为合理的默认值。请随意根据您的需求进行修改。

请注意,如果您正在将webpack.config.jswebpack.config.server.js复制到您的项目中,您很可能还需要.babelrc以有Babel预设(用于将React JSX和现代JavaScript转换为纯旧JavaScript)

为什么使用服务器端渲染?

如果您启用了服务器端渲染以及组件的客户端渲染(这是默认设置),您的React组件将由Twig直接渲染为HTML,然后,当客户端代码运行时,React将识别已渲染的HTML,并且只有在需要时才会再次渲染它。相反,它将静默地接管它,并且仅在需要时才会重新渲染。

这对于某些应用程序的SEO目的或需要爬取内容的情况(例如,Facebook爬取og:标签)至关重要,同时也非常适合快速页面加载,并为禁用JavaScript的用户提供内容(如果还有的话,或者如果您有计划构建渐进式Web应用程序)。

您可以为ReactBundle配置服务器端、客户端或两者兼而有之。有关更多信息,请参阅包文档。

它是如何工作的

当您启用客户端和服务器端渲染(这是默认设置)时,在Twig模板中使用{{ react_component('RecipesApp', {'props': props}) }}渲染React组件时,ReactBundle将渲染一个<div>,该div将作为组件的容器。

在其中,包将放置评估组件产生的所有HTML代码。它将通过调用PhpExecJs,使用由Webpack生成的服务器包作为上下文,并检索结果来实现这一点。

当您的客户端JavaScript运行时,React将找到这个<div>标签,并将其识别为渲染组件的结果。它不会再次渲染它(除非客户端代码的评估有所不同),但会接管它,并根据用户执行的操作,动态重新渲染组件。

概述

我们已经设置了一个简单的应用程序。一个带有主从视图的食谱应用程序。在src/AppBundle/Controller/RecipeController.php下的控制器操作中,您将找到两种类型的操作。

渲染Twig模板的操作。

这些操作检索将在页面上显示的食谱,并将它们作为JSON字符串传递到模板中。

/app/Resouces/views/recipe/下的Twig模板中,您将找到类似于以下代码的模板

{{ react_component('RecipesApp', {'props': props}) }}

此Twig函数由ReactBundle提供,将在服务器和客户端模式下渲染React组件RecipesApp

渲染JSON响应的操作。

这些操作充当API,并由客户端React代码在导航到其他页面时使用,而无需重新加载页面来检索所需的数据。

为了简化问题,我们在这里不使用FOSRestBundle,但请随意使用它来构建您的API。

全局公开您的React组件

为了让您的React组件能够被ReactBundle访问,您需要注册它们。为此,我们使用React On Rails的npm包(这个包也可以在Ruby世界之外使用)。

请查看assets/js/recipes/startup/registration.js文件

服务器端

import ReactOnRails from 'react-on-rails'
import RecipesApp from './RecipesApp'

ReactOnRails.register({ RecipesApp })

同构应用程序的JavaScript代码组织

请注意,在大多数情况下,您将需要在您的客户端组件及其服务器端同构组件之间共享几乎所有的代码,但是,尽管客户端代码没有意外,在服务器端,您可能需要与react-router进行一些操作,以便让它知道位置并设置路由历史。这是同构应用程序中常见的问题。您可以在互联网上找到如何操作的示例,也可以在文件assets/js/recipes/RecipesApp.js中找到。

请注意,React on Rails将一个包含属性serverSide的第二个context参数传递给根容器

export default (initialProps, context) => {

    if (context.serverSide) {
        /...
    } else {
        /...
    }

Redux示例

assets/js/recipes-redux/有一个使用Redux的运行示例,且URI为/redux/

请注意,两个版本的表现性组件是共享的,因为它们不知道Redux。

Liform示例

还有一个使用LiformBundle处理表单的示例,因此Symphony表单被序列化为json-schema,然后在React中自动生成,并且可以与生成的模式进行验证。这个想法与$form->createView()类似,但用于API。

此示例可以通过URI/admin/liform/访问。

与JWT的使用

此沙盒使用LexikJWTAuthenticationBundle在管理区域处理身份验证。

如果您不打算在私有区域使用服务器端渲染,使用JWT非常简单。然而,由于这是一个沙盒,所以是一个尝试东西的地方,我们提供了一个同时支持服务器端渲染的示例。这涉及到在登录后设置JWT令牌到一个cookie,并在加载管理面板的控制器中提取令牌和验证它。

涉及的相关代码片段可以在这里这里找到。

请注意,如果您打算复制并粘贴此沙盒并将其用于严肃的事情,您应该根据LexikJWTAuthenticationBundle的文档重新生成加密密钥。

服务器端渲染模式

此库支持两种服务器端渲染的模式

  • 使用PhpExecJs来自动检测JavaScript环境(通过终端命令调用node.js或使用V8Js PHP)并通过它运行JavaScript代码。

  • 使用外部node.js服务器(示例。它将使用一个虚拟服务器,该服务器对您的逻辑一无所知,为您渲染React。引入了更多的操作复杂性(您需要保持node服务器运行,但这并不是什么大问题)。

目前,在生产中最佳选择是使用外部服务器,因为编译V8js相当困难。然而,如果您可以编译它或您的发行版/操作系统有良好的包,如果您启用缓存(我们将在下一节中看到),这是一个非常好的选择。

缓存

如果您在config.prod.yamlconfig/packages/prod/limenius_react.yaml中添加以下配置,并且您已经安装了V8js,则此包将运行得更快

limenius_react:
    serverside_rendering:
        cache:
            enabled: true
            # name of your app, it is the key of the cache where the snapshot will be stored.
            key: "recipes_app"

在第一页渲染后,这将把JS虚拟机V8js的快照存储在缓存中,因此,在随后的访问中,您不需要再次处理整个JavaScript应用,只需要渲染您想要的特定组件。

启用缓存后,如果您更改JS应用的代码,您需要清除缓存。

致谢

本项目深受优秀的React on Rails项目启发,并使用了其JavaScript包。