From e8b5b1908cf8399d65645a9251d2b9fcf7af3c9d Mon Sep 17 00:00:00 2001 From: Li Xuanji Date: Wed, 19 Oct 2016 18:13:21 -0400 Subject: [PATCH 1/4] Document what npm build does and pushState --- packages/react-scripts/template/README.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/react-scripts/template/README.md b/packages/react-scripts/template/README.md index 788f77e7805..fde10ea41d6 100644 --- a/packages/react-scripts/template/README.md +++ b/packages/react-scripts/template/README.md @@ -863,7 +863,20 @@ This feature is experimental and still [has major usage issues](https://github.c ## Deployment -## Building for Relative Paths +`npm run build` creates a `build` directory with a production build of your app. Set up your favourite http server so that a visitor to your site is served `index.html`, and requests to static paths like `/static/js/main..js` is served with the contents of the `/static/js/main..js` file. + +```sh +cd ./build +python3 -m http.server 80 +``` + +### `pushState` routers + +If you use routers that use the HTML5 `pushState` history API under the hood (for example, React Router using `browserHistory`), many static file servers will fail. For example, if you used react-router with a route for `/todos/42`, the development server will respond to `localhost:3000/todos/42` properly, but the python3 http.server serving a production build as above will not. + +This is because when there is a fresh page load for a `0.0.0.0/todos/42`, the server looks for the file `build/todos/42` and does not find it. The server needs to be configured to respond to a request to `/todos/42` by serving `index.html`. + +### Building for Relative Paths By default, Create React App produces a build assuming your app is hosted at the server root.
To override this, specify the `homepage` in your `package.json`, for example: From defe7692120313d2472ad23ffb51bdd64ef5795b Mon Sep 17 00:00:00 2001 From: Li Xuanji Date: Sun, 30 Oct 2016 17:18:46 -0400 Subject: [PATCH 2/4] Fix typos, add express example --- packages/react-scripts/template/README.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/react-scripts/template/README.md b/packages/react-scripts/template/README.md index fde10ea41d6..ac589e2955e 100644 --- a/packages/react-scripts/template/README.md +++ b/packages/react-scripts/template/README.md @@ -863,13 +863,29 @@ This feature is experimental and still [has major usage issues](https://github.c ## Deployment -`npm run build` creates a `build` directory with a production build of your app. Set up your favourite http server so that a visitor to your site is served `index.html`, and requests to static paths like `/static/js/main..js` is served with the contents of the `/static/js/main..js` file. +`npm run build` creates a `build` directory with a production build of your app. Set up your favourite HTTP server so that a visitor to your site is served `index.html`, and requests to static paths like `/static/js/main..js` are served with the contents of the `/static/js/main..js` file. For example, python contains a built-in HTTP server that can serve static files: ```sh cd ./build python3 -m http.server 80 ``` +Or using express: + +```javascript +const express = require('express'); +const path = require('path'); +const app = express(); + +app.use(express.static('./build')); + +app.get('/', function (req, res) { + res.sendFile(path.join(__dirname, './build', 'index.html')); +}); + +app.listen(80); +``` + ### `pushState` routers If you use routers that use the HTML5 `pushState` history API under the hood (for example, React Router using `browserHistory`), many static file servers will fail. For example, if you used react-router with a route for `/todos/42`, the development server will respond to `localhost:3000/todos/42` properly, but the python3 http.server serving a production build as above will not. From ce81f470cb70c13abde8cfc5f13bac2af2972d2a Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Mon, 5 Dec 2016 21:52:37 +0000 Subject: [PATCH 3/4] Tweaks --- packages/react-scripts/template/README.md | 27 +++++++++++++++++------ 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/packages/react-scripts/template/README.md b/packages/react-scripts/template/README.md index ac589e2955e..7506b40c38b 100644 --- a/packages/react-scripts/template/README.md +++ b/packages/react-scripts/template/README.md @@ -863,14 +863,14 @@ This feature is experimental and still [has major usage issues](https://github.c ## Deployment -`npm run build` creates a `build` directory with a production build of your app. Set up your favourite HTTP server so that a visitor to your site is served `index.html`, and requests to static paths like `/static/js/main..js` are served with the contents of the `/static/js/main..js` file. For example, python contains a built-in HTTP server that can serve static files: +`npm run build` creates a `build` directory with a production build of your app. Set up your favourite HTTP server so that a visitor to your site is served `index.html`, and requests to static paths like `/static/js/main..js` are served with the contents of the `/static/js/main..js` file. For example, Python contains a built-in HTTP server that can serve static files: ```sh -cd ./build -python3 -m http.server 80 +cd build +python -m SimpleHTTPServer 9000 ``` -Or using express: +Or using [Express](http://expressjs.com/): ```javascript const express = require('express'); @@ -883,14 +883,27 @@ app.get('/', function (req, res) { res.sendFile(path.join(__dirname, './build', 'index.html')); }); -app.listen(80); +app.listen(9000); ``` +However this is not quite enough if you use client-side routing. Read the next section if you want to support URLs like `/todos/42` in your single-page app. + ### `pushState` routers -If you use routers that use the HTML5 `pushState` history API under the hood (for example, React Router using `browserHistory`), many static file servers will fail. For example, if you used react-router with a route for `/todos/42`, the development server will respond to `localhost:3000/todos/42` properly, but the python3 http.server serving a production build as above will not. +If you use routers that use the HTML5 [`pushState` history API](https://developer.mozilla.org/en-US/docs/Web/API/History_API#Adding_and_modifying_history_entries) under the hood (for example, [React Router](https://github.com/ReactTraining/react-router) with `browserHistory`), many static file servers will fail. For example, if you used React Router with a route for `/todos/42`, the development server will respond to `localhost:3000/todos/42` properly, but an Express serving a production build as above will not. + +This is because when there is a fresh page load for a `/todos/42`, the server looks for the file `build/todos/42` and does not find it. The server needs to be configured to respond to a request to `/todos/42` by serving `index.html`. For example, we can amend our Express example above to serve `index.html` for any unknown paths: + +```diff + app.use(express.static('./build')); + +-app.get('/', function (req, res) { ++app.get('/*', function (req, res) { + res.sendFile(path.join(__dirname, './build', 'index.html')); + }); +``` -This is because when there is a fresh page load for a `0.0.0.0/todos/42`, the server looks for the file `build/todos/42` and does not find it. The server needs to be configured to respond to a request to `/todos/42` by serving `index.html`. +Now requests to `/todos/42` will be handled correctly both in development and in production. ### Building for Relative Paths From 3c30eae8894b3c594d11439980c6c9009890b810 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Mon, 5 Dec 2016 21:57:05 +0000 Subject: [PATCH 4/4] Update README.md --- packages/react-scripts/template/README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/react-scripts/template/README.md b/packages/react-scripts/template/README.md index 7506b40c38b..c92083cdbf2 100644 --- a/packages/react-scripts/template/README.md +++ b/packages/react-scripts/template/README.md @@ -42,6 +42,7 @@ You can find the most recent version of this guide [here](https://github.com/fac - [Disabling jsdom](#disabling-jsdom) - [Experimental Snapshot Testing](#experimental-snapshot-testing) - [Deployment](#deployment) + - [Serving Apps with Client-Side Routing](#serving-apps-with-client-side-routing) - [Building for Relative Paths](#building-for-relative-paths) - [GitHub Pages](#github-pages) - [Heroku](#heroku) @@ -134,6 +135,8 @@ It correctly bundles React in production mode and optimizes the build for the be The build is minified and the filenames include the hashes.
Your app is ready to be deployed! +See the section about [deployment](#deployment) for more information. + ### `npm run eject` **Note: this is a one-way operation. Once you `eject`, you can’t go back!** @@ -870,7 +873,7 @@ cd build python -m SimpleHTTPServer 9000 ``` -Or using [Express](http://expressjs.com/): +If you're using [Node](https://nodejs.org/) and [Express](http://expressjs.com/) as a server, it might look like this: ```javascript const express = require('express'); @@ -886,9 +889,11 @@ app.get('/', function (req, res) { app.listen(9000); ``` +Create React App is not opinionated about your choice of web server. Any static file server will do. The `build` folder with static assets is the only output produced by Create React App. + However this is not quite enough if you use client-side routing. Read the next section if you want to support URLs like `/todos/42` in your single-page app. -### `pushState` routers +### Serving Apps with Client-Side Routing If you use routers that use the HTML5 [`pushState` history API](https://developer.mozilla.org/en-US/docs/Web/API/History_API#Adding_and_modifying_history_entries) under the hood (for example, [React Router](https://github.com/ReactTraining/react-router) with `browserHistory`), many static file servers will fail. For example, if you used React Router with a route for `/todos/42`, the development server will respond to `localhost:3000/todos/42` properly, but an Express serving a production build as above will not.