Skip to content

Commit 8d5e677

Browse files
committed
Allow relative $PUBLIC_URL in dev mode
As long as client side routing isn't actively used, a relative $PUBLIC_URL should work correctly in both development and production. There's no reason it should be limited to production. Closes facebook#8623 Also see coder/code-server#2565
1 parent 3f5dea9 commit 8d5e677

File tree

2 files changed

+38
-32
lines changed

2 files changed

+38
-32
lines changed

packages/react-dev-utils/__tests__/getPublicUrlOrPath.test.js

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ const tests = [
1414
{ dev: true, homepage: '/', expect: '/' },
1515
{ dev: true, homepage: '/test', expect: '/test/' },
1616
{ dev: true, homepage: '/test/', expect: '/test/' },
17-
{ dev: true, homepage: './', expect: '/' },
18-
{ dev: true, homepage: '../', expect: '/' },
19-
{ dev: true, homepage: '../test', expect: '/' },
20-
{ dev: true, homepage: './test/path', expect: '/' },
17+
{ dev: true, homepage: './', expect: './' },
18+
{ dev: true, homepage: '../', expect: '../' },
19+
{ dev: true, homepage: '../test', expect: '../test/' },
20+
{ dev: true, homepage: './test/path', expect: './test/path/' },
2121
{ dev: true, homepage: 'https://create-react-app.dev/', expect: '/' },
2222
{
2323
dev: true,
@@ -28,10 +28,10 @@ const tests = [
2828
{ dev: true, publicUrl: '/', expect: '/' },
2929
{ dev: true, publicUrl: '/test', expect: '/test/' },
3030
{ dev: true, publicUrl: '/test/', expect: '/test/' },
31-
{ dev: true, publicUrl: './', expect: '/' },
32-
{ dev: true, publicUrl: '../', expect: '/' },
33-
{ dev: true, publicUrl: '../test', expect: '/' },
34-
{ dev: true, publicUrl: './test/path', expect: '/' },
31+
{ dev: true, publicUrl: './', expect: './' },
32+
{ dev: true, publicUrl: '../', expect: '../' },
33+
{ dev: true, publicUrl: '../test', expect: '../test/' },
34+
{ dev: true, publicUrl: './test/path', expect: './test/path/' },
3535
{ dev: true, publicUrl: 'https://create-react-app.dev/', expect: '/' },
3636
{
3737
dev: true,
@@ -42,10 +42,15 @@ const tests = [
4242
{ dev: true, publicUrl: '/', homepage: '/test', expect: '/' },
4343
{ dev: true, publicUrl: '/test', homepage: '/path', expect: '/test/' },
4444
{ dev: true, publicUrl: '/test/', homepage: '/test/path', expect: '/test/' },
45-
{ dev: true, publicUrl: './', homepage: '/test', expect: '/' },
46-
{ dev: true, publicUrl: '../', homepage: '/test', expect: '/' },
47-
{ dev: true, publicUrl: '../test', homepage: '/test', expect: '/' },
48-
{ dev: true, publicUrl: './test/path', homepage: '/test', expect: '/' },
45+
{ dev: true, publicUrl: './', homepage: '/test', expect: './' },
46+
{ dev: true, publicUrl: '../', homepage: '/test', expect: '../' },
47+
{ dev: true, publicUrl: '../test', homepage: '/test', expect: '../test/' },
48+
{
49+
dev: true,
50+
publicUrl: './test/path',
51+
homepage: '/test',
52+
expect: './test/path/',
53+
},
4954
{
5055
dev: true,
5156
publicUrl: 'https://create-react-app.dev/',
@@ -67,11 +72,15 @@ const tests = [
6772
{ dev: false, homepage: '../', expect: '../' },
6873
{ dev: false, homepage: '../test', expect: '../test/' },
6974
{ dev: false, homepage: './test/path', expect: './test/path/' },
70-
{ dev: false, homepage: 'https://create-react-app.dev/', expect: '/' },
75+
{
76+
dev: false,
77+
homepage: 'https://create-react-app.dev/',
78+
expect: 'https://create-react-app.dev/',
79+
},
7180
{
7281
dev: false,
7382
homepage: 'https://create-react-app.dev/test',
74-
expect: '/test/',
83+
expect: 'https://create-react-app.dev/test/',
7584
},
7685
// PRODUCTION with publicUrl
7786
{ dev: false, publicUrl: '/', expect: '/' },

packages/react-dev-utils/getPublicUrlOrPath.js

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ module.exports = getPublicUrlOrPath;
1414
/**
1515
* Returns a URL or a path with slash at the end
1616
* In production can be URL, abolute path, relative path
17-
* In development always will be an absolute path
17+
* In development can be a relative or absolute path
1818
* In development can use `path` module functions for operations
1919
*
2020
* @param {boolean} isEnvDevelopment
@@ -31,34 +31,31 @@ function getPublicUrlOrPath(isEnvDevelopment, homepage, envPublicUrl) {
3131
? envPublicUrl
3232
: envPublicUrl + '/';
3333

34+
// Some apps do not use client-side routing with pushState.
35+
// For these, "$PUBLIC_URL" can be set to "." to enable relative asset paths.
36+
if (envPublicUrl.startsWith('.')) {
37+
return envPublicUrl;
38+
}
39+
3440
// validate if `envPublicUrl` is a URL or path like
3541
// `stubDomain` is ignored if `envPublicUrl` contains a domain
3642
const validPublicUrl = new URL(envPublicUrl, stubDomain);
37-
38-
return isEnvDevelopment
39-
? envPublicUrl.startsWith('.')
40-
? '/'
41-
: validPublicUrl.pathname
42-
: // Some apps do not use client-side routing with pushState.
43-
// For these, "homepage" can be set to "." to enable relative asset paths.
44-
envPublicUrl;
43+
return isEnvDevelopment ? validPublicUrl.pathname : envPublicUrl;
4544
}
4645

4746
if (homepage) {
4847
// strip last slash if exists
4948
homepage = homepage.endsWith('/') ? homepage : homepage + '/';
5049

50+
// Some apps do not use client-side routing with pushState.
51+
// For these, homepage can be set to "." to enable relative asset paths.
52+
if (homepage.startsWith('.')) {
53+
return homepage;
54+
}
55+
5156
// validate if `homepage` is a URL or path like and use just pathname
5257
const validHomepagePathname = new URL(homepage, stubDomain).pathname;
53-
return isEnvDevelopment
54-
? homepage.startsWith('.')
55-
? '/'
56-
: validHomepagePathname
57-
: // Some apps do not use client-side routing with pushState.
58-
// For these, "homepage" can be set to "." to enable relative asset paths.
59-
homepage.startsWith('.')
60-
? homepage
61-
: validHomepagePathname;
58+
return isEnvDevelopment ? validHomepagePathname : homepage;
6259
}
6360

6461
return '/';

0 commit comments

Comments
 (0)