Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add helper-compilation-targets docs #2484

Merged
merged 5 commits into from Apr 20, 2021
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
240 changes: 240 additions & 0 deletions docs/helper-compilation-targets.md
@@ -0,0 +1,240 @@
---
id: babel-helper-compilation-targets
title: @babel/helper-compilation-targets
sidebar_label: helper-compilation-targets
---

`@babel/helper-compilation-targets` is a helper set working with compilation targets and compat tables. It is used by `@babel/preset-env` to determine which plugin should be enabled based on the give [`targets`](options.md#targets) option.
JLHwung marked this conversation as resolved.
Show resolved Hide resolved

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

## filterItems

```typescript
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> | null,

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

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

Given a compat data table `list` (i.e. `@babel/compat-data`) and [browser targets](preset-env.md#targets) `targets`, return a set of required plugins.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we need a doc for @babel/compat-data later


**Example**

```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,
},
null,
null,
new Map([["transform-feature-2", "syntax-feature-2"]])
);
```

> When a new ES feature reaches stage-4, it will be matured in `@babel/parser`, which means it will always be parsed regardless of the plugin. However we need the syntax plugin for older `@babel/parser`.

## getTargets

```typescript
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;
```

Normalize user specified `targets` to a list of supported targets. See also (`@babel/preset-env`)[preset-env.md#options] for `GetTargetsOption`

**Example**

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

An empty compilation target is equivalent to [force all transforms](preset-env.md#forceAllTransforms). The default compilation targets will changed to browserlists [`defaults, not IE 11`](https://runkit.com/jlhwung/605cd58b2c44c6001a463717) in Babel 8.
JLHwung marked this conversation as resolved.
Show resolved Hide resolved

```javascript
// Return compilation targets with ES Module support
/* 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,
});
```

The ES Module compat data is generated from [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export#browser_compatibility).

## isRequired

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

Given browser targets `targets`, query the `compatData` whether plugin `name` is required for compilation. When `compatData` is not specified, the default data source is `@babel/compat-data`

**Example**

```javascript
// 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
);
};
```

Plugin authors can use `isRequired` to optimize plugin output given different `targets`:

```javascript
// a naive plugin replace `a.b` to `a != null && 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.isPattern("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 != null && a.b`
path.replaceWith(api.templates`a?.b`);
} else {
path.replaceWith(api.templates`a != null && ${path.node}`);
}
}
},
},
};
};
```