https://github.com/frontarm/create-universal-react-app
Configuration-free SSR for Create React App.
https://github.com/frontarm/create-universal-react-app
Last synced: 19 days ago
JSON representation
Configuration-free SSR for Create React App.
- Host: GitHub
- URL: https://github.com/frontarm/create-universal-react-app
- Owner: frontarm
- License: mit
- Created: 2019-08-02T03:23:28.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2022-02-26T01:41:12.000Z (about 3 years ago)
- Last Synced: 2025-03-31T06:01:33.335Z (26 days ago)
- Language: JavaScript
- Homepage:
- Size: 9.06 MB
- Stars: 126
- Watchers: 9
- Forks: 1
- Open Issues: 15
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG-0.x.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
README
๐
Create Universal React App
Configuration-free SSR for Create React App**This is a fork of Create React App. For details on Create React App itself, see the [official repository](https://github.com/facebook/create-react-app/).**
## Getting Started
### For new projects
To create a new project with SSR, just use `npm init`:
```bash
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:
```bash
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:
```js
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();
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:
```bash
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 ยป](https://github.com/jamesknelson/cura-firebase-example)**
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`:**
```json
{
"name": "app",
"main": "build/node/index.js",
"files": ["build/node/*.*"],
"scripts": {
"deploy": "firebase deploy",
"predeploy": "sh ./scripts/pack.sh"
}
}
```**`scripts/pack.sh`:**
```bash
rm functions/renderer.tgz
npm run build
mv "$(npm pack)" functions/renderer.tgz
```**`functions/package.json`:**
```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:
```js
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:
```json
{
"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](https://github.com/jamesknelson/cura-firebase-example) repository._
## The rest is just Create React App
Learn more at the [Create React App](https://facebook.github.io/create-react-app/) website.
If you'd like to understand the changes this fork makes to standard Create React App, see the [Pull Request](https://github.com/facebook/create-react-app/pull/6747).
## License
Create React App is open source software [licensed as MIT](https://github.com/facebook/create-react-app/blob/master/LICENSE).