diff --git a/packages/react-scripts/fixtures/kitchensink/integration/env.test.js b/packages/react-scripts/fixtures/kitchensink/integration/env.test.js
index a179aa7cbb2..414229b22ac 100644
--- a/packages/react-scripts/fixtures/kitchensink/integration/env.test.js
+++ b/packages/react-scripts/fixtures/kitchensink/integration/env.test.js
@@ -3,22 +3,30 @@ import initDOM from './initDOM'
describe('Integration', () => {
describe('Environment variables', () => {
+ it('file env variables', async () => {
+ const doc = await initDOM('file-env-variables')
+
+ expect(doc.getElementById('feature-file-env-variables').textContent).to.equal('fromtheenvfile.')
+ })
+
it('NODE_PATH', async () => {
const doc = await initDOM('node-path')
expect(doc.getElementById('feature-node-path').childElementCount).to.equal(4)
})
- it('shell env variables', async () => {
- const doc = await initDOM('shell-env-variables')
+ it('PUBLIC_URL', async () => {
+ const doc = await initDOM('public-url')
- expect(doc.getElementById('feature-shell-env-variables').textContent).to.equal('fromtheshell.')
+ expect(doc.getElementById('feature-public-url').textContent).to.equal('http://www.example.org/spa.')
+ expect(doc.querySelector('head link[rel="shortcut icon"]').getAttribute('href'))
+ .to.equal('http://www.example.org/spa/favicon.ico')
})
- it('file env variables', async () => {
- const doc = await initDOM('file-env-variables')
+ it('shell env variables', async () => {
+ const doc = await initDOM('shell-env-variables')
- expect(doc.getElementById('feature-file-env-variables').textContent).to.equal('fromtheenvfile.')
+ expect(doc.getElementById('feature-shell-env-variables').textContent).to.equal('fromtheshell.')
})
})
})
diff --git a/packages/react-scripts/fixtures/kitchensink/integration/initDOM.js b/packages/react-scripts/fixtures/kitchensink/integration/initDOM.js
index cec02227493..7cf8134b79f 100644
--- a/packages/react-scripts/fixtures/kitchensink/integration/initDOM.js
+++ b/packages/react-scripts/fixtures/kitchensink/integration/initDOM.js
@@ -15,9 +15,11 @@ if (process.env.E2E_FILE) {
const markup = fs.readFileSync(file, 'utf8')
getMarkup = () => markup
+ const pathPrefix = process.env.PUBLIC_URL.replace(/^https?:\/\/[^\/]+\/?/, '')
+
resourceLoader = (resource, callback) => callback(
null,
- fs.readFileSync(path.join(path.dirname(file), resource.url.pathname), 'utf8')
+ fs.readFileSync(path.join(path.dirname(file), resource.url.pathname.replace(pathPrefix, '')), 'utf8')
)
} else if (process.env.E2E_URL) {
getMarkup = () => new Promise(resolve => {
@@ -37,7 +39,7 @@ if (process.env.E2E_FILE) {
export default feature => new Promise(async resolve => {
const markup = await getMarkup()
- const host = process.env.E2E_URL || 'http://localhost:3000'
+ const host = process.env.E2E_URL || 'http://www.example.org/spa:3000'
const doc = jsdom.jsdom(markup, {
features: {
FetchExternalResources: ['script', 'css'],
diff --git a/packages/react-scripts/fixtures/kitchensink/src/App.js b/packages/react-scripts/fixtures/kitchensink/src/App.js
index cf93b4c132b..be9465ece36 100644
--- a/packages/react-scripts/fixtures/kitchensink/src/App.js
+++ b/packages/react-scripts/fixtures/kitchensink/src/App.js
@@ -32,7 +32,8 @@ class App extends React.Component {
}
componentDidMount() {
- switch (location.hash.slice(1)) {
+ const feature = location.hash.slice(1)
+ switch (feature) {
case 'array-destructuring':
require.ensure([], () => this.setFeature(require('./features/syntax/ArrayDestructuring').default));
break;
@@ -87,6 +88,9 @@ class App extends React.Component {
case 'promises':
require.ensure([], () => this.setFeature(require('./features/syntax/Promises').default));
break;
+ case 'public-url':
+ require.ensure([], () => this.setFeature(require('./features/env/PublicUrl').default));
+ break;
case 'rest-and-default':
require.ensure([], () => this.setFeature(require('./features/syntax/RestAndDefault').default));
break;
@@ -106,6 +110,9 @@ class App extends React.Component {
require.ensure([], () => this.setFeature(require('./features/webpack/UnknownExtInclusion').default));
break;
default:
+ if (feature) {
+ throw new Error(`Missing feature "${feature}"`);
+ }
this.setFeature(null);
break;
}
diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/env/PublicUrl.js b/packages/react-scripts/fixtures/kitchensink/src/features/env/PublicUrl.js
new file mode 100644
index 00000000000..bbb7b958b61
--- /dev/null
+++ b/packages/react-scripts/fixtures/kitchensink/src/features/env/PublicUrl.js
@@ -0,0 +1,5 @@
+import React from 'react'
+
+export default () => (
+ {process.env.PUBLIC_URL}.
+)
diff --git a/packages/react-scripts/fixtures/kitchensink/src/features/env/PublicUrl.test.js b/packages/react-scripts/fixtures/kitchensink/src/features/env/PublicUrl.test.js
new file mode 100644
index 00000000000..31e699ece0b
--- /dev/null
+++ b/packages/react-scripts/fixtures/kitchensink/src/features/env/PublicUrl.test.js
@@ -0,0 +1,10 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import PublicUrl from './PublicUrl';
+
+describe('PUBLIC_URL', () => {
+ it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(, div);
+ });
+});
diff --git a/packages/react-scripts/scripts/start.js b/packages/react-scripts/scripts/start.js
index 8615fb074a9..c326b9b94d9 100644
--- a/packages/react-scripts/scripts/start.js
+++ b/packages/react-scripts/scripts/start.js
@@ -241,7 +241,7 @@ function runDevServer(host, port, protocol) {
// project directory is dangerous because we may expose sensitive files.
// Instead, we establish a convention that only files in `public` directory
// get served. Our build script will copy `public` into the `build` folder.
- // In `index.html`, you can get URL of `public` folder with %PUBLIC_PATH%:
+ // In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%:
//
// In JavaScript code, you can access it with `process.env.PUBLIC_URL`.
// Note that we only recommend to use `public` folder as an escape hatch
diff --git a/tasks/e2e-kitchensink.sh b/tasks/e2e-kitchensink.sh
index 892230ab747..3db6ef8d1d0 100755
--- a/tasks/e2e-kitchensink.sh
+++ b/tasks/e2e-kitchensink.sh
@@ -111,7 +111,11 @@ create_react_app --scripts-version=$scripts_path --internal-testing-template=$ro
cd test-kitchensink
# Test the build
-NODE_PATH=src REACT_APP_SHELL_ENV_MESSAGE=fromtheshell npm run build
+REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \
+ NODE_PATH=src \
+ PUBLIC_URL=http://www.example.org/spa/ \
+ npm run build
+
# Check for expected output
test -e build/*.html
test -e build/static/js/main.*.js
@@ -127,6 +131,7 @@ tmp_server_log=`mktemp`
PORT=3001 \
REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \
NODE_PATH=src \
+ PUBLIC_URL=http://www.example.org/spa/ \
nohup npm start &>$tmp_server_log &
grep -q 'The app is running at:' <(tail -f $tmp_server_log)
E2E_URL="http://localhost:3001" \
@@ -138,6 +143,7 @@ E2E_URL="http://localhost:3001" \
E2E_FILE=./build/index.html \
CI=true \
NODE_PATH=src \
+ PUBLIC_URL=http://www.example.org/spa/ \
node_modules/.bin/mocha --require babel-register --require babel-polyfill integration/*.test.js
# ******************************************************************************
@@ -157,7 +163,11 @@ npm link $root_path/packages/react-scripts
rm .babelrc
# Test the build
-NODE_PATH=src REACT_APP_SHELL_ENV_MESSAGE=fromtheshell npm run build
+REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \
+ NODE_PATH=src \
+ PUBLIC_URL=http://www.example.org/spa/ \
+ npm run build
+
# Check for expected output
test -e build/*.html
test -e build/static/js/main.*.js
@@ -173,6 +183,7 @@ tmp_server_log=`mktemp`
PORT=3002 \
REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \
NODE_PATH=src \
+ PUBLIC_URL=http://www.example.org/spa/ \
nohup npm start &>$tmp_server_log &
grep -q 'The app is running at:' <(tail -f $tmp_server_log)
E2E_URL="http://localhost:3002" \
@@ -186,6 +197,7 @@ E2E_FILE=./build/index.html \
CI=true \
NODE_ENV=production \
NODE_PATH=src \
+ PUBLIC_URL=http://www.example.org/spa/ \
node_modules/.bin/mocha --require babel-register --require babel-polyfill integration/*.test.js
# Cleanup