diff --git a/docs/docs/add-custom-webpack-config.md b/docs/docs/add-custom-webpack-config.md index 8280012f13b92..1f81b3d2e48a8 100644 --- a/docs/docs/add-custom-webpack-config.md +++ b/docs/docs/add-custom-webpack-config.md @@ -42,37 +42,39 @@ e.g. [Sass](/packages/gatsby-plugin-sass/), Here is an example that configures **flexboxgrid** when processing css files. Add this in `gatsby-node.js`: ```js -exports.modifyWebpackConfig = ({ config, stage }) => { - switch (stage) { - case "develop": - config.loader("css", { - include: /flexboxgrid/, - }); - - break; - - case "build-css": - config.loader("css", { - include: /flexboxgrid/, - }); - - break; - - case "build-html": - config.loader("css", { - include: /flexboxgrid/, - }); - - break; - - case "build-javascript": - config.loader("css", { - include: /flexboxgrid/, - }); - - break; - } - - return config; +exports.modifyWebpackConfig = ({ + stage, + rules, + loaders, + plugins, + actions, +}) => { + actions.setWebpackConfig({ + module: { + rules: [ + { + test: /\.less$/, + // We don't need to add the matching ExtractText plugin + // because gatsby already includes it and makes sure its only + // run at the appropriate stages, e.g. not in development + use: plugins.extractText.extract({ + fallback: loaders.style(), + use: [ + loaders.css({ importLoaders: 1 }), + // the postcss loader comes with some nice defaults + // including autoprefixer for our configured browsers + loaders.postcss(), + `less-loader`, + ], + }), + }, + ], + }, + plugins: [ + plugins.define({ + __DEVELOPMENT__: stage === `develop` || stage === `develop-html`, + }), + ], + }); }; ``` diff --git a/packages/gatsby-cli/src/reporter/index.js b/packages/gatsby-cli/src/reporter/index.js index 8884461f252e6..438cb3eddff5b 100644 --- a/packages/gatsby-cli/src/reporter/index.js +++ b/packages/gatsby-cli/src/reporter/index.js @@ -27,6 +27,13 @@ module.exports = Object.assign(reporter, { process.exit(1) }, + panicOnBuild(...args) { + this.error(...args) + if (process.env.gatsby_executing_command !== `build`) { + process.exit(1) + } + }, + error(message, error) { if (arguments.length === 1 && typeof message !== `string`) { error = message diff --git a/packages/gatsby-plugin-coffeescript/src/gatsby-node.js b/packages/gatsby-plugin-coffeescript/src/gatsby-node.js index 351de1fd0d7cc..0d3bcc009bafd 100644 --- a/packages/gatsby-plugin-coffeescript/src/gatsby-node.js +++ b/packages/gatsby-plugin-coffeescript/src/gatsby-node.js @@ -8,15 +8,13 @@ export function resolvableExtensions() { } export function modifyWebpackConfig({ loaders, actions }) { - const coffeeLoader = [loaders.js(), resolve(`coffee-loader`)] - // We need to use Babel to get around the ES6 export issue. actions.setWebpackConfig({ module: { rules: [ { test: COFFEE, - use: coffeeLoader, + use: [loaders.js(), resolve(`coffee-loader`)], }, ], }, diff --git a/packages/gatsby-plugin-less/src/gatsby-node.js b/packages/gatsby-plugin-less/src/gatsby-node.js index 4bf3adea21901..049424aac1198 100644 --- a/packages/gatsby-plugin-less/src/gatsby-node.js +++ b/packages/gatsby-plugin-less/src/gatsby-node.js @@ -17,7 +17,7 @@ exports.modifyWebpackConfig = ( test: /\.less$/, exclude: /\.module\.less$/, use: plugins.extractText.extract({ - fallback: loaders.style, + fallback: loaders.style(), use: [ loaders.css({ importLoaders: 1 }), loaders.postcss({ plugins: postCssPlugins }), @@ -28,7 +28,7 @@ exports.modifyWebpackConfig = ( const lessRuleModules = { test: /\.module\.less$/, use: plugins.extractText.extract({ - fallback: loaders.style, + fallback: loaders.style(), use: [ loaders.css({ modules: true, importLoaders: 1 }), loaders.postcss({ plugins: postCssPlugins }), @@ -51,7 +51,7 @@ exports.modifyWebpackConfig = ( configRules = configRules.concat([ { ...lessRule, - use: loaders.null, + use: [loaders.null()], }, lessRuleModules, ]) diff --git a/packages/gatsby-plugin-sass/src/gatsby-node.js b/packages/gatsby-plugin-sass/src/gatsby-node.js index 4dd4c6b813ccb..e8680b5e3e476 100644 --- a/packages/gatsby-plugin-sass/src/gatsby-node.js +++ b/packages/gatsby-plugin-sass/src/gatsby-node.js @@ -17,7 +17,7 @@ exports.modifyWebpackConfig = ( test: /\.s(a|c)ss$/, exclude: /\.module\.s(a|c)ss$/, use: plugins.extractText.extract({ - fallback: loaders.style, + fallback: loaders.style(), use: [ loaders.css({ importLoaders: 1 }), loaders.postcss({ plugins: postCssPlugins }), @@ -28,7 +28,7 @@ exports.modifyWebpackConfig = ( const sassRuleModules = { test: /\.module\.s(a|c)ss$/, use: plugins.extractText.extract({ - fallback: loaders.style, + fallback: loaders.style(), use: [ loaders.css({ modules: true, importLoaders: 1 }), loaders.postcss({ plugins: postCssPlugins }), @@ -51,7 +51,7 @@ exports.modifyWebpackConfig = ( configRules = configRules.concat([ { ...sassRule, - use: loaders.null, + use: [loaders.null()], }, sassRuleModules, ]) diff --git a/packages/gatsby-plugin-stylus/src/gatsby-node.js b/packages/gatsby-plugin-stylus/src/gatsby-node.js index cf2b12b38f9fe..f6f4085f09b67 100644 --- a/packages/gatsby-plugin-stylus/src/gatsby-node.js +++ b/packages/gatsby-plugin-stylus/src/gatsby-node.js @@ -38,7 +38,7 @@ exports.modifyWebpackConfig = ( test: /\.styl$/, exclude: /\.module\.styl$/, use: plugins.extractText.extract({ - fallback: loaders.style, + fallback: loaders.style(), use: [ loaders.css({ importLoaders: 1 }), loaders.postcss({ plugins: postCssPlugins }), @@ -50,7 +50,7 @@ exports.modifyWebpackConfig = ( const stylusRuleModules = { test: /\.module\.styl$/, use: plugins.extractText.extract({ - fallback: loaders.style, + fallback: loaders.style(), use: [ loaders.css({ modules: true, importLoaders: 1 }), loaders.postcss({ plugins: postCssPlugins }), @@ -73,7 +73,7 @@ exports.modifyWebpackConfig = ( configRules = configRules.concat([ { ...stylusRule, - use: loaders.null, + use: [loaders.null()], }, stylusRuleModules, ]) diff --git a/packages/gatsby/.npmignore b/packages/gatsby/.npmignore index 4918c8e4f099c..03341dbf9e82c 100644 --- a/packages/gatsby/.npmignore +++ b/packages/gatsby/.npmignore @@ -1,2 +1,3 @@ src flow-typed +**/__tests__/** diff --git a/packages/gatsby/package.json b/packages/gatsby/package.json index f64710695151a..e41d4874ee70d 100644 --- a/packages/gatsby/package.json +++ b/packages/gatsby/package.json @@ -77,7 +77,6 @@ "node-libs-browser": "^2.0.0", "normalize-path": "^2.1.1", "null-loader": "^0.1.1", - "nyc": "^11.4.1", "opn": "^5.1.0", "parse-filepath": "^1.0.1", "path-exists": "^3.0.0", @@ -123,6 +122,7 @@ "@babel/cli": "^7.0.0-beta.38", "@babel/core": "^7.0.0-beta.38", "@babel/plugin-proposal-class-properties": "^7.0.0-beta.39", + "@babel/preset-flow": "^7.0.0-beta.40", "chokidar": "^2.0.0", "cross-env": "^5.0.5", "nyc": "^7.0.0", @@ -162,7 +162,7 @@ "build": "rimraf dist && npm run build:src && npm run build:internal-plugins && npm run build:rawfiles", "build:internal-plugins": "copyfiles -u 1 src/internal-plugins/**/package.json dist", "build:rawfiles": "copyfiles -u 1 src/internal-plugins/**/raw_* dist", - "build:src": "babel src --out-dir dist --source-maps --ignore gatsby-cli.js,raw_*,__tests__", + "build:src": "babel src --out-dir dist --source-maps --ignore **/gatsby-cli.js,**/raw_*,**/__tests__/***", "clean-test-bundles": "find test/ -type f -name bundle.js* -exec rm -rf {} +", "prepublish": "cross-env NODE_ENV=production npm run build", "test-coverage": "node_modules/.bin/nyc --reporter=lcov --reporter=text npm test", diff --git a/packages/gatsby/src/utils/api-node-docs.js b/packages/gatsby/src/utils/api-node-docs.js index 400aedf8613ae..90ac7f5a5471a 100644 --- a/packages/gatsby/src/utils/api-node-docs.js +++ b/packages/gatsby/src/utils/api-node-docs.js @@ -187,7 +187,7 @@ exports.modifyBabelrc = true * rules: [ * { * test: 'my-css', - * use: [loaders.style, loaders.css()] + * use: [loaders.style(), loaders.css()] * }, * ], * }, diff --git a/packages/gatsby/src/utils/babel-config.js b/packages/gatsby/src/utils/babel-config.js index 453d4c569ab17..a9e5f50197b00 100644 --- a/packages/gatsby/src/utils/babel-config.js +++ b/packages/gatsby/src/utils/babel-config.js @@ -4,6 +4,7 @@ import fs from "fs" import path from "path" import json5 from "json5" import _ from "lodash" +const report = require(`gatsby-cli/lib/reporter`) import apiRunnerNode from "./api-runner-node" // TODO update this to store Babelrc config in Redux store. @@ -18,12 +19,35 @@ function findBabelrc(directory) { const babelrc = fs.readFileSync(path.join(directory, `.babelrc`), `utf-8`) return json5.parse(babelrc) } catch (error) { - if (error.code === `ENOENT`) { + if (error.code !== `ENOENT`) throw error + } + return null +} + +/** + * Locates a .babelrc.js in the Gatsby site root directory. + * requires it and unwraps any esm default export + */ +function findBabelrcJs(directory, stage) { + try { + // $FlowFixMe + let babelrc = require(path.join(directory, `.babelrc.js`)) + babelrc = + babelrc && babelrc.__esModule ? babelrc.default || undefined : babelrc + + // TODO support this + if (typeof babelrc === `function`) { + report.error( + `.babelrc.js files that export a function are not supported in Gatsby` + ) return null - } else { - throw error } + + return babelrc + } catch (error) { + if (error.code !== `ENOENT`) throw error } + return null } /** @@ -32,7 +56,7 @@ function findBabelrc(directory) { */ function findBabelPackage(directory) { try { - // $FlowIssue - https://github.com/facebook/flow/issues/1975 + // $FlowFixMe - https://github.com/facebook/flow/issues/1975 const packageJson = require(path.join(directory, `package.json`)) return packageJson.babel } catch (error) { @@ -51,7 +75,10 @@ function findBabelPackage(directory) { module.exports = async function babelConfig(program, stage) { const { directory } = program - let babelrc = findBabelrc(directory) || findBabelPackage(directory) + let babelrc = + findBabelrc(directory) || + findBabelrcJs(directory) || + findBabelPackage(directory) // If user doesn't have a custom babelrc, add defaults. if (!babelrc) { @@ -73,21 +100,26 @@ module.exports = async function babelConfig(program, stage) { [ require.resolve(`@babel/preset-react`), { + useBuiltIns: true, pragma: `React.createElement`, + development: stage === `develop`, }, ], require.resolve(`@babel/preset-flow`), ], plugins: [ - require.resolve(`@babel/plugin-proposal-class-properties`), + [ + require.resolve(`@babel/plugin-proposal-class-properties`), + { loose: true }, + ], require.resolve(`@babel/plugin-syntax-dynamic-import`), // Polyfills the runtime needed for async/await and generators [ require.resolve(`@babel/plugin-transform-runtime`), { - helpers: false, - polyfill: false, + helpers: true, regenerator: true, + polyfill: false, }, ], ], @@ -103,10 +135,6 @@ module.exports = async function babelConfig(program, stage) { if (stage === `develop`) { // TODO: maybe this should be left to the user? babelrc.plugins.unshift(require.resolve(`react-hot-loader/babel`)) - // TODO figure out what this was — if left in it breaks builds - // babelrc.plugins.unshift( - // require.resolve(`@babel/transform-react-jsx-source`) - // ) } babelrc.plugins.unshift( diff --git a/packages/gatsby/src/utils/webpack-modify-validate.js b/packages/gatsby/src/utils/webpack-modify-validate.js deleted file mode 100644 index 02f8912a0ad3f..0000000000000 --- a/packages/gatsby/src/utils/webpack-modify-validate.js +++ /dev/null @@ -1,69 +0,0 @@ -import _ from "lodash" -import invariant from "invariant" -import validate, { Joi } from "webpack-validator" -import stripIndent from "common-tags/lib/stripIndent" -import apiRunnerNode from "./api-runner-node" - -// We whitelist special config keys that are not part of a standard Webpack v1 -// config but are in common usage. We should be able to completely remove this -// once we're on Webpack v3. -// -// For info on whitelisting with webpack-validator see: -// https://github.com/js-dxtools/webpack-validator#customizing -const validationWhitelist = Joi.object({ - stylus: Joi.any(), - sassLoader: Joi.any(), - sassResources: [Joi.string(), Joi.array().items(Joi.string())], - responsiveLoader: Joi.any(), -}) - -export default (async function ValidateWebpackConfig( - program, - config, - babelConfig, - stage -) { - // We don't care about the return as plugins just mutate the config directly. - await apiRunnerNode(`modifyWebpackConfig`, { - program, - config, - babelConfig, - stage, - }) - - // console.log(JSON.stringify(config, null, 4)) - - invariant( - _.isObject(config) && _.isFunction(config.resolve), - ` - You must return an webpack-configurator instance when modifying the Webpack config. - Returned: ${config} - stage: ${stage} - ` - ) - - const validationState = validate(config.resolve(), { - returnValidation: true, - schemaExtension: validationWhitelist, - }) - - if (!validationState.error) { - return config - } - - console.log(`There were errors with your webpack config:`) - validationState.error.details.forEach((err, index) => { - console.log(`[${index + 1}]`) - console.log(err.path) - console.log(err.type, `,`, err.message) - console.log(`\n`) - }) - - console.log(stripIndent` - Your Webpack config does not appear to be valid. This could be because of - something you added or a plugin. If you don't recognize the invalid keys listed - above try removing plugins and rebuilding to identify the culprit. - `) - - return process.exit(1) -}) diff --git a/packages/gatsby/src/utils/webpack-utils.js b/packages/gatsby/src/utils/webpack-utils.js index f3f04c99d600b..f153eec693401 100644 --- a/packages/gatsby/src/utils/webpack-utils.js +++ b/packages/gatsby/src/utils/webpack-utils.js @@ -197,6 +197,7 @@ module.exports = async ({ loader: require.resolve(`postcss-loader`), options: { ident: `postcss-${++ident}`, + sourceMap: !PRODUCTION, plugins: loader => { plugins = (typeof plugins === `function` ? plugins(loader) : plugins) || [] @@ -355,7 +356,7 @@ module.exports = async ({ return { test: /\.css$/, use: ExtractTextPlugin.extract({ - fallback: loaders.style, + fallback: loaders.style(), use: [loaders.css({ importLoaders: 1 }), loaders.postcss(options)], }), } diff --git a/packages/gatsby/src/utils/webpack.config.js b/packages/gatsby/src/utils/webpack.config.js index ad60bdbd2f855..8e567c7fec17a 100644 --- a/packages/gatsby/src/utils/webpack.config.js +++ b/packages/gatsby/src/utils/webpack.config.js @@ -13,6 +13,7 @@ const { actions } = require(`../redux/actions`) const debug = require(`debug`)(`gatsby:webpack-config`) const WebpackMD5Hash = require(`webpack-md5-hash`) const GatsbyModulePlugin = require(`gatsby-module-loader/plugin`) +const report = require(`gatsby-cli/lib/reporter`) const { withBasePath } = require(`./path`) const apiRunnerNode = require(`./api-runner-node`) @@ -48,11 +49,12 @@ module.exports = async ( let parsed = {} try { parsed = dotenv.parse(fs.readFileSync(envFile, { encoding: `utf8` })) - } catch (e) { - if (e && e.code !== `ENOENT`) { - console.log(e) + } catch (err) { + if (err.code !== `ENOENT`) { + report.error(`There was a problem processing the .env file`, err) } } + const envObject = Object.keys(parsed).reduce((acc, key) => { acc[key] = JSON.stringify(parsed[key]) return acc @@ -346,7 +348,7 @@ module.exports = async ( configRules = configRules.concat([ { ...rules.css(), - use: loaders.null, + use: [loaders.null()], }, rules.cssModules(), ]) @@ -389,10 +391,8 @@ module.exports = async ( if (fs.statSync(userLoaderDirectoryPath).isDirectory()) { root.push(userLoaderDirectoryPath) } - } catch (e) { - if (e && e.code !== `ENOENT`) { - console.log(e) - } + } catch (err) { + debug(`Error resolving user loaders directory`, err) } return { diff --git a/yarn.lock b/yarn.lock index 45df1ba4a9e1c..e8df9393e4689 100644 --- a/yarn.lock +++ b/yarn.lock @@ -334,9 +334,9 @@ version "7.0.0-beta.39" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.0.0-beta.39.tgz#aa7b0b60c1c20250f89d09204c03fc67e3f9806c" -"@babel/plugin-syntax-flow@7.0.0-beta.39": - version "7.0.0-beta.39" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.0.0-beta.39.tgz#b9247a81e4dacaa57aac3670792d788a64253f68" +"@babel/plugin-syntax-flow@7.0.0-beta.40": + version "7.0.0-beta.40" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.0.0-beta.40.tgz#2326da177cd83ad3d12e8324ad003edb702c384c" "@babel/plugin-syntax-function-sent@7.0.0-beta.39": version "7.0.0-beta.39" @@ -435,11 +435,11 @@ dependencies: "@babel/helper-builder-binary-assignment-operator-visitor" "7.0.0-beta.39" -"@babel/plugin-transform-flow-strip-types@7.0.0-beta.39": - version "7.0.0-beta.39" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.0.0-beta.39.tgz#3a03fc8ebaa9eddd62bdf501ceeff2a8e048bc4d" +"@babel/plugin-transform-flow-strip-types@7.0.0-beta.40": + version "7.0.0-beta.40" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.0.0-beta.40.tgz#fe3afe922de6dfbd21d9f53f01cbe1bac89e0423" dependencies: - "@babel/plugin-syntax-flow" "7.0.0-beta.39" + "@babel/plugin-syntax-flow" "7.0.0-beta.40" "@babel/plugin-transform-for-of@7.0.0-beta.39": version "7.0.0-beta.39" @@ -612,11 +612,11 @@ invariant "^2.2.2" semver "^5.3.0" -"@babel/preset-flow@^7.0.0-beta.38": - version "7.0.0-beta.39" - resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.0.0-beta.39.tgz#2a104114c71fbce992af0ed6ba633ac8f1be7277" +"@babel/preset-flow@^7.0.0-beta.40": + version "7.0.0-beta.40" + resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.0.0-beta.40.tgz#08784f5a847bf1a7fc7ea031977c5e43ef72753a" dependencies: - "@babel/plugin-transform-flow-strip-types" "7.0.0-beta.39" + "@babel/plugin-transform-flow-strip-types" "7.0.0-beta.40" "@babel/preset-react@^7.0.0-beta.38": version "7.0.0-beta.39"