Skip to content

Commit 92e22af

Browse files
committed
Allowing an absolute publicPath with dev-server, but showing a warning
1 parent 830fdb5 commit 92e22af

File tree

10 files changed

+122
-36
lines changed

10 files changed

+122
-36
lines changed

bin/encore.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
'use strict';
1212

13-
const path = require('path');
1413
const parseRuntime = require('../lib/config/parse-runtime');
1514
const context = require('../lib/context');
1615
const chalk = require('chalk');

index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,17 @@ const configGenerator = require('./lib/config-generator');
1414
const validator = require('./lib/config/validator');
1515
const PrettyError = require('pretty-error');
1616
const runtimeConfig = require('./lib/context').runtimeConfig;
17+
const logger = require('./lib/logger');
1718

1819
// at this time, the encore executable should have set the runtimeConfig
1920
if (!runtimeConfig) {
2021
throw new Error('Are you trying to require index.js directly?');
2122
}
2223

2324
let webpackConfig = new WebpackConfig(runtimeConfig);
25+
if (runtimeConfig.verbose) {
26+
logger.verbose();
27+
}
2428

2529
module.exports = {
2630
/**

lib/WebpackConfig.js

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -86,23 +86,11 @@ class WebpackConfig {
8686
}
8787

8888
setPublicPath(publicPath) {
89-
/*
90-
* Do not allow absolute URLs *and* the webpackDevServer
91-
* to be used at the same time. The webpackDevServer basically
92-
* provides the publicPath (and so in those cases, publicPath)
93-
* is simply used as the default manifestKeyPrefix.
94-
*/
95-
if (publicPath.includes('://')) {
96-
if (this.useDevServer() && false === this.runtimeConfig.devServerKeepPublicPath) {
97-
throw new Error('You cannot pass an absolute URL to setPublicPath() and use the dev-server at the same time. This is because the public path is automatically set to point to the dev server. Try using Encore.isProduction() to only configure your absolute publicPath for production. Or, if you want to override this behavior, pass the --keep-public-path option to allow this.');
98-
}
99-
} else {
100-
if (publicPath.indexOf('/') !== 0) {
101-
// technically, not starting with "/" is legal, but not
102-
// what you want in most cases. Let's not let the user make
103-
// a mistake (and we can always change this later).
104-
throw new Error('The value passed to setPublicPath() must start with "/" or be a full URL (http://...)');
105-
}
89+
if (publicPath.includes('://') === false && publicPath.indexOf('/') !== 0) {
90+
// technically, not starting with "/" is legal, but not
91+
// what you want in most cases. Let's not let the user make
92+
// a mistake (and we can always change this later).
93+
throw new Error('The value passed to setPublicPath() must start with "/" or be a full URL (http://...)');
10694
}
10795

10896
// guarantee a single trailing slash
@@ -129,13 +117,20 @@ class WebpackConfig {
129117
* @returns {string}
130118
*/
131119
getRealPublicPath() {
132-
// if we're using webpack-dev-server, use it & add the publicPath
133-
if (this.useDevServer() && false === this.runtimeConfig.devServerKeepPublicPath) {
134-
// avoid 2 middle slashes
135-
return this.runtimeConfig.devServerUrl.replace(/\/$/,'') + this.publicPath;
120+
if (!this.useDevServer()) {
121+
return this.publicPath;
122+
}
123+
124+
if (this.runtimeConfig.devServerKeepPublicPath) {
125+
return this.publicPath;
126+
}
127+
128+
if (this.publicPath.includes('://')) {
129+
return this.publicPath;
136130
}
137131

138-
return this.publicPath;
132+
// if using dev-server, prefix the publicPath with the dev server URL
133+
return this.runtimeConfig.devServerUrl.replace(/\/$/,'') + this.publicPath;
139134
}
140135

141136
addEntry(name, src) {

lib/config-generator.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,8 +384,8 @@ class ConfigGenerator {
384384
publicPath: this.webpackConfig.publicPath,
385385
// avoid CORS concerns trying to load things like fonts from the dev server
386386
headers: { 'Access-Control-Allow-Origin': '*' },
387-
// required by FriendlyErrorsWebpackPlugin
388387
hot: this.webpackConfig.useHotModuleReplacementPlugin(),
388+
// required by FriendlyErrorsWebpackPlugin
389389
quiet: true,
390390
compress: true,
391391
historyApiFallback: true,

lib/config/RuntimeConfig.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class RuntimeConfig {
2525
this.babelRcFileExists = null;
2626

2727
this.helpRequested = false;
28+
this.verbose = false;
2829
}
2930
}
3031

lib/config/parse-runtime.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,18 @@ module.exports = function(argv, cwd) {
2929
case 'dev':
3030
runtimeConfig.isValidCommand = true;
3131
runtimeConfig.environment = 'dev';
32+
runtimeConfig.verbose = true;
3233
break;
3334
case 'production':
3435
runtimeConfig.isValidCommand = true;
3536
runtimeConfig.environment = 'production';
37+
runtimeConfig.verbose = false;
3638
break;
3739
case 'dev-server':
3840
runtimeConfig.isValidCommand = true;
3941
runtimeConfig.environment = 'dev';
42+
runtimeConfig.verbose = true;
43+
4044
runtimeConfig.useDevServer = true;
4145
runtimeConfig.devServerHttps = argv.https;
4246
runtimeConfig.useHotModuleReplacement = argv.hot || false;

lib/config/validator.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
'use strict';
1111

1212
const pathUtil = require('./path-util');
13+
const logger = require('./../logger');
1314

1415
class Validator {
1516
/**
@@ -46,9 +47,24 @@ class Validator {
4647
}
4748

4849
_validateDevServer() {
49-
if (this.webpackConfig.useVersioning && this.webpackConfig.useDevServer()) {
50+
if (!this.webpackConfig.useDevServer()) {
51+
return;
52+
}
53+
54+
if (this.webpackConfig.useVersioning) {
5055
throw new Error('Don\'t enable versioning with the dev-server. A good setting is Encore.enableVersioning(Encore.isProduction()).');
5156
}
57+
58+
/*
59+
* An absolute publicPath is incompatible with webpackDevServer.
60+
* This is because we want to *change* the publicPath to point
61+
* to the webpackDevServer URL (e.g. http://localhost:8080/).
62+
* There are some valid use-cases for not wanting this behavior
63+
* (see #59), but we want to warn the user.
64+
*/
65+
if (this.webpackConfig.publicPath.includes('://')) {
66+
logger.warning(`Passing an absolute URL to setPublicPath() *and* using the dev-server can cause issues. Your assets will load from the publicPath (${this.webpackConfig.publicPath}) instead of from the dev server URL (${this.webpackConfig.runtimeConfig.devServerUrl}).`);
67+
}
5268
}
5369
}
5470

lib/logger.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* This file is part of the Symfony package.
3+
*
4+
* (c) Fabien Potencier <[email protected]>
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
'use strict';
11+
12+
const chalk = require('chalk');
13+
let isVerbose = false;
14+
let quiet = false;
15+
let messages = {
16+
debug: [],
17+
warning: [],
18+
};
19+
20+
function log(message) {
21+
if (quiet) {
22+
return;
23+
}
24+
25+
console.log(message);
26+
}
27+
28+
module.exports = {
29+
debug(message) {
30+
messages.debug.push(message);
31+
32+
if (isVerbose) {
33+
log(`${chalk.bgBlack.white(' DEBUG ')} ${message}`);
34+
}
35+
},
36+
37+
warning(message) {
38+
messages.warning.push(message);
39+
40+
log(`${chalk.bgYellow.black(' WARNING ')} ${chalk.yellow(message)}`);
41+
},
42+
43+
clearMessages() {
44+
messages.debug = [];
45+
messages.warning = [];
46+
},
47+
48+
getMessages() {
49+
return messages;
50+
},
51+
52+
quiet() {
53+
quiet = true;
54+
},
55+
56+
verbose() {
57+
isVerbose = true;
58+
}
59+
};

test/WebpackConfig.js

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,6 @@ describe('WebpackConfig object', () => {
104104
config.setPublicPath('foo/');
105105
}).to.throw('The value passed to setPublicPath() must start with "/"');
106106
});
107-
108-
it('Setting to a URL when using devServer throws an error', () => {
109-
const config = createConfig();
110-
config.runtimeConfig.useDevServer = true;
111-
112-
expect(() => {
113-
config.setPublicPath('https://examplecdn.com');
114-
}).to.throw('You cannot pass an absolute URL to setPublicPath() and use the dev-server');
115-
});
116107
});
117108

118109
describe('getRealPublicPath', () => {
@@ -142,11 +133,10 @@ describe('WebpackConfig object', () => {
142133
expect(config.getRealPublicPath()).to.equal('/public/');
143134
});
144135

145-
it('devServer & devServerKeepPublicPath option allows absolute publicPath', () => {
136+
it('devServer does not prefix if publicPath is absolute', () => {
146137
const config = createConfig();
147138
config.runtimeConfig.useDevServer = true;
148139
config.runtimeConfig.devServerUrl = 'http://localhost:8080/';
149-
config.runtimeConfig.devServerKeepPublicPath = true;
150140
config.setPublicPath('http://coolcdn.com/public');
151141
config.setManifestKeyPrefix('/public/');
152142

test/config/validator.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ const expect = require('chai').expect;
1313
const WebpackConfig = require('../../lib/WebpackConfig');
1414
const RuntimeConfig = require('../../lib/config/RuntimeConfig');
1515
const validator = require('../../lib/config/validator');
16+
const logger = require('../../lib/logger');
17+
18+
logger.quiet();
1619

1720
function createConfig() {
1821
const runtimeConfig = new RuntimeConfig();
@@ -65,4 +68,19 @@ describe('The validator function', () => {
6568
validator(config);
6669
}).to.throw('Don\'t enable versioning with the dev-server');
6770
});
71+
72+
it('warning with dev-server and absolute publicPath', () => {
73+
const config = createConfig();
74+
config.outputPath = '/tmp/public/build';
75+
config.setPublicPath('https://absoluteurl.com/build');
76+
config.setManifestKeyPrefix('build/');
77+
config.addEntry('main', './main');
78+
config.runtimeConfig.useDevServer = true;
79+
80+
logger.clearMessages();
81+
validator(config);
82+
83+
expect(logger.getMessages().warning).to.have.lengthOf(1);
84+
expect(logger.getMessages().warning[0]).to.include('Passing an absolute URL to setPublicPath() *and* using the dev-server can cause issues');
85+
});
6886
});

0 commit comments

Comments
 (0)