diff --git a/packages/gatsby-plugin-netlify-cms/src/gatsby-node.js b/packages/gatsby-plugin-netlify-cms/src/gatsby-node.js index bd805360bb81c..daaf7600ab858 100644 --- a/packages/gatsby-plugin-netlify-cms/src/gatsby-node.js +++ b/packages/gatsby-plugin-netlify-cms/src/gatsby-node.js @@ -1,5 +1,5 @@ import path from "path" -import { get, mapValues, isPlainObject, trim } from "lodash" +import { mapValues, isPlainObject, trim } from "lodash" import webpack from "webpack" import HtmlWebpackPlugin from "html-webpack-plugin" import HtmlWebpackExcludeAssetsPlugin from "html-webpack-exclude-assets-plugin" @@ -7,23 +7,17 @@ import MiniCssExtractPlugin from "mini-css-extract-plugin" // TODO: swap back when https://github.com/geowarin/friendly-errors-webpack-plugin/pull/86 lands import FriendlyErrorsPlugin from "@pieh/friendly-errors-webpack-plugin" -/** - * Deep mapping function for plain objects and arrays. Allows any value, - * including an object or array, to be transformed. - */ +// Deep mapping function for plain objects and arrays. Allows any value, +// including an object or array, to be transformed. function deepMap(obj, fn) { - /** - * If the transform function transforms the value, regardless of type, - * return the transformed value. - */ + // If the transform function transforms the value, regardless of type, return + // the transformed value. const mapped = fn(obj) if (mapped !== obj) { return mapped } - /** - * Recursively deep map arrays and plain objects, otherwise return the value. - */ + // Recursively deep map arrays and plain objects, otherwise return the value. if (Array.isArray(obj)) { return obj.map(value => deepMap(value, fn)) } @@ -33,6 +27,42 @@ function deepMap(obj, fn) { return obj } +function replaceRule(value) { + // If `value` does not have a `test` property, it isn't a rule object. + if (!value || !value.test) { + return value + } + + // when javascript we exclude node_modules + if ( + value.type === `javascript/auto` && + value.exclude && + value.exclude instanceof RegExp + ) { + return { + ...value, + exclude: new RegExp( + [value.exclude.source, `node_modules|bower_components`].join(`|`) + ), + } + } + + // Manually swap `style-loader` for `MiniCssExtractPlugin.loader`. + // `style-loader` is only used in development, and doesn't allow us to pass + // the `styles` entry css path to Netlify CMS. + if ( + typeof value.loader === `string` && + value.loader.includes(`style-loader`) + ) { + return { + ...value, + loader: MiniCssExtractPlugin.loader, + } + } + + return value +} + exports.onCreateDevServer = ({ app, store }, { publicPath = `admin` }) => { const { program } = store.getState() const publicPathClean = trim(publicPath, `/`) @@ -49,7 +79,7 @@ exports.onCreateDevServer = ({ app, store }, { publicPath = `admin` }) => { } exports.onCreateWebpackConfig = ( - { store, stage, getConfig, plugins, pathPrefix }, + { store, stage, getConfig, plugins, pathPrefix, loaders }, { modulePath, publicPath = `admin`, @@ -79,26 +109,11 @@ exports.onCreateWebpackConfig = ( path: path.join(program.directory, `public`, publicPathClean), }, module: { - /** - * Manually swap `style-loader` for `MiniCssExtractPlugin.loader`. - * `style-loader` is only used in development, and doesn't allow us to - * pass the `styles` entry css path to Netlify CMS. - */ - rules: deepMap(gatsbyConfig.module.rules, value => { - if ( - typeof get(value, `loader`) === `string` && - value.loader.includes(`style-loader`) - ) { - return { ...value, loader: MiniCssExtractPlugin.loader } - } - return value - }), + rules: deepMap(gatsbyConfig.module.rules, replaceRule), }, plugins: [ - /** - * Remove plugins that either attempt to process the core Netlify CMS - * application, or that we want to replace with our own instance. - */ + // Remove plugins that either attempt to process the core Netlify CMS + // application, or that we want to replace with our own instance. ...gatsbyConfig.plugins.filter( plugin => ![`MiniCssExtractPlugin`, `GatsbyWebpackStatsExtractor`].find( @@ -122,49 +137,37 @@ exports.onCreateWebpackConfig = ( }, }), - /** - * Use a simple filename with no hash so we can access from source by - * path. - */ + // Use a simple filename with no hash so we can access from source by + // path. new MiniCssExtractPlugin({ filename: `[name].css`, }), - /** - * Auto generate CMS index.html page. - */ + // Auto generate CMS index.html page. new HtmlWebpackPlugin({ title: htmlTitle, chunks: [`cms`], excludeAssets: [/cms.css/], }), - /** - * Exclude CSS from index.html, as any imported styles are assumed to be - * targeting the editor preview pane. Uses `excludeAssets` option from - * `HtmlWebpackPlugin` config. - */ + // Exclude CSS from index.html, as any imported styles are assumed to be + // targeting the editor preview pane. Uses `excludeAssets` option from + // `HtmlWebpackPlugin` config. new HtmlWebpackExcludeAssetsPlugin(), - /** - * Pass in needed Gatsby config values. - */ + // Pass in needed Gatsby config values. new webpack.DefinePlugin({ __PATH__PREFIX__: pathPrefix, CMS_PUBLIC_PATH: JSON.stringify(publicPath), }), ].filter(p => p), - /** - * Remove common chunks style optimizations from Gatsby's default - * config, they cause issues for our pre-bundled code. - */ + // Remove common chunks style optimizations from Gatsby's default + // config, they cause issues for our pre-bundled code. mode: stage === `develop` ? `development` : `production`, optimization: { - /** - * Without this, node can get out of memory errors - * when building for production. - */ + // Without this, node can get out of memory errors when building for + // production. minimizer: stage === `develop` ? [] : gatsbyConfig.optimization.minimizer, }, devtool: stage === `develop` ? `cheap-module-source-map` : `source-map`,