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
Use new babel API's to manage babel options #6801
Changes from 7 commits
24155bd
446a2eb
e814fd0
c37459d
8846126
ec7bc2b
69afca8
ba147ee
20b4855
d79b0ce
b5b69e8
748dc9c
14922dd
196dae8
3333174
e1e1db5
bdca781
7693394
6b27a5c
66de295
99dedbf
9883d64
cef9f22
ac1ea8f
ee0523c
5481a14
e223d25
f75d497
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,76 +1,15 @@ | ||
/* @flow */ | ||
|
||
const fs = require(`fs`) | ||
const fs = require(`fs-extra`) | ||
const path = require(`path`) | ||
const json5 = require(`json5`) | ||
const report = require(`gatsby-cli/lib/reporter`) | ||
const { actionifyBabelrc, addDefaultPluginsPresets } = require(`./utils`) | ||
const existsSync = require(`fs-exists-cached`).sync | ||
|
||
const apiRunnerNode = require(`../../utils/api-runner-node`) | ||
const testRequireError = require(`../../utils/test-require-error`).default | ||
|
||
/** | ||
* Locates a .babelrc in the Gatsby site root directory. Parses it using | ||
* json5 (what Babel uses). It throws an error if the users's .babelrc is | ||
* not parseable. | ||
*/ | ||
function findBabelrc(directory) { | ||
const babelrcPath = path.join(directory, `.babelrc`) | ||
if (existsSync(babelrcPath)) { | ||
try { | ||
const babelrc = fs.readFileSync(babelrcPath, `utf-8`) | ||
return json5.parse(babelrc) | ||
} catch (error) { | ||
throw error | ||
} | ||
} | ||
return null | ||
} | ||
|
||
/** | ||
* Locates a .babelrc.js in the Gatsby site root directory. | ||
* requires it and unwraps any esm default export | ||
*/ | ||
const preferDefault = m => (m && m.default) || m | ||
function findBabelrcJs(directory, stage) { | ||
let babelrc = null | ||
const babelrcPath = path.join(directory, `.babelrc.js`) | ||
try { | ||
babelrc = preferDefault(require(babelrcPath)) | ||
} catch (error) { | ||
if (!testRequireError(babelrcPath, error)) { | ||
throw error | ||
} | ||
} | ||
|
||
// TODO support this | ||
if (typeof babelrc === `function`) { | ||
report.error( | ||
`.babelrc.js files that export a function are not supported in Gatsby` | ||
) | ||
return null | ||
} | ||
|
||
return babelrc | ||
} | ||
|
||
/** | ||
* Reads the user's package.json and returns the "babel" section. It will | ||
* return undefined when the "babel" section does not exist. | ||
*/ | ||
function findBabelPackage(directory) { | ||
const packageJson = require(path.join(directory, `package.json`)) | ||
try { | ||
// $FlowFixMe - https://github.com/facebook/flow/issues/1975 | ||
return packageJson.babel | ||
} catch (error) { | ||
if (testRequireError(packageJson, error)) { | ||
return null | ||
} else { | ||
throw error | ||
} | ||
} | ||
} | ||
const { withBasePath } = require(`../../utils/path`) | ||
|
||
/** | ||
* Creates a normalized Babel config to use with babel-loader. Loads a local | ||
|
@@ -80,18 +19,29 @@ exports.onCreateBabelConfig = ({ stage, store, actions }) => { | |
const program = store.getState().program | ||
const { directory } = program | ||
|
||
let babelrc = | ||
findBabelrc(directory) || | ||
findBabelrcJs(directory) || | ||
findBabelPackage(directory) | ||
addDefaultPluginsPresets(actions, { | ||
stage, | ||
browserslist: program.browserslist, | ||
}) | ||
} | ||
|
||
// If user doesn't have a custom babelrc, add defaults. | ||
if (babelrc) { | ||
actionifyBabelrc(babelrc, actions) | ||
} else { | ||
addDefaultPluginsPresets(actions, { | ||
stage, | ||
browserslist: program.browserslist, | ||
}) | ||
} | ||
exports.onPreBootstrap = async ({ store }) => { | ||
const directory = store.getState().program.directory | ||
const directoryPath = withBasePath(directory) | ||
|
||
await apiRunnerNode(`onCreateBabelConfig`, { | ||
stage: `develop`, | ||
}) | ||
await apiRunnerNode(`onCreateBabelConfig`, { | ||
stage: `develop-html`, | ||
}) | ||
await apiRunnerNode(`onCreateBabelConfig`, { | ||
stage: `build-javascript`, | ||
}) | ||
await apiRunnerNode(`onCreateBabelConfig`, { | ||
stage: `build-html`, | ||
}) | ||
const babelrcState = store.getState().babelrc | ||
const babelState = JSON.stringify(babelrcState.stages, null, 4) | ||
fs.writeFile(directoryPath(`.cache/babelState.json`), babelState) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this missing an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes :-D |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
const babelLoader = require(`babel-loader`) | ||
const path = require(`path`) | ||
const fs = require(`fs`) | ||
|
||
const prepareOptions = babel => { | ||
const pluginBabelConfig = require(path.join( | ||
process.cwd(), | ||
`./.cache/babelState.json` | ||
)) | ||
|
||
const stage = fs.readFileSync( | ||
path.join(process.cwd(), `./.cache/current-stage.txt`), | ||
`utf8` | ||
) | ||
|
||
// Go through babel state and create config items. | ||
const reduxPlugins = [] | ||
const reduxPresets = [] | ||
pluginBabelConfig[stage].plugins.forEach(plugin => { | ||
reduxPlugins.push( | ||
babel.createConfigItem([require.resolve(plugin.name), plugin.options], { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be worth caching this somehow to avoid re-resolving for every single file that Gatsby compiles. Or does Node already cache that for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, node caches that so we should be fine. |
||
type: `plugin`, | ||
}) | ||
) | ||
}) | ||
pluginBabelConfig[stage].presets.forEach(preset => { | ||
reduxPresets.push( | ||
babel.createConfigItem([require.resolve(preset.name), preset.options], { | ||
type: `preset`, | ||
}) | ||
) | ||
}) | ||
|
||
return [reduxPresets, reduxPlugins] | ||
} | ||
|
||
module.exports = babelLoader.custom(babel => { | ||
const toReturn = { | ||
// Passed the loader options. | ||
customOptions(options) { | ||
return { | ||
loader: { | ||
cacheDirectory: true, | ||
babelrc: false, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think you'd want to set this since you have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
sourceType: `unambiguous`, | ||
...options, | ||
}, | ||
} | ||
}, | ||
|
||
// Passed Babel's 'PartialConfig' object. | ||
config(partialConfig) { | ||
let { options } = partialConfig | ||
|
||
// If there is no filesystem config present add more defaults | ||
// TODO: maybe this should be stricter, like checks if there are no plugins or presets? | ||
if (!partialConfig.hasFilesystemConfig()) { | ||
const [reduxPresets, reduxPlugins] = prepareOptions(babel) | ||
options = { | ||
...options, | ||
plugins: reduxPlugins, | ||
presets: reduxPresets, | ||
} | ||
} | ||
|
||
return options | ||
}, | ||
} | ||
|
||
return toReturn | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
require(`v8-compile-cache`) | ||
|
||
const fs = require(`fs`) | ||
const fs = require(`fs-extra`) | ||
const path = require(`path`) | ||
const dotenv = require(`dotenv`) | ||
const FriendlyErrorsWebpackPlugin = require(`friendly-errors-webpack-plugin`) | ||
|
@@ -28,6 +28,12 @@ module.exports = async ( | |
) => { | ||
const directoryPath = withBasePath(directory) | ||
|
||
await fs.writeFile( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the stage able to be passed through to the loaders as an argument? That seems like it would be easier. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No idea... I'll just set it on |
||
directoryPath(`.cache/current-stage.txt`), | ||
suppliedStage, | ||
`utf8` | ||
) | ||
|
||
// We combine develop & develop-html stages for purposes of generating the | ||
// webpack config. | ||
const stage = suppliedStage | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,20 +7,20 @@ | |
"bluebird": "^3.5.1", | ||
"email-validator": "^1.1.1", | ||
"fuse.js": "^3.2.0", | ||
"gatsby": "^2.0.0-beta.47", | ||
"gatsby": "^2.0.0-beta.97", | ||
"gatsby-image": "next", | ||
"gatsby-plugin-canonical-urls": "next", | ||
"gatsby-plugin-catch-links": "next", | ||
"gatsby-plugin-create-client-paths": "^1.0.8", | ||
"gatsby-plugin-feed": "next", | ||
"gatsby-plugin-fullstory": "^1.0.4-5", | ||
"gatsby-plugin-glamor": "next", | ||
"gatsby-plugin-google-analytics": "next", | ||
"gatsby-plugin-google-analytics": "^2.0.0-beta.5", | ||
"gatsby-plugin-google-tagmanager": "next", | ||
"gatsby-plugin-lodash": "next", | ||
"gatsby-plugin-mailchimp": "^2.2.3", | ||
"gatsby-plugin-manifest": "next", | ||
"gatsby-plugin-netlify": "next", | ||
"gatsby-plugin-manifest": "^2.0.2-beta.5", | ||
"gatsby-plugin-netlify": "^2.0.0-beta.6", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should these stay on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤷♂️ it's the same but yeah — I'll remove them to reduce PR noise |
||
"gatsby-plugin-netlify-cache": "^0.1.0", | ||
"gatsby-plugin-nprogress": "next", | ||
"gatsby-plugin-offline": "^2.0.0-beta.9", | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like we can remove
json5
from package.json (this and tests you remove are only places where this is used)