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

feat(babel-preset-gatsby-package): add conditional compilation plugin #32687

Merged
merged 8 commits into from
Aug 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions .eslintrc.js
Expand Up @@ -36,6 +36,7 @@ module.exports = {
__PATH_PREFIX__: true,
__BASE_PATH__: true,
__ASSET_PREFIX__: true,
_CFLAGS_: true,
},
rules: {
"@babel/no-unused-expressions": [
Expand Down
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -117,8 +117,8 @@
},
"scripts": {
"bootstrap": "npm-run-all -s check-versions \"lerna-prepare -- --{@}\" --",
"check-repo-fields": "babel-node scripts/check-repo-fields.js",
"check-versions": "babel-node scripts/check-versions.js",
"check-repo-fields": "node scripts/check-repo-fields.js",
"check-versions": "node scripts/check-versions.js",
Comment on lines +120 to +121
Copy link
Contributor Author

Choose a reason for hiding this comment

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

These are not necessary anymore, else I had to change a few things in babelrc

"format": "npm run format:code && npm run format:other && npm run format:svg",
"format:code": "npm run lint:code -- --fix",
"format:other": "npm run prettier -- --write",
Expand Down
11 changes: 11 additions & 0 deletions packages/babel-preset-gatsby-package/.babelrc
@@ -0,0 +1,11 @@
{
"plugins": [
["@babel/plugin-transform-modules-commonjs"]
],
"overrides": [
{
"test": ["**/*.ts", "**/*.tsx"],
"plugins": [["@babel/plugin-transform-typescript", { "isTSX": true }]],
}
]
}
1 change: 1 addition & 0 deletions packages/babel-preset-gatsby-package/.gitignore
@@ -1 +1,2 @@
yarn.lock
dist/
Expand Up @@ -54,13 +54,64 @@ Array [
]
`;

exports[`babel-preset-gatsby-package in browser mode specifies proper presets for esm 1`] = `
Array [
Array [
"@babel/preset-env",
Object {
"bugfixes": true,
"debug": false,
"loose": true,
"modules": false,
"shippedProposals": true,
"targets": Object {
"esmodules": true,
},
"useBuiltIns": false,
},
],
Array [
"@babel/preset-react",
],
"@babel/preset-flow",
]
`;

exports[`babel-preset-gatsby-package in browser mode specifies the proper plugins 1`] = `
Array [
"@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-transform-runtime",
"@babel/plugin-syntax-dynamic-import",
"babel-plugin-dynamic-import-node",
Array [
"./babel-transform-compiler-flags",
Object {
"availableFlags": Array [
"GATSBY_MAJOR",
],
"flags": Object {},
},
],
]
`;

exports[`babel-preset-gatsby-package in node mode can enable compilerFlags 1`] = `
Array [
"@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-transform-runtime",
"@babel/plugin-syntax-dynamic-import",
"babel-plugin-dynamic-import-node",
Array [
"./babel-transform-compiler-flags",
Object {
"availableFlags": Array [
"MAJOR",
],
"flags": Object {},
},
],
]
`;

Expand Down Expand Up @@ -119,5 +170,14 @@ Array [
"@babel/plugin-transform-runtime",
"@babel/plugin-syntax-dynamic-import",
"babel-plugin-dynamic-import-node",
Array [
"./babel-transform-compiler-flags",
Object {
"availableFlags": Array [
"GATSBY_MAJOR",
],
"flags": Object {},
},
],
]
`;
@@ -0,0 +1,3 @@
const runner = require(`@babel/helper-plugin-test-runner`).default

runner(__dirname)
@@ -0,0 +1,17 @@

if (_CFLAGS_.MAJOR === '4') {
console.log('We only load this for Gatsby 4')
} else {
console.log('Old code path')
}

function isGatsby4() {
return _CFLAGS_.MAJOR === '4'
}


if (isGatsby4()) {
console.log('We only load this for Gatsby 4')
} else {
console.log('Old code path')
}
@@ -0,0 +1,15 @@
if ("4" === '4') {
console.log('We only load this for Gatsby 4');
} else {
console.log('Old code path');
}

function isGatsby4() {
return "4" === '4';
}

if (isGatsby4()) {
console.log('We only load this for Gatsby 4');
} else {
console.log('Old code path');
}
@@ -0,0 +1,6 @@

if (_CFLAGS_.UNKNOWN === 'true') {
console.log('We only load this when true')
} else {
console.log('Old code path')
}
@@ -0,0 +1,3 @@
{
"throws": "UNKNOWN is not part of the available compiler flags."
}
17 changes: 17 additions & 0 deletions packages/babel-preset-gatsby-package/__tests__/fixtures/options.js
@@ -0,0 +1,17 @@
const path = require("path")

module.exports = {
sourceType: "module",
plugins: [
[path.resolve(__dirname, "../../src/babel-transform-compiler-flags.ts"),
{
availableFlags: ['MAJOR'],
flags: {
MAJOR: '4',
}
}
],
],
babelrc: false,
configFile: false,
}
32 changes: 24 additions & 8 deletions packages/babel-preset-gatsby-package/__tests__/index.js
@@ -1,12 +1,20 @@
const preset = require(`../`)
const preset = require(`../src/index.js`)

jest.mock(`../resolver`, () => jest.fn(moduleName => moduleName))
jest.mock(`../src/resolver`, () => jest.fn(moduleName => moduleName))

beforeEach(() => {
delete process.env.BABEL_ENV
})

describe(`babel-preset-gatsby-package`, () => {
let babelEnv;

beforeEach(() => {
babelEnv = process.env.BABEL_ENV
delete process.env.BABEL_ENV;
})

afterEach(() => {
process.env.BABEL_ENV = babelEnv
})

describe(`in node mode`, () => {
it(`specifies the proper plugins`, () => {
const { plugins } = preset()
Expand All @@ -29,12 +37,15 @@ describe(`babel-preset-gatsby-package`, () => {
nodeVersion,
})

const [, opts] = presets.find(preset =>
[].concat(preset).includes(`@babel/preset-env`)
)
const [, opts] = presets.find(preset => [].concat(preset).includes(`@babel/preset-env`))

expect(opts.targets.node).toBe(nodeVersion)
})

it(`can enable compilerFlags`, () => {
const { plugins } = preset(null, { availableCompilerFlags: [`MAJOR`] })
expect(plugins).toMatchSnapshot()
})
})

describe(`in browser mode`, () => {
Expand All @@ -52,5 +63,10 @@ describe(`babel-preset-gatsby-package`, () => {
const { presets } = preset(null, { browser: true, debug: true })
expect(presets).toMatchSnapshot()
})

it(`specifies proper presets for esm`, () => {
const { presets } = preset(null, { browser: true, esm: true })
expect(presets).toMatchSnapshot()
})
})
})
14 changes: 13 additions & 1 deletion packages/babel-preset-gatsby-package/package.json
Expand Up @@ -20,12 +20,24 @@
"babel-plugin-dynamic-import-node": "^2.3.3",
"core-js": "^3.10.0"
},
"devDependencies": {
"@types/babel__core": "^7.1.15",
"@babel/cli": "^7.14.8",
"@babel/core": "^7.14.8",
"@babel/helper-plugin-test-runner": "7.14.5",
"@babel/plugin-transform-modules-commonjs": "^7.14.5"
},
"peerDependencies": {
"@babel/core": "^7.11.6"
},
"license": "MIT",
"main": "index.js",
"main": "dist/index.js",
"engines": {
"node": ">=12.13.0"
},
"scripts": {
"build": "babel src --out-dir dist/ --ignore \"**/__tests__\" --ignore \"**/__mocks__\" --extensions \".ts,.js\"",
"prepare": "cross-env NODE_ENV=production npm run build",
"watch": "babel -w src --out-dir dist/ --ignore \"**/__tests__\" --extensions \".ts,.js\""
}
}
@@ -0,0 +1,52 @@
import type { NodePath, PluginObj, types, PluginPass } from "@babel/core"

interface IPluginOptions {
flags: Record<string, string>
availableFlags: Array<string>
}

export default function compilerFlags(
{
types: t,
}: {
types: typeof types
},
opts: Partial<IPluginOptions>
): PluginObj {
if (!opts.flags) {
throw new Error(`flags option needs to be set`)
}
if (!opts.availableFlags) {
throw new Error(`availableFlags option needs to be set`)
}

return {
name: `babel-transform-compiler-flags`,
visitor: {
Identifier(
nodePath: NodePath<types.Identifier>,
state: PluginPass
): void {
const flags = (state.opts as IPluginOptions).flags
const availableFlags = (state.opts as IPluginOptions).availableFlags

if (
nodePath.node.name === `_CFLAGS_` &&
t.isMemberExpression(nodePath.parent)
) {
const cFlag = (nodePath.parent.property as types.Identifier).name

if (!availableFlags.includes(cFlag)) {
throw new Error(
`${cFlag} is not part of the available compiler flags.`
)
}

nodePath.parentPath.replaceWith(
t.stringLiteral(flags[cFlag] ? flags[cFlag] : ``)
)
}
},
},
}
}
@@ -1,8 +1,14 @@
const r = require(`./resolver`)

function preset(context, options = {}) {
const { browser = false, debug = false, nodeVersion = `12.13.0`, esm = false } = options
const { NODE_ENV, BABEL_ENV } = process.env
const {
browser = false,
debug = false,
nodeVersion = `12.13.0`,
esm = false,
availableCompilerFlags = [`GATSBY_MAJOR`],
} = options
const { NODE_ENV, BABEL_ENV, COMPILER_OPTIONS } = process.env

const IS_TEST = (BABEL_ENV || NODE_ENV) === `test`

Expand All @@ -13,11 +19,11 @@ function preset(context, options = {}) {
if (browser) {
if (esm) {
browserConfig.targets = {
esmodules: true
esmodules: true,
}
} else {
browserConfig.targets = {
browsers: [`last 2 versions`, `not ie <= 11`, `not android 4.4.3`]
browsers: [`last 2 versions`, `not ie <= 11`, `not android 4.4.3`],
}
}
}
Expand All @@ -30,6 +36,20 @@ function preset(context, options = {}) {
},
}

let parsedCompilerOptions = {}
if (COMPILER_OPTIONS) {
// COMPILER_OPTIONS syntax is key=value,key2=value2
parsedCompilerOptions = COMPILER_OPTIONS.split(`,`).reduce((acc, curr) => {
const [key, value] = curr.split(`=`)

if (key) {
acc[key] = value
}

return acc
}, Object.create(null))
}

return {
presets: [
[
Expand All @@ -54,6 +74,13 @@ function preset(context, options = {}) {
r(`@babel/plugin-transform-runtime`),
r(`@babel/plugin-syntax-dynamic-import`),
IS_TEST && r(`babel-plugin-dynamic-import-node`),
[
r(`./babel-transform-compiler-flags`),
{
flags: parsedCompilerOptions,
availableFlags: availableCompilerFlags,
},
],
].filter(Boolean),
overrides: [
{
Expand Down
@@ -1,3 +1,3 @@
const r = m => require.resolve(m)

module.exports = r;
module.exports = r
4 changes: 4 additions & 0 deletions packages/babel-preset-gatsby-package/tsconfig.json
@@ -0,0 +1,4 @@
{
"extends": "../../tsconfig.json",
"strict": true
}
1 change: 1 addition & 0 deletions tsconfig.json
Expand Up @@ -15,6 +15,7 @@
"resolveJsonModule": true,
"esModuleInterop": true,
"jsx": "preserve",
"typeRoots": ["./types", "**/node_modules/@types", "node_modules/@types"],
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is necessary to find the global CFLAGS types in the monorepo

"paths": {
"@reach/router/*": ["./node_modules/@gatsbyjs/reach-router/*"]
}
Expand Down