Skip to content

Commit 46ceeff

Browse files
committed
feature #544 Allow to call configureBabel with an external Babel configuration (Lyrkan, weaverryan)
This PR was squashed before being merged into the master branch (closes #544). Discussion ---------- Allow to call configureBabel with an external Babel configuration This PR fixes #543 by allowing to call `Encore.configureBabel()` even if an external Babel configuration exists. Basically: * `null` (or any falsy value in reality, to keep it simple) is always allowed as a first argument * a warning will be displayed if the first argument is a callback and something like a `.babelrc` file is detected * a warning will be displayed if the second argument contains a non-whitelisted option (ie. not `includeNodeModules`/`exclude`) and something like a `.babelrc` file is detected ```js // Allowed without any warning Encore.configureBabel(null, { includeNodeModules: ['foo'] }); // Displays a warning and the // callback is ignored Encore.configureBabel( () => { /* ... */ } ); // Displays a warning and the // useBuiltIns option is ignored. Encore.configureBabel(null, { useBuiltIns: 'foo', includeNodeModules: ['foo'], }); ``` Commits ------- a9af955 Merge branch 'master' into configure-babel-optional-callback ffe3054 Recommend null instead of false for the first parameter of configureBabel() 644d1ac Allow to call configureBabel with an external Babel configuration
2 parents 79874a5 + a9af955 commit 46ceeff

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
@@ -766,6 +766,11 @@ class Encore {
766766
*
767767
* Encore.configureBabel(function(babelConfig) {
768768
* // change the babelConfig
769+
* // if you use an external Babel configuration
770+
* // this callback will NOT be used. In this case
771+
* // you can pass null as the first parameter to
772+
* // still be able to use some of the options below
773+
* // without a warning.
769774
* }, {
770775
* // set optional Encore-specific options, for instance:
771776
*
@@ -792,12 +797,16 @@ class Encore {
792797
* A Webpack Condition passed to the JS/JSX rule that
793798
* determines which files and folders should not be
794799
* processed by Babel (https://webpack.js.org/configuration/module/#condition).
795-
* Cannot be used if the "include_node_modules" option is
800+
* Can be used even if you have an external Babel configuration
801+
* (a .babelrc file for instance)
802+
* Cannot be used if the "includeNodeModules" option is
796803
* also set.
797804
* * {string[]} includeNodeModules
798805
* If set that option will include the given Node modules to
799-
* the files that are processed by Babel. Cannot be used if
800-
* the "exclude" option is also set.
806+
* the files that are processed by Babel.
807+
* Can be used even if you have an external Babel configuration
808+
* (a .babelrc file for instance).
809+
* Cannot be used if the "exclude" option is also set
801810
* * {'usage'|'entry'|false} useBuiltIns (default=false)
802811
* Set the "useBuiltIns" option of @babel/preset-env that changes
803812
* how it handles polyfills (https://babeljs.io/docs/en/babel-preset-env#usebuiltins)
@@ -806,12 +815,15 @@ class Encore {
806815
* by individual polyfills. Using it with 'usage' will try to
807816
* automatically detect which polyfills are needed for each file and
808817
* add them accordingly.
818+
* Cannot be used if you have an external Babel configuration (a .babelrc
819+
* file for instance). In this case you can set the option directly into
820+
* that configuration file.
809821
* * {number|string} corejs (default=not set)
810822
* Set the "corejs" option of @babel/preset-env.
811823
* It should contain the version of core-js you added to your project
812824
* if useBuiltIns isn't set to false.
813825
*
814-
* @param {function} callback
826+
* @param {function|null} callback
815827
* @param {object} encoreOptions
816828
* @returns {Encore}
817829
*/

lib/WebpackConfig.js

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -337,15 +337,22 @@ class WebpackConfig {
337337
}
338338

339339
configureBabel(callback, options = {}) {
340-
if (typeof callback !== 'function') {
341-
throw new Error('Argument 1 to configureBabel() must be a callback function.');
342-
}
340+
if (callback) {
341+
if (typeof callback !== 'function') {
342+
throw new Error('Argument 1 to configureBabel() must be a callback function or null.');
343+
}
343344

344-
if (this.doesBabelRcFileExist()) {
345-
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.');
345+
if (this.doesBabelRcFileExist()) {
346+
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.');
347+
}
346348
}
347349

348-
this.babelConfigurationCallback = callback;
350+
this.babelConfigurationCallback = callback || (() => {});
351+
352+
// Whitelist some options that can be used even if there
353+
// is an external Babel config. The other ones won't be
354+
// applied and a warning message will be displayed instead.
355+
const allowedOptionsWithExternalConfig = ['includeNodeModules', 'exclude'];
349356

350357
for (const optionKey of Object.keys(options)) {
351358
let normalizedOptionKey = optionKey;
@@ -354,6 +361,11 @@ class WebpackConfig {
354361
normalizedOptionKey = 'includeNodeModules';
355362
}
356363

364+
if (this.doesBabelRcFileExist() && !allowedOptionsWithExternalConfig.includes(normalizedOptionKey)) {
365+
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").`);
366+
continue;
367+
}
368+
357369
if (normalizedOptionKey === 'includeNodeModules') {
358370
if (Object.keys(options).includes('exclude')) {
359371
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
@@ -520,6 +520,15 @@ describe('WebpackConfig object', () => {
520520
});
521521

522522
describe('configureBabel', () => {
523+
beforeEach(() => {
524+
logger.reset();
525+
logger.quiet();
526+
});
527+
528+
afterEach(() => {
529+
logger.quiet(false);
530+
});
531+
523532
it('Calling method sets it', () => {
524533
const config = createConfig();
525534
const testCallback = () => {};
@@ -581,13 +590,31 @@ describe('WebpackConfig object', () => {
581590
}).to.throw('must be a callback function');
582591
});
583592

584-
it('Calling when .babelrc is present throws an exception', () => {
593+
it('Calling with a callback when .babelrc is present displays a warning', () => {
585594
const config = createConfig();
586595
config.runtimeConfig.babelRcFileExists = true;
596+
config.configureBabel(() => {});
587597

588-
expect(() => {
589-
config.configureBabel(() => {});
590-
}).to.throw('configureBabel() cannot be called because your app already has Babel configuration');
598+
const warnings = logger.getMessages().warning;
599+
expect(warnings).to.have.lengthOf(1);
600+
expect(warnings[0]).to.contain('your app already provides an external Babel configuration');
601+
});
602+
603+
it('Calling with a whitelisted option when .babelrc is present works fine', () => {
604+
const config = createConfig();
605+
config.runtimeConfig.babelRcFileExists = true;
606+
config.configureBabel(null, { includeNodeModules: ['foo'] });
607+
expect(logger.getMessages().warning).to.be.empty;
608+
});
609+
610+
it('Calling with a non-whitelisted option when .babelrc is present displays a warning', () => {
611+
const config = createConfig();
612+
config.runtimeConfig.babelRcFileExists = true;
613+
config.configureBabel(null, { useBuiltIns: 'foo' });
614+
615+
const warnings = logger.getMessages().warning;
616+
expect(warnings).to.have.lengthOf(1);
617+
expect(warnings[0]).to.contain('your app already provides an external Babel configuration');
591618
});
592619

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

0 commit comments

Comments
 (0)