Skip to content

Commit b71ed15

Browse files
tibdexDaniel Figueiredo
authored and
Daniel Figueiredo
committed
Support relative asset paths for special case (facebook#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
1 parent 21dabde commit b71ed15

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

packages/react-scripts/config/webpack.config.prod.js

+21-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ var path = require('path');
2727
// Webpack uses `publicPath` to determine where the app is being served from.
2828
// It requires a trailing slash, or the file assets will get an incorrect path.
2929
var publicPath = paths.servedPath;
30+
// Some apps do not use client-side routing with pushState.
31+
// For these, "homepage" can be set to "." to enable relative asset paths.
32+
var shouldUseRelativeAssetPaths = publicPath === './';
3033
// `publicUrl` is just like `publicPath`, but we will provide it to our app
3134
// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
3235
// Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
@@ -43,6 +46,18 @@ if (env.stringified['process.env'].NODE_ENV !== '"production"') {
4346
throw new Error('Production builds must have NODE_ENV=production.');
4447
}
4548

49+
// Note: defined here because it will be used more than once.
50+
const cssFilename = 'static/css/[name].[contenthash:8].css';
51+
52+
// ExtractTextPlugin expects the build output to be flat.
53+
// (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27)
54+
// However, our output is structured with css, js and media folders.
55+
// To have this structure working with relative paths, we have to use custom options.
56+
const extractTextPluginOptions = shouldUseRelativeAssetPaths
57+
// Making sure that the publicPath goes back to to build folder.
58+
? { publicPath: Array(cssFilename.split('/').length).join('../') }
59+
: undefined;
60+
4661
// This is the production configuration.
4762
// It compiles slowly and is focused on producing a fast and minimal bundle.
4863
// The development configuration is different and lives in a separate file.
@@ -153,7 +168,11 @@ module.exports = {
153168
// in the main CSS file.
154169
{
155170
test: /\.css$/,
156-
loader: ExtractTextPlugin.extract('style', 'css?importLoaders=1!postcss')
171+
loader: ExtractTextPlugin.extract(
172+
'style',
173+
'css?importLoaders=1!postcss',
174+
extractTextPluginOptions
175+
)
157176
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
158177
},
159178
// JSON is not enabled by default in Webpack but both Node and Browserify
@@ -233,7 +252,7 @@ module.exports = {
233252
}
234253
}),
235254
// Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
236-
new ExtractTextPlugin('static/css/[name].[contenthash:8].css'),
255+
new ExtractTextPlugin(cssFilename),
237256
// Generate a manifest file which contains a mapping of all asset filenames
238257
// to their corresponding output file so that tools can pick it up without
239258
// having to parse `index.html`.

packages/react-scripts/template/README.md

+11
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,17 @@ To override this, specify the `homepage` in your `package.json`, for example:
10701070

10711071
This will let Create React App correctly infer the root path to use in the generated HTML file.
10721072

1073+
#### Serving the Same Build from Different Paths
1074+
1075+
>Note: this feature is available with `[email protected]` and higher.
1076+
1077+
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`:
1078+
1079+
```js
1080+
"homepage": ".",
1081+
```
1082+
1083+
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.
10731084

10741085
### Firebase
10751086

0 commit comments

Comments
 (0)