unknown: .targets is not allowed in preset options

Bug Report

Current behavior

Upgrading our preset to babel 7.13.x, and trying to hoist the targets options at the preset root, following the blog post and the docs, I get the following error:

[BABEL] unknown: .targets is not allowed in preset options

  at node_modules/@babel/core/lib/config/validation/options.js:100:13
      at Array.forEach (<anonymous>)
  at validateNested (node_modules/@babel/core/lib/config/validation/options.js:92:21)
  at validate (node_modules/@babel/core/lib/config/validation/options.js:83:10)
  at node_modules/@babel/core/lib/config/full.js:328:36
  at cachedFunction (node_modules/@babel/core/lib/config/caching.js:62:27)
      at cachedFunction.next (<anonymous>)
  at evaluateSync (node_modules/gensync/index.js:251:28)
  at sync (node_modules/gensync/index.js:89:14)
  at loadPresetDescriptor (node_modules/@babel/core/lib/config/full.js:317:18)

GitHub Repo

Gandi/babel-preset-gandi#29

Input Code

module.exports = (context, options = {}) => {
  let targets = {
    browsers: ['last 2 versions', '> 1%%', 'Firefox ESR', 'not dead'],
    ...options.targets,
  };

  let envOpts = {
    modules: options.modules,
    bugfixes: targets.esmodules === true,
  };

  let runtimeOpts = {
    corejs: 2,
    helpers: true,
    regenerator: true,
    version: '7.13.0', // 1
  };

  let presets = [
    ['@babel/preset-env', envOpts],
    '@babel/preset-react',
    '@babel/preset-flow',
  ];

  let plugins = [
    '@babel/plugin-transform-flow-strip-types', 
    ['@babel/plugin-proposal-class-properties', { loose: true }],
    ['@babel/plugin-transform-runtime', runtimeOpts],
  ];

  return {
    targets,
    presets,
    plugins,
  };
};

Expected behavior
No error…

Environment

System:
  OS: Linux 5.8 Ubuntu 20.04.2 LTS (Focal Fossa)
Binaries:
  Node: 12.16.2 - /tmp/fnm-shell-1022461/bin/node
  Yarn: 1.22.5 - /usr/bin/yarn
  npm: 6.14.9 - /tmp/fnm-shell-1022461/bin/npm
npmPackages:
  @babel/core: ^7.13.1 => 7.13.1 
  @babel/plugin-proposal-class-properties: ^7.13.0 => 7.13.0 
  @babel/plugin-transform-runtime: ^7.13.5 => 7.13.5 
  @babel/preset-env: ^7.13.5 => 7.13.5 
  @babel/preset-flow: ^7.12.13 => 7.12.13 
  @babel/preset-react: ^7.12.13 => 7.12.13 
  @babel/runtime-corejs2: ^7.13.4 => 7.13.4 
  jest: ^26.6.3 => 26.6.3 

1 possible answer(s) on “unknown: .targets is not allowed in preset options

  1. For now we could only allow targets in configuration files.

    This is because presets (such as @babel/preset-env) need to be consumers of targets and thus they cannot define new targets (because we need to know the targets and pass them to the presets before calling the presets).

    The docs mention that this is only Allowed in Babel's programmatic options, or in config files (not in presets), maybe we could make that message more prominent.

    We might relax this restriction in the future, but for now there isn’t a clear way to do so ☹️.

    (also, usually only the authors of the app knows what browsers they want to target, and not the authors of the presets that the final developers are using).