create-universal-react-app

Configuration-free SSR for Create React App.

  • 所有者: frontarm/create-universal-react-app
  • 平台:
  • 许可证: MIT License
  • 分类:
  • 主题:
  • 喜欢:
    0
      比较:

Github星跟踪图

This is a fork of Create React App. For details on Create React App itself, see the official repository.

Getting Started

For new projects

To create a new project with SSR, just use npm init:

npm init universal-react-app my-ssr-app

Alternatively, you can use plain old create-react-app with a --react-scripts universal-react-scripts option:

create-react-app my-ssr-app --scripts-version universal-react-scripts

Either way, you'll get the standard Create React App template with one extra file: src/index.node.js (which is where you'll handle server side rendering).

For existing projects

In your package.json, just change the react-scripts dependency to universal-react-scripts. You can leave the occurences of react-scripts in the scripts object as is. Then, re-run yarn install or npm install, and add a src/index.node.js file:

import fs from 'fs';
import React from 'react';
import { renderToString } from 'react-dom/server';
import './index.css';
import App from './App';

const renderer = async (request, response) => {
  // The index.html file is a template, which will have environment variables
  // and bundled scripts and stylesheets injected during the build step, and
  // placed at the location specified by `process.env.HTML_TEMPLATE_PATH`.
  //
  // To customize the rendered HTML, you can add other placeholder strings,
  // and replace them within this function -- just as %RENDERED_CONTENT% is
  // replaced. Note however that if you name the placeholder after an
  // environment variable available at build time, then it will be
  // automatically replaced by the build script.
  let template = fs.readFileSync(process.env.HTML_TEMPLATE_PATH, 'utf8');
  let [header, footer] = template.split('%RENDERED_CONTENT%');
  let body = renderToString(<App />);
  let html = header + body + footer;
  response.send(html);
};

export default renderer;

Your app will now call the function exported by src/index.node.js to render its HTML.

Note: if you encounter any build errors after making this change, try deleting your node_modules and reinstalling them from scratch.

Build output

Universal React Scripts outputs two versions of your app: a browser version, and a node version. The node version is just a common-js version of index.node.js, which you can import in your express app or serverless function to handle server side rendering.

serve script

Universal React Scripts includes a serve script for testing your build output:

npm run serve

# or

yarn serve

This launches a server for the content in the build folder, and when a index.node.js file exists, it loads the Node bundle and server the app with server rendering.

Server Rendering with Serverless / Cloud Functions

CURA can be used to do serverless SSR -- for example, using Firebase Functions. To get this working, you'll need to package up the files in build/node and then call them within your serverless function.

With Firebase Functions

See the example repository with routes, react-helmet and styled-components »

You can create a package with your app's commonjs code by setting the name, files and main fields in your app's package.json. Once the package is configured correctly, you'll be able to use npm pack to create a tgz file that can be added as a dependency to your functions package.json -- which can be automated by adding a bash script as a predeploy step.

Changes to package.json:

{
  "name": "app",
  "main": "build/node/index.js",
  "files": ["build/node/*.*"],
  "scripts": {
    "deploy": "firebase deploy",
    "predeploy": "sh ./scripts/pack.sh"
  }
}

scripts/pack.sh:

rm functions/renderer.tgz
npm run build
mv "$(npm pack)" functions/renderer.tgz

functions/package.json:

{
  "optionalDependencies": {
    "app": "./renderer.tgz"
  }
}

The result of these three files is that each time you call yarn deploy or npm run deploy, a version of your app's index.node.js file will be built, packaged, and then made available to your firebase functions. You can then import it and use it as so:

const admin = require('firebase-admin');
const functions = require('firebase-functions');

admin.initializeApp();

let renderer;
if (process.env.NODE_ENV === 'production') {
  // Load the renderer from the packaged version when deploying
  renderer = require('app').default;
} else {
  // Load the renderer directly from the build directory during development.
  // Note: the renderer is not used in development as CURA includes its own
  // renderer, but the functions emulator fails without this.
  renderer = require('../build/node').default;
}

exports.renderer = functions.https.onRequest(renderer);

Finally, if you're using Firebase Hosting, you'll need to configure it to route all non-static requests to the renderer function. Here's what the resulting firebase.json looks like:

{
  "hosting": {
    "public": "build/web",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "rewrites": [
      {
        "source": "**",
        "function": "renderer"
      }
    ]
  }
}

You can see an example of this setup, along with async routing, styled components and react-helmet, at the cura-firebase-example repository.

The rest is just Create React App

Learn more at the Create React App website.

If you'd like to understand the changes this fork makes to standard Create React App, see the Pull Request.

License

Create React App is open source software licensed as MIT.

主要指标

概览
名称与所有者frontarm/create-universal-react-app
主编程语言JavaScript
编程语言JavaScript (语言数: 6)
平台
许可证MIT License
所有者活动
创建于2019-08-02 03:23:28
推送于2022-02-26 01:41:12
最后一次提交2019-11-06 11:54:17
发布数196
最新版本名称universal-react-scripts@3.2.1 (发布于 2019-11-06 11:54:18)
第一版名称create-react-app@1.3.3 (发布于 2017-06-29 19:03:42)
用户参与
星数126
关注者数8
派生数1
提交数2.4k
已启用问题?
问题数7
打开的问题数3
拉请求数0
打开的拉请求数12
关闭的拉请求数8
项目设置
已启用Wiki?
已存档?
是复刻?
已锁定?
是镜像?
是私有?