Skip to content

Commit

Permalink
feat: allow to opt-out of default babel plugins and presets
Browse files Browse the repository at this point in the history
  • Loading branch information
sastan committed Nov 7, 2019
1 parent 80059cb commit 801fbd7
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 22 deletions.
9 changes: 9 additions & 0 deletions README.md
Expand Up @@ -82,6 +82,7 @@ In comparison with the [official plugin](https://github.com/rollup/rollup-plugin
- [Full list of plugin options](#full-list-of-plugin-options)
- [`transpiler`](#transpiler)
- [`babelConfig`](#babelconfig)
- [`noBabelConfigCustomization`](#nobabelconfigcustomization)
- [`tsconfig`](#tsconfig)
- [`browserslist`](#browserslist)
- [`cwd`](#cwd)
Expand Down Expand Up @@ -443,6 +444,12 @@ Type: `string | Partial<IBabelInputOptions>`

This option will only be respected when `"babel"` is being used as the `transpiler` and can be used to provide a [Babel config](https://babeljs.io/docs/en/options) or a path to one.

#### `noBabelConfigCustomization`

Type: `boolean`

If this option is `true`, **no** [default presets or plugins](#default-babel-plugins) are applied to the babel config. The [ignored/overridden Babel options](#ignoredoverridden-babel-options) are nevertheless applied.

#### `tsconfig`

Type: `string | Partial<CompilerOptions> | Partial<Record<keyof CompilerOptions, string | number | boolean>> | ParsedCommandLine | TsConfigResolver | TsConfigResolverWithFileName`
Expand Down Expand Up @@ -557,6 +564,8 @@ By default, the plugin will conditionally apply the `@babel/preset-env` preset i

If you provide these presets or plugins yourself through the found or provided Babel config, _your_ config options will take precedence.

In case that this is not enough for you setting [`noBabelConfigCustomization`](#nobabelconfigcustomization) disables these defaults.

Here's table with a full overview of the specifics:

| Preset/Plugin | Condition | Reason |
Expand Down
1 change: 1 addition & 0 deletions src/plugin/i-typescript-plugin-options.ts
Expand Up @@ -55,6 +55,7 @@ export interface ITypescriptPluginTypescriptOptions extends ITypescriptPluginBas

export interface ITypescriptPluginBabelOptions extends ITypescriptPluginBaseOptions {
transpiler: "babel";
noBabelConfigCustomization?: boolean;
babelConfig?: string | Partial<IBabelInputOptions>;
}

Expand Down
1 change: 1 addition & 0 deletions src/plugin/typescript-plugin.ts
Expand Up @@ -189,6 +189,7 @@ export default function typescriptRollupPlugin(pluginInputOptions: Partial<Types
const babelConfigResult = getBabelConfig({
cwd,
babelConfig: pluginOptions.babelConfig,
noBabelConfigCustomization: pluginOptions.noBabelConfigCustomization,
forcedOptions: getForcedBabelOptions({cwd, pluginOptions, rollupInputOptions, browserslist: computedBrowserslist}),
defaultOptions: getDefaultBabelOptions({pluginOptions, rollupInputOptions, browserslist: computedBrowserslist}),
browserslist: computedBrowserslist,
Expand Down
2 changes: 2 additions & 0 deletions src/util/get-babel-config/get-babel-config-options.ts
@@ -1,3 +1,4 @@
import {ITypescriptPluginBabelOptions} from "../../plugin/i-typescript-plugin-options";
import {IGetForcedBabelOptionsResult} from "../get-forced-babel-options/i-get-forced-babel-options-result";
import {IGetDefaultBabelOptionsResult} from "../get-default-babel-options/i-get-default-babel-options-result";
import {InputOptions} from "rollup";
Expand All @@ -8,4 +9,5 @@ export interface GetBabelConfigOptions extends FindBabelConfigOptions {
rollupInputOptions: InputOptions;
forcedOptions?: IGetForcedBabelOptionsResult;
defaultOptions?: IGetDefaultBabelOptionsResult;
noBabelConfigCustomization?: ITypescriptPluginBabelOptions["noBabelConfigCustomization"];
}
110 changes: 88 additions & 22 deletions src/util/get-babel-config/get-babel-config.ts
Expand Up @@ -17,22 +17,39 @@ import {findBabelConfig} from "./find-babel-config";

// tslint:disable:no-any

interface IBabelPlugin {
key: string;
}

function getBabelItemId(item: IBabelConfigItem | IBabelPlugin): string {
if ("file" in item) return item.file.resolved;

const {key} = item;

// 1) full file path to plugin entrypoint
// 2 & 3) full module name
if (key.startsWith("/") || key.startsWith("@") || key.startsWith("babel-plugin-")) return key;

// add prefix to match keys defined in BABEL_MINIFY_PLUGIN_NAMES
return `babel-plugin-${key}`;
}

/**
* Combines the given two sets of presets
* @param {IBabelConfigItem[]} userItems
* @param {IBabelConfigItem[]} defaultItems
* @param {object[]} [forcedItems]
* @param {(IBabelConfigItem | IBabelPlugin)[]} userItems
* @param {(IBabelConfigItem | IBabelPlugin)[]} defaultItems
* @param {(IBabelConfigItem | IBabelPlugin)[]} [forcedItems]
* @param {boolean} [useMinifyOptions]
* @returns {{}[]}
*/
function combineConfigItems(
userItems: IBabelConfigItem[],
defaultItems: IBabelConfigItem[] = [],
forcedItems: IBabelConfigItem[] = [],
userItems: (IBabelConfigItem | IBabelPlugin)[],
defaultItems: (IBabelConfigItem | IBabelPlugin)[] = [],
forcedItems: (IBabelConfigItem | IBabelPlugin)[] = [],
useMinifyOptions: boolean = false
): {}[] {
const namesInUserItems = new Set(userItems.map(item => item.file.resolved));
const namesInForcedItems = new Set(forcedItems.map(item => item.file.resolved));
const namesInUserItems = new Set(userItems.map(getBabelItemId));
const namesInForcedItems = new Set(forcedItems.map(getBabelItemId));
const userItemsHasYearlyPreset = [...namesInUserItems].some(isYearlyBabelPreset);

return (
Expand All @@ -41,20 +58,22 @@ function combineConfigItems(
// If the options contains a yearly preset such as "preset-es2015", filter out preset-env from the default items if it is given
...defaultItems.filter(
item =>
!namesInUserItems.has(item.file.resolved) &&
!namesInForcedItems.has(item.file.resolved) &&
(!userItemsHasYearlyPreset || !isBabelPresetEnv(item.file.resolved))
!namesInUserItems.has(getBabelItemId(item)) &&
!namesInForcedItems.has(getBabelItemId(item)) &&
(!userItemsHasYearlyPreset || !isBabelPresetEnv(getBabelItemId(item)))
),

// Only use those user items that doesn't appear within the forced items
...userItems.filter(item => !namesInForcedItems.has(item.file.resolved)),
...userItems.filter(item => !namesInForcedItems.has(getBabelItemId(item))),

// Apply the forced items at all times
...forcedItems
]
// Filter out those options that do not apply depending on whether or not to apply minification
.filter(configItem =>
useMinifyOptions ? configItemIsAllowedDuringMinification(configItem) : configItemIsAllowedDuringNoMinification(configItem)
useMinifyOptions
? configItemIsAllowedDuringMinification(getBabelItemId(configItem))
: configItemIsAllowedDuringNoMinification(getBabelItemId(configItem))
)
);
}
Expand All @@ -64,19 +83,19 @@ function combineConfigItems(
* @param {string} resolved
* @returns {boolean}
*/
function configItemIsMinificationRelated({file: {resolved}}: IBabelConfigItem): boolean {
return BABEL_MINIFY_PRESET_NAMES.some(preset => resolved.includes(preset)) || BABEL_MINIFY_PLUGIN_NAMES.some(plugin => resolved.includes(plugin));
function configItemIsMinificationRelated(id: string): boolean {
return BABEL_MINIFY_PRESET_NAMES.some(preset => id.includes(preset)) || BABEL_MINIFY_PLUGIN_NAMES.some(plugin => id.includes(plugin));
}

/**
* Returns true if the given configItem is allowed during minification
* @param {string} resolved
* @returns {boolean}
*/
function configItemIsAllowedDuringMinification({file: {resolved}}: IBabelConfigItem): boolean {
function configItemIsAllowedDuringMinification(id: string): boolean {
return (
BABEL_MINIFICATION_BLACKLIST_PRESET_NAMES.every(preset => !resolved.includes(preset)) &&
BABEL_MINIFICATION_BLACKLIST_PLUGIN_NAMES.every(plugin => !resolved.includes(plugin))
BABEL_MINIFICATION_BLACKLIST_PRESET_NAMES.every(preset => !id.includes(preset)) &&
BABEL_MINIFICATION_BLACKLIST_PLUGIN_NAMES.every(plugin => !id.includes(plugin))
);
}

Expand All @@ -85,10 +104,8 @@ function configItemIsAllowedDuringMinification({file: {resolved}}: IBabelConfigI
* @param {string} resolved
* @returns {boolean}
*/
function configItemIsAllowedDuringNoMinification({file: {resolved}}: IBabelConfigItem): boolean {
return (
BABEL_MINIFY_PRESET_NAMES.every(preset => !resolved.includes(preset)) && BABEL_MINIFY_PLUGIN_NAMES.every(plugin => !resolved.includes(plugin))
);
function configItemIsAllowedDuringNoMinification(id: string): boolean {
return BABEL_MINIFY_PRESET_NAMES.every(preset => !id.includes(preset)) && BABEL_MINIFY_PLUGIN_NAMES.every(plugin => !id.includes(plugin));
}

/**
Expand All @@ -99,13 +116,62 @@ function configItemIsAllowedDuringNoMinification({file: {resolved}}: IBabelConfi
export function getBabelConfig({
babelConfig,
cwd,
noBabelConfigCustomization,
forcedOptions = {},
defaultOptions = {},
browserslist,
rollupInputOptions
}: GetBabelConfigOptions): GetBabelConfigResult {
const resolvedConfig = findBabelConfig({cwd, babelConfig});

if (noBabelConfigCustomization === true) {
const loadOptionsForFilename = (filename: string, useMinifyOptions: boolean = false) => {
const partialConfig =
resolvedConfig != null && resolvedConfig.kind === "dict"
? // If the given babelConfig is an object of input options, use that as the basis for the full config
resolvedConfig
: // Load the path to a babel config provided to the plugin if any, otherwise try to resolve it
loadPartialConfig({
cwd,
root: cwd,
...(resolvedConfig != null ? {configFile: resolvedConfig.path} : {babelrc: true}),
filename
});

// fully load all options, which results in a flat plugins structure
// which can then be used to match minification plugins
const options = loadOptions({
...partialConfig.options,
...forcedOptions,
presets: partialConfig.options.presets,
plugins: partialConfig.options.plugins,
filename,
caller: {
name: "rollup-plugin-ts",
...(partialConfig.options.caller || {}),
supportsStaticESM: true,
supportsDynamicImport: true
}
});

// sourceMap is an alias for 'sourceMaps'. If the user provided it, make sure it is undefined. Otherwise, Babel will fail during validation
if ("sourceMap" in options) {
delete options.sourceMap;
}

return {
...options,
plugins: combineConfigItems(options.plugins, [], [], useMinifyOptions)
};
};

return {
config: filename => loadOptionsForFilename(filename, false),
minifyConfig: filename => loadOptionsForFilename(filename, true),
hasMinifyOptions: true
};
}

// Load a partial Babel config based on the input options
const partialConfig = loadPartialConfig(
resolvedConfig != null && resolvedConfig.kind === "dict"
Expand Down
1 change: 1 addition & 0 deletions src/util/plugin-options/get-plugin-options.ts
Expand Up @@ -46,6 +46,7 @@ export function getPluginOptions(options: Partial<TypescriptPluginOptions>): Typ
return {
...baseOptions,
...("babelConfig" in options ? {babelConfig: options.babelConfig} : {}),
...("noBabelConfigCustomization" in options ? {noBabelConfigCustomization: options.noBabelConfigCustomization} : {}),
transpiler: "babel"
};
}
Expand Down

0 comments on commit 801fbd7

Please sign in to comment.