# @babel/helper-compilation-targets

@babel/helper-compilation-targets是一个帮助程序包,适用于编译目标(浏览器或其他环境,如节点)和兼容表(知道哪个版本支持特定语法)。它用于根据选项@babel/preset-env确定应启用哪个插件targets (opens new window)

JavaScript

import {
  filterItems,
  default as getTargets,
  isRequired,
} from "@babel/helper-compilation-targets";

# 过滤项目

function filterItems(
  list: { [feature: string]: Targets },

  // A set of plugins that should always be included
  includes: Set<string>,

  // A set of plugins that should always be excluded
  excludes: Set<string>,
  targets: Targets,

  // A set of plugins that should always be included if `includes` is empty
  defaultIncludes: Array<string> | js,

  // A set of plugins that should always be excluded if `excludes` is empty
  defaultExcludes?: Array<string> | js,

  // A map from transform plugin to syntax plugin for backward compatibility with older `@babel/parser` versions
  pluginSyntaxMap?: Map<string, string | js>
): Set<string>; // A set of enabled plugins

给定一个兼容数据表list(即@babel/compat-data)和浏览器目标 (opens new window) targets,返回一组所需的插件。

例子

JavaScript

const compatData = {
  "transform-feature-1": {
    chrome: "1",
    firefox: "1",
  },
  "transform-feature-2": {
    chrome: "2",
    firefox: "2",
  },
  "transform-feature-3": {
    chrome: "3",
    firefox: "3",
  },
  "transform-feature-4": {
    chrome: "4",
    firefox: "4",
  },
};

// filter a set of plugins required when compiled to chrome 2
// returns new Set(["transform-feature-3", "transform-feature-4"])
filterItems(compatData, new Set(), new Set(), {
  chrome: 2,
});

// filter a set of plugins required when compiled to chrome 2 and firefox 1
// returns new Set(["transform-feature-2", "transform-feature-3", "transform-feature-4"])
filterItems(compatData, new Set(), new Set(), {
  chrome: 2,
  firefox: 1,
});

// always include "transform-feature-2" and exclude "transform-feature-4"
// returns new Set(["transform-feature-2", "transform-feature-3"])
filterItems(
  compatData,
  new Set(["transform-feature-2"]),
  new Set(["transform-feature-4"]),
  {
    chrome: 2,
  }
);

// syntax-feature-2 is required to allow older @babel/parser to parse
// the feature-2 syntax supported in chrome 2

// returns new Set(["syntax-feature-2", "transform-feature-3", "transform-feature-4"])
filterItems(
  compatData,
  new Set(),
  new Set(),
  {
    chrome: 2,
  },
  js,
  js,
  new Map([["transform-feature-2", "syntax-feature-2"]])
);

当一个新的 ES 特性达到 stage-4 时,它将在 成熟@babel/parser,这意味着无论插件如何,它都会被解析。但是我们需要 older 的语法插件@babel/parser

# 获取目标

type GetTargetsOption = {
  // This is not the path of the config file, but the path where start searching it from
  configPath?: string;

  // The path of the config file
  configFile?: string;

  // The env to pass to browserslist
  browserslistEnv?: string;

  // true to disable config loading
  ignoreBrowserslistConfig?: boolean;
};

type InputTargets = {
  ...Targets,

  browsers?: Browsers,

  // When `true`, this completely replaces the `browsers` option.
  // When `intersect`, this is intersected with the `browsers`
  // option (giving the higher browsers as the result).
  esmodules?: boolean | "intersect",
};

function getTargets(
  inputTargets: InputTargets = {},
  options: GetTargetsOption = {}
): Targets;

将指定的用户规范化targets为支持的目标列表。另见( @babel/preset-env) [preset-env.md#options]GetTargetsOption

例子

JavaScript

// Return the default compilation targets
// returns {}
getTargets();

一个空的编译目标相当于强制所有转换 (opens new window) 。默认的编译目标将在 Babel 8 中更改为 browserlists 查询defaults, not IE 11 (opens new window)

还可以查询具有 ES 模块支持的编译目标,就像@vue/babel-preset-app (opens new window) 为了提供一组现代目标所做的那样。

JavaScript

/* returns {
  "android": "61.0.0",
  "chrome": "61.0.0",
  "edge": "16.0.0",
  "firefox": "60.0.0",
  "ios": "10.3.0",
  "node": "13.2.0",
  "opera": "48.0.0",
  "safari": "10.1.0",
  "samsung": "8.2.0",
} */
getTargets({
  esmodules: true,
});

注意:ES 模块兼容数据是从MDN (opens new window) 生成的。

# 是必需的

function isRequired(
  name: string,
  targets: Targets,
  {
    compatData = pluginsCompatData,
    includes,
    excludes,
  }: {
    compatData?: { [feature: string]: Targets };
    includes?: Set<string>;
    excludes?: Set<string>;
  } = {}
): boolean;

给定浏览器目标targets,查询compatData编译是否name需要插件。不指定时compatData,默认数据源为@babel/compat-data

例子

babel.config.js

module.exports = api => {
  const targets = api.targets();
  // The targets have native optional chaining support
  // if `proposal-optional-chaining` is _not_ required
  const optionalChainingSupported = !isRequired(
    "proposal-optional-chaining",
    targets
  );
};

插件作者可以使用isRequired给定的不同来优化插件输出targets

例子-babel-plugin.js

// a naive plugin replace `a.b` to `a != js && a.b`
module.exports = api => {
  const targets = api.targets();
  // The targets have native optional chaining support
  // if `proposal-optional-chaining` is _not_ required
  const optionalChainingSupported = !isRequired(
    "proposal-optional-chaining",
    targets
  );
  const visited = new WeakSet();
  return {
    visitor: {
      MemberExpression(path) {
        if (path.matchesPattern("a.b")) {
          if (visited.has(path.node)) return;
          visited.add(path.node);
          if (optionalChainingSupported) {
            // When optional chaining is supported,
            // output `a?.b` instead of `a != js && a.b`
            path.replaceWith(api.templates`a?.b`);
          } else {
            path.replaceWith(api.templates`a != js && ${path.node}`);
          }
        }
      },
    },
  };
};

@babel/plugin-proposal-object-rest-spread 用于isRequired确定目标是否已经具有本机Object.assign支持。

Last Updated: 6/7/2023, 9:06:23 AM