From 8e127aaa38384a1e04ffc35670f0f60bd63e60d5 Mon Sep 17 00:00:00 2001
From: Thibault Derousseaux <tibdex@users.noreply.github.com>
Date: Fri, 10 Feb 2017 06:44:00 +0100
Subject: [PATCH] Support relative asset paths for special case (#1489)

* Fix paths in CSS files when homepage is set to "./"

In the production build, ExtractTextPlugin is used to generate a separate CSS file instead of injecting style through JavaScript. This plugin does not work well by default with nested output structure. To fix it, we give it a relative publicPath pointing to the build folder.

* Add section in README to explain how to make builds deployable anywhere

* Apply review requested change

* Apply review changes 2
---
 .../config/webpack.config.prod.js             | 23 +++++++++++++++++--
 packages/react-scripts/template/README.md     | 11 +++++++++
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/packages/react-scripts/config/webpack.config.prod.js b/packages/react-scripts/config/webpack.config.prod.js
index 6bd61c99c..4e75be521 100644
--- a/packages/react-scripts/config/webpack.config.prod.js
+++ b/packages/react-scripts/config/webpack.config.prod.js
@@ -27,6 +27,9 @@ var path = require('path');
 // Webpack uses `publicPath` to determine where the app is being served from.
 // It requires a trailing slash, or the file assets will get an incorrect path.
 var publicPath = paths.servedPath;
+// Some apps do not use client-side routing with pushState.
+// For these, "homepage" can be set to "." to enable relative asset paths.
+var shouldUseRelativeAssetPaths = publicPath === './';
 // `publicUrl` is just like `publicPath`, but we will provide it to our app
 // as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
 // Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
@@ -40,6 +43,18 @@ if (env.stringified['process.env'].NODE_ENV !== '"production"') {
   throw new Error('Production builds must have NODE_ENV=production.');
 }
 
+// Note: defined here because it will be used more than once.
+const cssFilename = 'static/css/[name].[contenthash:8].css';
+
+// ExtractTextPlugin expects the build output to be flat.
+// (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27)
+// However, our output is structured with css, js and media folders.
+// To have this structure working with relative paths, we have to use custom options.
+const extractTextPluginOptions = shouldUseRelativeAssetPaths
+  // Making sure that the publicPath goes back to to build folder.
+  ? { publicPath: Array(cssFilename.split('/').length).join('../') }
+  : undefined;
+
 // This is the production configuration.
 // It compiles slowly and is focused on producing a fast and minimal bundle.
 // The development configuration is different and lives in a separate file.
@@ -150,7 +165,11 @@ module.exports = {
       // in the main CSS file.
       {
         test: /\.css$/,
-        loader: ExtractTextPlugin.extract('style', 'css?importLoaders=1!postcss')
+        loader: ExtractTextPlugin.extract(
+          'style',
+          'css?importLoaders=1!postcss',
+          extractTextPluginOptions
+        )
         // Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
       },
       // JSON is not enabled by default in Webpack but both Node and Browserify
@@ -241,7 +260,7 @@ module.exports = {
       }
     }),
     // Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
-    new ExtractTextPlugin('static/css/[name].[contenthash:8].css'),
+    new ExtractTextPlugin(cssFilename),
     // Generate a manifest file which contains a mapping of all asset filenames
     // to their corresponding output file so that tools can pick it up without
     // having to parse `index.html`.
diff --git a/packages/react-scripts/template/README.md b/packages/react-scripts/template/README.md
index 357df8d5d..c85e54472 100644
--- a/packages/react-scripts/template/README.md
+++ b/packages/react-scripts/template/README.md
@@ -1070,6 +1070,17 @@ To override this, specify the `homepage` in your `package.json`, for example:
 
 This will let Create React App correctly infer the root path to use in the generated HTML file.
 
+#### Serving the Same Build from Different Paths
+
+>Note: this feature is available with `react-scripts@0.9.0` and higher.
+
+If you are not using the HTML5 `pushState` history API or not using client-side routing at all, it is unnecessary to specify the URL from which your app will be served. Instead, you can put this in your `package.json`:
+
+```js
+  "homepage": ".",
+```
+
+This will make sure that all the asset paths are relative to `index.html`. You will then be able to move your app from `http://mywebsite.com` to `http://mywebsite.com/relativepath` or even `http://mywebsite.com/relative/path` without having to rebuild it.
 
 ### Firebase
 
-- 
GitLab