Skip to content

Commit

Permalink
Improve the future proof of using the jsx runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
blainekasten committed Aug 27, 2020
1 parent 2be05b7 commit 357a858
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 18 deletions.
6 changes: 4 additions & 2 deletions packages/babel-preset-gatsby/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,11 @@ export default function preset(_, options = {}) {
{
useBuiltIns: true,
pragma:
options.runtime === `automatic` ? null : `React.createElement`,
options.reactRuntime === `automatic`
? undefined
: `React.createElement`,
development: stage === `develop`,
runtime: options.runtime || `classic`,
runtime: options.reactRuntime || `classic`,
},
],
],
Expand Down
4 changes: 2 additions & 2 deletions packages/gatsby/src/utils/babel-loader-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const getCustomOptions = stage => {
const prepareOptions = (babel, options = {}, resolve = require.resolve) => {
const pluginBabelConfig = loadCachedConfig()

const { stage, runtime } = options
const { stage, reactRuntime } = options

// Required plugins/presets
const requiredPlugins = [
Expand Down Expand Up @@ -67,7 +67,7 @@ const prepareOptions = (babel, options = {}, resolve = require.resolve) => {
resolve(`babel-preset-gatsby`),
{
stage,
runtime,
reactRuntime,
},
],
{
Expand Down
4 changes: 2 additions & 2 deletions packages/gatsby/src/utils/babel-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ const {
module.exports = babelLoader.custom(babel => {
const toReturn = {
// Passed the loader options.
customOptions({ stage = `test`, runtime = `classic`, ...options }) {
customOptions({ stage = `test`, reactRuntime = `classic`, ...options }) {
return {
custom: {
stage,
runtime,
reactRuntime,
},
loader: {
sourceType: `unambiguous`,
Expand Down
11 changes: 10 additions & 1 deletion packages/gatsby/src/utils/eslint-config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { printSchema, GraphQLSchema } from "graphql"
import { CLIEngine } from "eslint"

export const eslintConfig = (schema: GraphQLSchema): CLIEngine.Options => {
export const eslintConfig = (
schema: GraphQLSchema,
usingJsxRuntime: boolean
): CLIEngine.Options => {
return {
useEslintrc: false,
resolvePluginsRelativeTo: __dirname,
Expand All @@ -14,6 +17,12 @@ export const eslintConfig = (schema: GraphQLSchema): CLIEngine.Options => {
extends: [require.resolve(`eslint-config-react-app`)],
plugins: [`graphql`],
rules: {
// New versions of react use a special jsx runtime that remove the requirement
// for having react in scope for jsx. Once the jsx runtime is backported to all
// versions of react we can make this always be `off`.
// I would also assume that eslint-config-react-app will switch their flag to `off`
// when jsx runtime is stable in all common versions of React.
"react/react-in-jsx-scope": usingJsxRuntime ? `off` : `error`, // Conditionally apply for reactRuntime?
"import/no-webpack-loader-syntax": [0],
"graphql/template-strings": [
`error`,
Expand Down
27 changes: 16 additions & 11 deletions packages/gatsby/src/utils/webpack-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import MiniCssExtractPlugin from "mini-css-extract-plugin"
import OptimizeCssAssetsPlugin from "optimize-css-assets-webpack-plugin"
import ReactRefreshWebpackPlugin from "@pmmmwh/react-refresh-webpack-plugin"
import isWsl from "is-wsl"
import semver from "semver"
import { getBrowsersList } from "./browserslist"

import { GatsbyWebpackStatsExtractor } from "./gatsby-webpack-stats-extractor"
Expand Down Expand Up @@ -138,6 +137,20 @@ export const createWebpackUtils = (

const isSSR = stage.includes(`html`)

let jsxRuntimeExists = false

try {
// React is shipping a new jsx runtime that is to be used with
// an option on @babel/preset-react called `runtime: automatic`
// Not every version of React has this jsx-runtime yet. Eventually,
// it will be backported to older versions of react and this check
// will become unnecessary.
jsxRuntimeExists = !!require.resolve(`react/jsx-runtime.js`)
} catch (e) {
// If the require.resolve throws, that means this version of React
// does not support the jsx runtime.
}

const makeExternalOnly = (original: RuleFactory) => (
options = {}
): RuleSetRule => {
Expand Down Expand Up @@ -271,18 +284,10 @@ export const createWebpackUtils = (
},

js: options => {
let runtimeExists = false

try {
runtimeExists = !!require.resolve(`react/jsx-runtime.js`)
console.log({ runtimeExists })
} catch (e) {
// no-op.
}
return {
options: {
stage,
runtime: runtimeExists ? `automatic` : `classic`,
reactRuntime: jsxRuntimeExists ? `automatic` : `classic`,
// TODO add proper cache keys
cacheDirectory: path.join(
program.directory,
Expand Down Expand Up @@ -313,7 +318,7 @@ export const createWebpackUtils = (
},

eslint: (schema: GraphQLSchema) => {
const options = eslintConfig(schema)
const options = eslintConfig(schema, jsxRuntimeExists)

return {
options,
Expand Down

0 comments on commit 357a858

Please sign in to comment.