From 70e8b8985d17bfb18c97ae84beae72264f921095 Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Thu, 26 Sep 2024 19:42:42 +0200 Subject: [PATCH] Add options configuration callback to Encore.enableReactPreset() --- index.js | 12 ++++++++++-- lib/WebpackConfig.js | 12 +++++++++++- lib/loaders/babel.js | 11 +++++++---- test/WebpackConfig.js | 17 +++++++++++++++++ test/loaders/babel.js | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 79 insertions(+), 7 deletions(-) diff --git a/index.js b/index.js index a5538140..8d3ea409 100644 --- a/index.js +++ b/index.js @@ -1106,10 +1106,18 @@ class Encore { * * https://babeljs.io/docs/plugins/preset-react/ * + * You can configure the preset by passing a callback: + * ``` + * Encore.enableReactPreset(function(options) { + * // https://babeljs.io/docs/babel-preset-react/#options + * options.development = !Encore.isProduction(); + * }); + * ``` + * * @returns {Encore} */ - enableReactPreset() { - webpackConfig.enableReactPreset(); + enableReactPreset(callback = () => {}) { + webpackConfig.enableReactPreset(callback); return this; } diff --git a/lib/WebpackConfig.js b/lib/WebpackConfig.js index 0fb34d6b..7a62616d 100644 --- a/lib/WebpackConfig.js +++ b/lib/WebpackConfig.js @@ -159,6 +159,8 @@ class WebpackConfig { /** @type {OptionsCallback} */ this.babelPresetEnvOptionsCallback = () => {}; /** @type {OptionsCallback} */ + this.babelReactPresetOptionsCallback = () => {}; + /** @type {OptionsCallback} */ this.cssLoaderConfigurationCallback = () => {}; /** @type {OptionsCallback} */ this.styleLoaderConfigurationCallback = () => {}; @@ -793,8 +795,16 @@ class WebpackConfig { this.persistentCacheCallback = callback; } - enableReactPreset() { + /** + * @param {OptionsCallback} callback + */ + enableReactPreset(callback = () => {}) { + if (typeof callback !== 'function') { + throw new Error('Argument 1 to enableForkedTypeScriptTypesChecking() must be a callback function.'); + } + this.useReact = true; + this.babelReactPresetOptionsCallback = callback; } enablePreactPreset(options = {}) { diff --git a/lib/loaders/babel.js b/lib/loaders/babel.js index 8ba0b42d..dc62e1f9 100644 --- a/lib/loaders/babel.js +++ b/lib/loaders/babel.js @@ -70,10 +70,13 @@ module.exports = { if (webpackConfig.useReact) { loaderFeatures.ensurePackagesExistAndAreCorrectVersion('react'); - babelConfig.presets.push([require.resolve('@babel/preset-react'), { - // TODO: To remove when Babel 8, "automatic" will become the default value - runtime: 'automatic', - }]); + babelConfig.presets.push([ + require.resolve('@babel/preset-react'), + applyOptionsCallback(webpackConfig.babelReactPresetOptionsCallback, { + // TODO: To remove when Babel 8, "automatic" will become the default value + runtime: 'automatic', + }) + ]); } if (webpackConfig.usePreact) { diff --git a/test/WebpackConfig.js b/test/WebpackConfig.js index c3b8836c..656ee5f4 100644 --- a/test/WebpackConfig.js +++ b/test/WebpackConfig.js @@ -982,6 +982,23 @@ describe('WebpackConfig object', () => { }); }); + describe('enableReactPreset', () => { + it('Calling method sets it', () => { + const config = createConfig(); + const testCallback = () => {}; + config.enableReactPreset(testCallback); + expect(config.babelReactPresetOptionsCallback).to.equal(testCallback); + }); + + it('Calling with non-callback throws an error', () => { + const config = createConfig(); + + expect(() => { + config.enableReactPreset('FOO'); + }).to.throw('must be a callback function'); + }); + }) + describe('enablePreactPreset', () => { it('Without preact-compat', () => { const config = createConfig(); diff --git a/test/loaders/babel.js b/test/loaders/babel.js index ab654f51..a21b47b5 100644 --- a/test/loaders/babel.js +++ b/test/loaders/babel.js @@ -94,6 +94,40 @@ describe('loaders/babel', () => { expect(actualLoaders[0].options.presets[2]).to.equal('foo'); }); + it('getLoaders() with react and callback', () => { + const config = createConfig(); + config.enableReactPreset((options) => { + options.development = !config.isProduction(); + }); + + config.configureBabel(function(babelConfig) { + babelConfig.presets.push('foo'); + }); + + const actualLoaders = babelLoader.getLoaders(config); + + // env, react & foo + expect(actualLoaders[0].options.presets).to.have.lengthOf(3); + expect(actualLoaders[0].options.presets[0]).to.deep.equal([ + require.resolve('@babel/preset-env'), + { + corejs: null, + modules: false, + targets: {}, + useBuiltIns: false, + }, + ]); + expect(actualLoaders[0].options.presets[1]).to.deep.equal([ + require.resolve('@babel/preset-react'), + { + runtime: 'automatic', + development: true, + } + ]); + // foo is also still there, not overridden + expect(actualLoaders[0].options.presets[2]).to.equal('foo'); + }); + it('getLoaders() with preact', () => { const config = createConfig(); config.enablePreactPreset();