Skip to content

Commit 644d1ac

Browse files
committed
Allow to call configureBabel with an external Babel configuration
1 parent 0facc4d commit 644d1ac

File tree

3 files changed

+65
-14
lines changed

3 files changed

+65
-14
lines changed

index.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,11 @@ class Encore {
785785
*
786786
* Encore.configureBabel(function(babelConfig) {
787787
* // change the babelConfig
788+
* // if you use an external Babel configuration
789+
* // this callback will NOT be used. In this case
790+
* // you can pass false as the first parameter to
791+
* // still be able to use some of the options below
792+
* // without a warning.
788793
* }, {
789794
* // set optional Encore-specific options, for instance:
790795
*
@@ -806,12 +811,16 @@ class Encore {
806811
* A Webpack Condition passed to the JS/JSX rule that
807812
* determines which files and folders should not be
808813
* processed by Babel (https://webpack.js.org/configuration/module/#condition).
809-
* Cannot be used if the "include_node_modules" option is
814+
* Can be used even if you have an external Babel configuration
815+
* (a .babelrc file for instance)
816+
* Cannot be used if the "includeNodeModules" option is
810817
* also set.
811818
* * {string[]} includeNodeModules
812819
* If set that option will include the given Node modules to
813-
* the files that are processed by Babel. Cannot be used if
814-
* the "exclude" option is also set.
820+
* the files that are processed by Babel.
821+
* Can be used even if you have an external Babel configuration
822+
* (a .babelrc file for instance).
823+
* Cannot be used if the "exclude" option is also set
815824
* * {'usage'|'entry'|false} useBuiltIns (default='entry')
816825
* Set the "useBuiltIns" option of @babel/preset-env that changes
817826
* how it handles polyfills (https://babeljs.io/docs/en/babel-preset-env#usebuiltins)
@@ -820,8 +829,11 @@ class Encore {
820829
* by individual polyfills. Using it with 'usage' will try to
821830
* automatically detect which polyfills are needed for each file and
822831
* add them accordingly.
832+
* Cannot be used if you have an external Babel configuration (a .babelrc
833+
* file for instance). In this case you can set the option directly into
834+
* that configuration file.
823835
*
824-
* @param {function} callback
836+
* @param {function|false} callback
825837
* @param {object} encoreOptions
826838
* @returns {Encore}
827839
*/

lib/WebpackConfig.js

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -329,15 +329,22 @@ class WebpackConfig {
329329
}
330330

331331
configureBabel(callback, options = {}) {
332-
if (typeof callback !== 'function') {
333-
throw new Error('Argument 1 to configureBabel() must be a callback function.');
334-
}
332+
if (callback) {
333+
if (typeof callback !== 'function') {
334+
throw new Error('Argument 1 to configureBabel() must be a callback function or null.');
335+
}
335336

336-
if (this.doesBabelRcFileExist()) {
337-
throw new Error('configureBabel() cannot be called because your app already has Babel configuration (a `.babelrc` file, `.babelrc.js` file or `babel` key in `package.json`). Either put all of your Babel configuration in that file, or delete it and use this function.');
337+
if (this.doesBabelRcFileExist()) {
338+
logger.warning('The "callback" argument of configureBabel() will not be used because your app already provides an external Babel configuration (a ".babelrc" file, ".babelrc.js" file or "babel" key in "package.json"). Use null as a first argument to remove that warning.');
339+
}
338340
}
339341

340-
this.babelConfigurationCallback = callback;
342+
this.babelConfigurationCallback = callback || (() => {});
343+
344+
// Whitelist some options that can be used even if there
345+
// is an external Babel config. The other ones won't be
346+
// applied and a warning message will be displayed instead.
347+
const allowedOptionsWithExternalConfig = ['includeNodeModules', 'exclude'];
341348

342349
for (const optionKey of Object.keys(options)) {
343350
let normalizedOptionKey = optionKey;
@@ -346,6 +353,11 @@ class WebpackConfig {
346353
normalizedOptionKey = 'includeNodeModules';
347354
}
348355

356+
if (this.doesBabelRcFileExist() && !allowedOptionsWithExternalConfig.includes(normalizedOptionKey)) {
357+
logger.warning(`The "${normalizedOptionKey}" option of configureBabel() will not be used because your app already provides an external Babel configuration (a ".babelrc" file, ".babelrc.js" file or "babel" key in "package.json").`);
358+
continue;
359+
}
360+
349361
if (normalizedOptionKey === 'includeNodeModules') {
350362
if (Object.keys(options).includes('exclude')) {
351363
throw new Error('"includeNodeModules" and "exclude" options can\'t be used together when calling configureBabel().');

test/WebpackConfig.js

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,15 @@ describe('WebpackConfig object', () => {
538538
});
539539

540540
describe('configureBabel', () => {
541+
beforeEach(() => {
542+
logger.reset();
543+
logger.quiet();
544+
});
545+
546+
afterEach(() => {
547+
logger.quiet(false);
548+
});
549+
541550
it('Calling method sets it', () => {
542551
const config = createConfig();
543552
const testCallback = () => {};
@@ -599,13 +608,31 @@ describe('WebpackConfig object', () => {
599608
}).to.throw('must be a callback function');
600609
});
601610

602-
it('Calling when .babelrc is present throws an exception', () => {
611+
it('Calling with a callback when .babelrc is present displays a warning', () => {
603612
const config = createConfig();
604613
config.runtimeConfig.babelRcFileExists = true;
614+
config.configureBabel(() => {});
605615

606-
expect(() => {
607-
config.configureBabel(() => {});
608-
}).to.throw('configureBabel() cannot be called because your app already has Babel configuration');
616+
const warnings = logger.getMessages().warning;
617+
expect(warnings).to.have.lengthOf(1);
618+
expect(warnings[0]).to.contain('your app already provides an external Babel configuration');
619+
});
620+
621+
it('Calling with a whitelisted option when .babelrc is present works fine', () => {
622+
const config = createConfig();
623+
config.runtimeConfig.babelRcFileExists = true;
624+
config.configureBabel(false, { includeNodeModules: ['foo'] });
625+
expect(logger.getMessages().warning).to.be.empty;
626+
});
627+
628+
it('Calling with a non-whitelisted option when .babelrc is present displays a warning', () => {
629+
const config = createConfig();
630+
config.runtimeConfig.babelRcFileExists = true;
631+
config.configureBabel(false, { useBuiltIns: 'foo' });
632+
633+
const warnings = logger.getMessages().warning;
634+
expect(warnings).to.have.lengthOf(1);
635+
expect(warnings[0]).to.contain('your app already provides an external Babel configuration');
609636
});
610637

611638
it('Pass invalid config', () => {

0 commit comments

Comments
 (0)