首页 > 解决方案 > 作为纯客户端应用程序构建和运行 React SSR 应用程序

问题描述

我的两个应用程序(同一应用程序的 CSR 和 SSR 版本)

我使用“create-react-app”创建了一个标准的客户端渲染 (CSR) React 应用程序。这是一个仅限客户端的应用程序,整个应用程序都在浏览器中部署和运行。

我还创建了此应用程序的服务器端渲染(SSR 或通用)版本。构建此应用程序时,它会创建一个 server-bundle.js 和一个 client-bundle.js。当应用程序运行时,浏览器向服务器请求应用程序。服务器返回 HTML 和对 client-bundle.js 的引用。此客户端捆绑包在客户端浏览器中执行以“水合”现有 HTML 内容或在服务器未生成内容的客户端导航的情况下呈现整个内容。

此设计的问题

我有两个代码库,其中大部分代码、样式、组件、路由等都是相同的。如果我需要更改应用程序的一部分,我必须确保在两个代码库中进行相同的更改。

当将此代码发布给消费者时,我将不得不发布两个应用程序。

我想要什么

我想要一个可以生成 CSR 应用程序和 SSR 应用程序的代码库。

我希望能够扩展我的 SSR 应用程序中的配置,以便我可以创建一个仅限 CSR 的应用程序,例如我的“create-react-app”。这样应用程序就可以通过以下两种方式之一构建/运行:

  1. 服务器端应用程序- 服务器用于在客户端导航发生时获取客户端包以进行水合/渲染
  2. 客户端应用程序 -客户端捆绑包部署到客户端浏览器并且没有服务器运行

企业社会责任申请

应用结构

public
  index.html
src
  components
     comp1.jsx
     comp2.jsx 
     home.jsx
     page1.jsx
  styles
     styles.css
  index.jsx (contains render method containing the routes)
package.json
etc

src/index.jsx 包含

import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

import Home from './components/Home';
import Page1 from './components/Page1';

render(
  (
    <Router>
        <Switch>
          <Route exact path="/" component={Home} />
          <Route exact path="/page1" component={Page1} />
        </Switch>
    </Router>
  ),
  document.getElementById('root'),
);

要构建和运行应用程序,使用“react-scripts”。我相信“webpack-dev-server”用于为应用程序提供服务。

"build": "react-scripts build",
"start": "react-scripts start",

react-scripts 更新 index.html 以添加客户端包引用并将其移动到“build”目录中。

SSR/通用应用

应用结构

public
  index.html
src
  client
     client.jsx (entry point for the client bundle, contains ReactDOM.hydrate)
  components
     comp1.jsx
     comp2.jsx 
  pages
     home.jsx
     page1.jsx
     routes.js
  server
     renderer.jsx (creates the html to return to the client)
     server.js (entry point for the server bundle, an Express server)
  styles
     styles.css
package.json
webpack.base.config.js
webpack.client.config.js (builds the client bundle)
webpack.server.config.js (builds the server bundle)
etc

webpack.client.config.js 包含

const path = require('path');
const merge = require('webpack-merge');
const CopyPlugin = require('copy-webpack-plugin');
const webpack = require('webpack');
const baseConfig = require('./webpack.base.config.js');

const config = {
  // do not need a 'target' as this is for the browser

  entry: './src/client/client.jsx',

  output: {
    filename: 'client-bundle.js',
    path: path.resolve(__dirname, 'public'),
  },

  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(__dirname, 'src', 'styles'),
          to: path.resolve(__dirname, 'public'),
        },
      ],
    }),
    new webpack.DefinePlugin({
      'process.env.IS_BROWSER': true,
    }),
  ],
};

module.exports = merge(baseConfig, config);

src/client/client.jsx 包含

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { renderRoutes } from 'react-router-config';

import Routes from '../pages/Routes';

ReactDOM.hydrate(
  <BrowserRouter>
    <div>{renderRoutes(Routes)}</div>
  </BrowserRouter>,
  document.querySelector('#root'),
);

构建应用程序包

"build-server-bundle": "webpack --config webpack.server.config.js",
"build-client-bundle": "webpack --config webpack.client.config.js",

运行应用程序

node dist/server-bundle.js

SSR 应用程序没有“react-scripts”,因为它不是使用“create-react-app”构建的。

我在想应该可以创建一个客户端包,如“create-react-app”创建,然后只能在浏览器上运行。

有谁知道这是否可行,如果可以,该怎么做。

标签: reactjsserver-side-renderingcsr

解决方案


您可以查看以下 SSR 和 CSR 的 repo。 https://github.com/ashish03399/react-js-ssr-csr-template

此模板使用最少的第三方模块提供服务器端渲染和客户端渲染


推荐阅读