From 4a6f295fd846b1bfc7fff9a921eb6503cc612a61 Mon Sep 17 00:00:00 2001 From: Thibault Derousseaux 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 a0490240a2f..548f3793456 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. @@ -163,7 +178,11 @@ module.exports = { // including CSS. This is confusing and will be removed in Webpack 2: // https://github.com/webpack/webpack/issues/283 // ZEAL: Add support for css modules - loader: ExtractTextPlugin.extract('style', 'css?importLoaders=1&-autoprefixer!postcss') + loader: ExtractTextPlugin.extract( + 'style', + 'css?importLoaders=1&-autoprefixer!postcss', + extractTextPluginOptions + ) // Note: this won't work without `new ExtractTextPlugin()` in `plugins`. }, { @@ -259,7 +278,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 357df8d5dee..c85e544720b 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