Skip to content

Commit 8e127aa

Browse files
tibdexTimer
authored andcommitted
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
1 parent 613b584 commit 8e127aa

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.
@@ -40,6 +43,18 @@ if (env.stringified['process.env'].NODE_ENV !== '"production"') {
4043
throw new Error('Production builds must have NODE_ENV=production.');
4144
}
4245

46+
// Note: defined here because it will be used more than once.
47+
const cssFilename = 'static/css/[name].[contenthash:8].css';
48+
49+
// ExtractTextPlugin expects the build output to be flat.
50+
// (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27)
51+
// However, our output is structured with css, js and media folders.
52+
// To have this structure working with relative paths, we have to use custom options.
53+
const extractTextPluginOptions = shouldUseRelativeAssetPaths
54+
// Making sure that the publicPath goes back to to build folder.
55+
? { publicPath: Array(cssFilename.split('/').length).join('../') }
56+
: undefined;
57+
4358
// This is the production configuration.
4459
// It compiles slowly and is focused on producing a fast and minimal bundle.
4560
// The development configuration is different and lives in a separate file.
@@ -150,7 +165,11 @@ module.exports = {
150165
// in the main CSS file.
151166
{
152167
test: /\.css$/,
153-
loader: ExtractTextPlugin.extract('style', 'css?importLoaders=1!postcss')
168+
loader: ExtractTextPlugin.extract(
169+
'style',
170+
'css?importLoaders=1!postcss',
171+
extractTextPluginOptions
172+
)
154173
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
155174
},
156175
// JSON is not enabled by default in Webpack but both Node and Browserify
@@ -241,7 +260,7 @@ module.exports = {
241260
}
242261
}),
243262
// Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
244-
new ExtractTextPlugin('static/css/[name].[contenthash:8].css'),
263+
new ExtractTextPlugin(cssFilename),
245264
// Generate a manifest file which contains a mapping of all asset filenames
246265
// to their corresponding output file so that tools can pick it up without
247266
// 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)