-
-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5445930
commit 5961afc
Showing
7 changed files
with
268 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
id: code-splitting | ||
title: Code Splitting | ||
--- | ||
|
||
CRA Universal supports code-splitting with SSR using [loadable-components](https://github.com/smooth-code/loadable-components). Please see `./packages/demo` for example. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
--- | ||
id: deployment | ||
title: Deployment | ||
--- | ||
|
||
Here are some deployment services you can try: | ||
|
||
These tutorials assumed that you've build your app using `cra-universal build` | ||
|
||
### [Now by Zeit](https://zeit.co/now) | ||
- Edit `package.json`, remove `build`, and `test` scripts | ||
- and update your npm `start` script to `node build/bundle.js` | ||
- Run command `now` inside `./dist` | ||
- Optional: you might need to remove your sourcemaps for free plan | ||
|
||
___ | ||
|
||
### [Firebase Functions by Google](https://firebase.google.com) | ||
https://medium.com/@antonybudianto/server-side-rendering-with-react-and-firebase-functions-cd67fdb2b605 | ||
- Copy `./dist` inside your `./functions/` and rename it to `./functions/server` | ||
- Update your rewrite on `firebase.json` | ||
```json | ||
{ | ||
"source": "**", | ||
"function": "app" | ||
} | ||
``` | ||
- Update your `webpack.config.js` | ||
```js | ||
module.exports = { | ||
// For Firebase function/package bundle | ||
entry: './src/app.js', // Initially, it's ./src/index.js | ||
``` | ||
- Update your `index.js` | ||
```js | ||
const functions = require('firebase-functions'); | ||
|
||
// Copy your `dist` into here and rename it into `server` | ||
const app = require('./server/build/bundle'); | ||
|
||
exports.app = functions.https.onRequest(app); | ||
``` | ||
- Add your server dependencies into your function `package.json` | ||
- Remove `./build/index.html` (let firebase function serve it) | ||
- Deploy using Firebase CLI `firebase deploy` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
--- | ||
id: integrate-react-router | ||
title: Integrate React Router | ||
--- | ||
|
||
This is how you integrate [React Router](https://github.com/ReactTraining/react-router) into server side rendering: | ||
|
||
```js | ||
// server/app.js | ||
|
||
// you can use `async` function too | ||
function handleUniversalRender(req, res) { | ||
const context = {}; | ||
const stream = ReactDOMServer.renderToNodeStream( | ||
<StaticRouter location={req.url} context={context}> | ||
<App /> | ||
</StaticRouter> | ||
); | ||
|
||
if (context.url) { | ||
res.redirect(301, context.url); | ||
return; | ||
} | ||
|
||
return stream; | ||
} | ||
|
||
const app = createReactAppExpress({ | ||
clientBuildPath, | ||
universalRender: handleUniversalRender | ||
}); | ||
``` | ||
|
||
**Note:** Make sure `App.js` didn't render `BrowserRouter`, but put it on `src/index.js` or outer files | ||
|
||
```js | ||
// src/index.js | ||
|
||
ReactDOM.hydrate( | ||
<BrowserRouter> | ||
<App /> | ||
</BrowserRouter>, | ||
document.getElementById('root') | ||
); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
--- | ||
id: integrate-redux | ||
title: Integrate Redux | ||
--- | ||
|
||
```jsx | ||
// src/index.js | ||
|
||
// Grab the state from a global variable injected into the server-generated HTML | ||
const preloadedState = window.__PRELOADED_STATE__ | ||
|
||
// Allow the passed state to be garbage-collected | ||
delete window.__PRELOADED_STATE__ | ||
|
||
const store = createStore( | ||
reducer, | ||
preloadedState, | ||
applyMiddleware(thunk) | ||
) | ||
``` | ||
|
||
```js | ||
// server/src/app.js | ||
|
||
import path from "path"; | ||
import React from "react"; | ||
import { renderToNodeStream } from "react-dom/server"; | ||
import { Provider } from "react-redux"; | ||
import { createReactAppExpress } from "@cra-express/core"; | ||
|
||
import App from "../../src/App"; | ||
import configureStore from "../../src/store/index.js"; | ||
const clientBuildPath = path.resolve(__dirname, "client"); | ||
|
||
function handleUniversalRender(req, res) { | ||
const initialState = {}; | ||
const store = configureStore(initialState); | ||
const stream = renderToNodeStream( | ||
<Provider store={store}> | ||
<App /> | ||
</Provider> | ||
); | ||
return stream; | ||
} | ||
|
||
const app = createReactAppExpress({ | ||
clientBuildPath, | ||
universalRender: handleUniversalRender, | ||
onFinish(req, res, html) { | ||
const state = store.getState(); | ||
const finalHtml = html.replace('{{SCRIPT}}', `<script> | ||
window.__PRELOADED_STATE__ = ${JSON.stringify(state).replace(/</g, '\\u003c')}; | ||
</script>`); | ||
return finalHtml; | ||
} | ||
}); | ||
|
||
module.exports = app; | ||
``` | ||
|
||
References: | ||
https://redux.js.org/recipes/server-rendering |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
--- | ||
id: integrade-typescript | ||
title: Integrate TypeScript | ||
--- | ||
|
||
> Credits: @Zummer | ||
```javascript | ||
// package.json | ||
"scripts": { | ||
"u-init": "cra-universal init" | ||
} | ||
``` | ||
|
||
Extract server folder for customization | ||
```sh | ||
npm run u-init | ||
``` | ||
|
||
Install required dep: | ||
```sh | ||
npm install -D webpack-merge ts-loader | ||
``` | ||
|
||
Create crau.config.js in cra root folder | ||
``` | ||
touch crau.config.js | ||
``` | ||
|
||
```javascript | ||
// crau.config.js | ||
const webpackMerge = require('webpack-merge'); | ||
|
||
const myCustomConfig = { | ||
resolve: { | ||
extensions: ['.ts', '.tsx'] | ||
}, | ||
module: { | ||
rules: [ | ||
{ | ||
test: /\.(ts|tsx)$/, | ||
exclude: [/node_modules/], | ||
use: [ | ||
{ | ||
loader: 'ts-loader' | ||
} | ||
] | ||
}, | ||
] | ||
} | ||
}; | ||
|
||
module.exports = { | ||
webpackPlugins: [], | ||
modifyWebpack: (config) => webpackMerge(config, myCustomConfig) | ||
}; | ||
``` | ||
|
||
``` javascript | ||
// tslint.json | ||
{ | ||
... | ||
"rules": { | ||
"no-console": false | ||
} | ||
} | ||
``` | ||
|
||
```javascript | ||
// tsconfig.json | ||
{ | ||
"compilerOptions": { | ||
... | ||
"rootDirs": ["src", "server"], | ||
... | ||
}, | ||
"exclude": [ | ||
"server-build", | ||
... | ||
] | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
--- | ||
id: known-issues | ||
title: Known Issues | ||
--- | ||
|
||
List of known issues: | ||
- Importing svg/img file will cause runtime warning on development (asset import didn't re-hydrate properly due filename mismatch), but the errors are gone after production build | ||
- Solution: https://github.com/antonybudianto/cra-universal/issues/16#issuecomment-392305234 | ||
- Latest React Loadable `v5.x.x` is not compatible, for now please stick to version `v4.x.x` or use [loadable-components](https://github.com/smooth-code/loadable-components) | ||
- Using renderToNodeStream limits you to: | ||
- render helmet on server | ||
- isomorphic css | ||
- sending custom status code based on app router context | ||
- If you enabled Service worker, it's expected to see non-rendered page when viewing the page source (somehow page source will show SW-cached page). You can use curl to check the rendered page | ||
- Fetching data based on route is on Alpha stage, please visit [@cra-express/redux-prefetcher](https://github.com/antonybudianto/create-react-app-express/tree/master/packages/redux-prefetcher) | ||
|
||
If you've ideas on how to solve the issue, please discuss or send a PR! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
--- | ||
id: prefetching | ||
title: Prefetching | ||
--- | ||
|
||
## Introduction | ||
|
||
One advantage being an SSR app is the ability to fetch from server instead of client. Imagine you want to fetch the article on the server so that the Googlebots/crawlers able to crawl and index your page. | ||
It's good for pages which are best rendered on server. | ||
|
||
Check out [@cra-express/redux-prefetcher](https://github.com/antonybudianto/create-react-app-express/tree/master/packages/redux-prefetcher) |