From fc340fc972a45f429b2f3ba2b79dad4b93ce1222 Mon Sep 17 00:00:00 2001 From: mathieudutour Date: Mon, 11 Mar 2019 14:06:46 -0400 Subject: [PATCH 01/21] configuration cache path --- benchmarks/query/gatsby-node.js | 8 +++--- docs/docs/production-app.md | 2 +- examples/styleguide/gatsby-node.js | 8 ++---- packages/babel-preset-gatsby/src/index.js | 16 ++++++++--- packages/gatsby-cli/src/create-cli.js | 23 +++++++++++++++- .../gatsby-plugin-guess-js/src/gatsby-ssr.js | 11 +++----- .../src/gatsby-browser.js | 7 ++--- .../src/gatsby-node.js | 12 ++++----- .../src/gatsby-ssr.js | 4 +-- .../src/cache-image.js | 7 ++--- .../gatsby-source-contentful/src/constants.js | 1 + .../src/extend-node-type.js | 4 +-- .../src/gatsby-node.js | 12 ++++----- packages/gatsby-source-filesystem/README.md | 3 --- .../src/create-remote-file-node.js | 14 +--------- .../src/gatsby-node.js | 8 +++--- .../src/extend-node-type.js | 12 ++++----- packages/gatsby/src/bootstrap/index.js | 13 ++++----- packages/gatsby/src/commands/clean.js | 3 ++- packages/gatsby/src/commands/serve.js | 3 ++- .../dev-404-page/gatsby-node.js | 9 ++----- .../load-babel-config/gatsby-node.js | 8 +++--- .../query-runner/pages-writer.js | 8 +++--- .../query-runner/query-compiler.js | 3 ++- .../query-runner/redirects-writer.js | 3 ++- packages/gatsby/src/redux/actions.js | 3 ++- packages/gatsby/src/redux/index.js | 5 ++-- .../gatsby/src/utils/babel-loader-helpers.js | 6 ++--- packages/gatsby/src/utils/cache.js | 27 ++++++++++++++++++- .../gatsby/src/utils/test-require-error.js | 2 +- packages/gatsby/src/utils/webpack.config.js | 18 ++++++------- 31 files changed, 145 insertions(+), 118 deletions(-) create mode 100644 packages/gatsby-source-contentful/src/constants.js diff --git a/benchmarks/query/gatsby-node.js b/benchmarks/query/gatsby-node.js index 40bd221ac4e04..7779eb5327ccf 100644 --- a/benchmarks/query/gatsby-node.js +++ b/benchmarks/query/gatsby-node.js @@ -85,9 +85,9 @@ function allTypeQuery(typeName) { } // Create template in .cache for the received type -function createTemplateFile(typeName) { +function createTemplateFile(cache, typeName) { const templateSrc = createPageTemplateJs(typeName) - const templateFilename = `./.cache/${typeName}Template.js` + const templateFilename = cache.rootPath(`./${typeName}Template.js`) fs.writeFileSync(templateFilename, templateSrc) return templateFilename } @@ -99,10 +99,10 @@ async function createNode(graphql, typeName) { } // Create page for each type -exports.createPages = async ({ actions, graphql }) => { +exports.createPages = async ({ actions, graphql, cache }) => { for (let i = 0; i < types.length; i++) { const typeName = types[i] - const templateFilename = createTemplateFile(typeName) + const templateFilename = createTemplateFile(cache, typeName) const edges = await createNode(graphql, typeName) _.forEach(edges, ({ node }) => { actions.createPage({ diff --git a/docs/docs/production-app.md b/docs/docs/production-app.md index 2889b4fba9859..00192a003c171 100644 --- a/docs/docs/production-app.md +++ b/docs/docs/production-app.md @@ -89,7 +89,7 @@ The first thing our app does is run the [onClientEntry](/docs/browser-apis/#onCl It's worth noting that the browser API runner is completely different to `api-runner-node` which is explained in [How APIs/Plugins Are Run](/docs/how-plugins-apis-are-run/). `api-runner-node` runs in Node.js and has to deal with complex server based execution paths. Whereas running APIs on the browser is simply a matter of iterating through the site's registered browser plugins and running them one after the other (see [api-runner-browser.js](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/cache-dir/api-runner-browser.js#L9)). -One thing to note is that it gets the list of plugins from `./cache/api-runner-browser-plugins.js`, which is generated [early in bootstrap](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/bootstrap/index.js#L338). +One thing to note is that it gets the list of plugins from `./.cache/api-runner-browser-plugins.js`, which is generated [early in bootstrap](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/bootstrap/index.js#L338). ### DOM Hydration diff --git a/examples/styleguide/gatsby-node.js b/examples/styleguide/gatsby-node.js index f9392a2d1ff65..c24284f28d831 100644 --- a/examples/styleguide/gatsby-node.js +++ b/examples/styleguide/gatsby-node.js @@ -1,13 +1,12 @@ const path = require(`path`) const fs = require(`fs`) -const appRootDir = require(`app-root-dir`).get() const componentPageTemplate = path.resolve( `src/templates/ComponentPage/index.js` ) const tableOfContentsTemplate = path.resolve(`src/templates/TOC/index.js`) -exports.createPages = ({ graphql, actions }) => { +exports.createPages = ({ graphql, actions, cache }) => { const { createPage } = actions return new Promise((resolve, reject) => { @@ -83,10 +82,7 @@ exports.createPages = ({ graphql, actions }) => { }, []) .join(`\n`) + `\n` - fs.writeFileSync( - path.join(appRootDir, `.cache/components.js`), - exportFileContents - ) + fs.writeFileSync(cache.rootPath(`components.js`), exportFileContents) allComponents.forEach(data => { const { filePath } = data diff --git a/packages/babel-preset-gatsby/src/index.js b/packages/babel-preset-gatsby/src/index.js index d0842a53188b8..760912dcced10 100644 --- a/packages/babel-preset-gatsby/src/index.js +++ b/packages/babel-preset-gatsby/src/index.js @@ -2,14 +2,22 @@ const path = require(`path`) const resolve = m => require.resolve(m) +const cachePath = filePath => { + const { GATSBY_CACHE } = process.env + if (GATSBY_CACHE) { + if (path.isAbsolute(GATSBY_CACHE)) { + return path.join(GATSBY_CACHE, filePath) + } + return path.join(process.cwd(), GATSBY_CACHE, filePath) + } + return path.join(process.cwd(), `./.cache`, filePath) +} + const loadCachedConfig = () => { let pluginBabelConfig = {} if (process.env.NODE_ENV !== `test`) { try { - pluginBabelConfig = require(path.join( - process.cwd(), - `./.cache/babelState.json` - )) + pluginBabelConfig = require(cachePath(`babelState.json`)) } catch (err) { if (err.message.includes(`Cannot find module`)) { // This probably is being used outside of the Gatsby CLI. diff --git a/packages/gatsby-cli/src/create-cli.js b/packages/gatsby-cli/src/create-cli.js index 943e81639fde6..3cf4dc31c672b 100644 --- a/packages/gatsby-cli/src/create-cli.js +++ b/packages/gatsby-cli/src/create-cli.js @@ -15,6 +15,7 @@ const handlerP = fn => (...args) => { function buildLocalCommands(cli, isLocalSite) { const defaultHost = `localhost` + const defaultCache = `.cache` const directory = path.resolve(`.`) // 'not dead' query not available in browserslist used in Gatsby v1 @@ -142,10 +143,16 @@ function buildLocalCommands(cli, isLocalSite) { .option(`open-tracing-config-file`, { type: `string`, describe: `Tracer configuration file (open tracing compatible). See https://www.gatsbyjs.org/docs/performance-tracing/`, + }) + .option(`cache-dir`, { + type: `string`, + default: defaultCache, + describe: `Set cache location. Defaults to ${defaultCache}`, }), handler: handlerP( getCommandHandler(`develop`, (args, cmd) => { process.env.NODE_ENV = process.env.NODE_ENV || `development` + process.env.GATSBY_CACHE = args.cacheDir cmd(args) // Return an empty promise to prevent handlerP from exiting early. // The development server shouldn't ever exit until the user directly @@ -172,10 +179,16 @@ function buildLocalCommands(cli, isLocalSite) { .option(`open-tracing-config-file`, { type: `string`, describe: `Tracer configuration file (open tracing compatible). See https://www.gatsbyjs.org/docs/performance-tracing/`, + }) + .option(`cache-dir`, { + type: `string`, + default: defaultCache, + describe: `Set cache location. Defaults to ${defaultCache}`, }), handler: handlerP( getCommandHandler(`build`, (args, cmd) => { process.env.NODE_ENV = `production` + process.env.GATSBY_CACHE = args.cacheDir return cmd(args) }) ), @@ -206,9 +219,17 @@ function buildLocalCommands(cli, isLocalSite) { type: `boolean`, default: false, describe: `Serve site with link paths prefixed (if built with pathPrefix in your gatsby-config.js).`, + }) + .option(`cache-dir`, { + type: `string`, + default: defaultCache, + describe: `Set cache location. Defaults to ${defaultCache}`, }), - handler: getCommandHandler(`serve`), + handler: getCommandHandler(`serve`, (args, cmd) => { + process.env.GATSBY_CACHE = args.cacheDir + return cmd(args) + }), }) cli.command({ diff --git a/packages/gatsby-plugin-guess-js/src/gatsby-ssr.js b/packages/gatsby-plugin-guess-js/src/gatsby-ssr.js index d0c0e96b1ddaf..3f36be504a126 100644 --- a/packages/gatsby-plugin-guess-js/src/gatsby-ssr.js +++ b/packages/gatsby-plugin-guess-js/src/gatsby-ssr.js @@ -1,5 +1,4 @@ const _ = require(`lodash`) -const nodePath = require(`path`) const fs = require(`fs`) const React = require(`react`) @@ -13,13 +12,11 @@ function urlJoin(...parts) { } let pd = [] -const readPageData = () => { +const readPageData = cache => { if (pd.length > 0) { return pd } else { - pd = JSON.parse( - fs.readFileSync(nodePath.join(process.cwd(), `.cache`, `data.json`)) - ) + pd = JSON.parse(fs.readFileSync(cache.rootPath(`data.json`))) return pd } } @@ -37,11 +34,11 @@ const readStats = () => { } exports.onRenderBody = ( - { setHeadComponents, pathname, pathPrefix }, + { setHeadComponents, pathname, pathPrefix, cache }, pluginOptions ) => { if (process.env.NODE_ENV === `production`) { - const pagesData = readPageData() + const pagesData = readPageData(cache) const stats = readStats() const matchedPaths = Object.keys( guess({ path: pathname, threshold: pluginOptions.minimumThreshold }) diff --git a/packages/gatsby-plugin-typography/src/gatsby-browser.js b/packages/gatsby-plugin-typography/src/gatsby-browser.js index 78be662204ed6..d3199ee134f8c 100644 --- a/packages/gatsby-plugin-typography/src/gatsby-browser.js +++ b/packages/gatsby-plugin-typography/src/gatsby-browser.js @@ -9,11 +9,12 @@ if (process.env.BUILD_STAGE === `develop`) { ReactDOMServer = require(`react-dom/server`) React = require(`react`) GoogleFont = require(`react-typography`).GoogleFont - // typography links to the file set in "pathToConfigModule" - const typographyConfig = require(`./.cache/typography.js`) - typography = typographyConfig.default || typographyConfig exports.onClientEntry = (a, pluginOptions) => { + // typography links to the file set in "pathToConfigModule" + const typographyConfig = require(a.cache.rootPath(`typography.js`)) + typography = typographyConfig.default || typographyConfig + // Inject the CSS Styles typography.injectStyles() diff --git a/packages/gatsby-plugin-typography/src/gatsby-node.js b/packages/gatsby-plugin-typography/src/gatsby-node.js index 92c3fcee55726..f9ed417385ae3 100644 --- a/packages/gatsby-plugin-typography/src/gatsby-node.js +++ b/packages/gatsby-plugin-typography/src/gatsby-node.js @@ -2,9 +2,9 @@ const fs = require(`fs`) const path = require(`path`) const os = require(`os`) -// Write out a typography module to .cache. +// Write out a typography module to the cache. -exports.onPreBootstrap = ({ store }, pluginOptions) => { +exports.onPreBootstrap = ({ store, cache }, pluginOptions) => { const program = store.getState().program let module @@ -23,11 +23,9 @@ const typography = new Typography() module.exports = typography` } - const dir = `${__dirname}/.cache` - - if (!fs.existsSync(dir)) { - fs.mkdirSync(dir) + if (!fs.existsSync(cache.rootDirectory)) { + fs.mkdirSync(cache.rootDirectory) } - fs.writeFileSync(`${dir}/typography.js`, module) + fs.writeFileSync(`${cache.rootPath(`typography.js`)}`, module) } diff --git a/packages/gatsby-plugin-typography/src/gatsby-ssr.js b/packages/gatsby-plugin-typography/src/gatsby-ssr.js index b0156b076f51a..eed742943d77d 100644 --- a/packages/gatsby-plugin-typography/src/gatsby-ssr.js +++ b/packages/gatsby-plugin-typography/src/gatsby-ssr.js @@ -1,8 +1,8 @@ import React from "react" import { TypographyStyle, GoogleFont } from "react-typography" -import typography from "./.cache/typography" -exports.onRenderBody = ({ setHeadComponents }, pluginOptions) => { +exports.onRenderBody = ({ setHeadComponents, cache }, pluginOptions) => { + const typography = require(cache.rootPath(`typography`)) if (process.env.BUILD_STAGE === `build-html`) { const googleFont = [].concat( pluginOptions.omitGoogleFont ? ( diff --git a/packages/gatsby-source-contentful/src/cache-image.js b/packages/gatsby-source-contentful/src/cache-image.js index a0a9bb30b04d5..0c663fee236c3 100644 --- a/packages/gatsby-source-contentful/src/cache-image.js +++ b/packages/gatsby-source-contentful/src/cache-image.js @@ -4,9 +4,10 @@ const { resolve, parse } = require(`path`) const axios = require(`axios`) const { pathExists, createWriteStream } = require(`fs-extra`) -module.exports = async function cacheImage(store, image, options) { - const program = store.getState().program - const CACHE_DIR = resolve(`${program.directory}/.cache/contentful/assets/`) +const { CACHE_NAME } = require(`./constants`) + +module.exports = async function cacheImage(cache, image, options) { + const CACHE_DIR = resolve(cache.rootPath(CACHE_NAME)) const { file: { url, fileName, details }, } = image diff --git a/packages/gatsby-source-contentful/src/constants.js b/packages/gatsby-source-contentful/src/constants.js new file mode 100644 index 0000000000000..8f9d574516b95 --- /dev/null +++ b/packages/gatsby-source-contentful/src/constants.js @@ -0,0 +1 @@ +module.exports.CACHE_NAME = `contentful/assets/` diff --git a/packages/gatsby-source-contentful/src/extend-node-type.js b/packages/gatsby-source-contentful/src/extend-node-type.js index 7c45c2f7e17a1..fa6f2b58f0215 100644 --- a/packages/gatsby-source-contentful/src/extend-node-type.js +++ b/packages/gatsby-source-contentful/src/extend-node-type.js @@ -458,7 +458,7 @@ const fluidNodeType = ({ name, getTracedSVG }) => { } } -exports.extendNodeType = ({ type, store }) => { +exports.extendNodeType = ({ type, cache }) => { if (type.name.match(/contentful.*RichTextNode/)) { return { nodeType: { @@ -491,7 +491,7 @@ exports.extendNodeType = ({ type, store }) => { return null } - const absolutePath = await cacheImage(store, image, options) + const absolutePath = await cacheImage(cache, image, options) const extension = path.extname(absolutePath) return traceSVG({ diff --git a/packages/gatsby-source-contentful/src/gatsby-node.js b/packages/gatsby-source-contentful/src/gatsby-node.js index ee68091e34669..f22c805cb2424 100644 --- a/packages/gatsby-source-contentful/src/gatsby-node.js +++ b/packages/gatsby-source-contentful/src/gatsby-node.js @@ -6,6 +6,8 @@ const fs = require(`fs-extra`) const normalize = require(`./normalize`) const fetchData = require(`./fetch`) +const { CACHE_NAME } = require(`./constants`) + const conflictFieldPrefix = `contentful` // restrictedNodeFields from here https://www.gatsbyjs.org/docs/node-interface/ @@ -215,12 +217,8 @@ exports.sourceNodes = async ( // Check if there are any ContentfulAsset nodes and if gatsby-image is installed. If so, // add fragments for ContentfulAsset and gatsby-image. The fragment will cause an error // if there's not ContentfulAsset nodes and without gatsby-image, the fragment is useless. -exports.onPreExtractQueries = async ({ store, getNodesByType }) => { - const program = store.getState().program - - const CACHE_DIR = path.resolve( - `${program.directory}/.cache/contentful/assets/` - ) +exports.onPreExtractQueries = async ({ cache, getNodesByType }) => { + const CACHE_DIR = path.resolve(cache.rootPath(CACHE_NAME)) await fs.ensureDir(CACHE_DIR) if (getNodesByType(`ContentfulAsset`).length == 0) { @@ -243,6 +241,6 @@ exports.onPreExtractQueries = async ({ store, getNodesByType }) => { // add our fragments to .cache/fragments. await fs.copy( require.resolve(`gatsby-source-contentful/src/fragments.js`), - `${program.directory}/.cache/fragments/contentful-asset-fragments.js` + cache.rootPath(`fragments/contentful-asset-fragments.js`) ) } diff --git a/packages/gatsby-source-filesystem/README.md b/packages/gatsby-source-filesystem/README.md index 177433c737b3a..12791ab4d5ec8 100644 --- a/packages/gatsby-source-filesystem/README.md +++ b/packages/gatsby-source-filesystem/README.md @@ -197,7 +197,6 @@ const { createRemoteFileNode } = require(`gatsby-source-filesystem`) exports.downloadMediaFiles = ({ nodes, - store, cache, createNode, createNodeId, @@ -212,7 +211,6 @@ exports.downloadMediaFiles = ({ fileNode = await createRemoteFileNode({ url: node.source_url, parentNodeId: node.id, - store, cache, createNode, createNodeId, @@ -243,7 +241,6 @@ createRemoteFileNode({ // The source url of the remote file url: `https://example.com/a-file-without-an-extension`, parentNodeId: node.id, - store, cache, createNode, createNodeId, diff --git a/packages/gatsby-source-filesystem/src/create-remote-file-node.js b/packages/gatsby-source-filesystem/src/create-remote-file-node.js index 7f6d1cf09ae96..808a84ac37164 100644 --- a/packages/gatsby-source-filesystem/src/create-remote-file-node.js +++ b/packages/gatsby-source-filesystem/src/create-remote-file-node.js @@ -47,7 +47,6 @@ const bar = new ProgressBar( * @description Create Remote File Node Payload * * @param {String} options.url - * @param {Redux} options.store * @param {GatsbyCache} options.cache * @param {Function} options.createNode * @param {Auth} [options.auth] @@ -71,7 +70,6 @@ const createHash = str => .update(str) .digest(`hex`) -const CACHE_DIR = `.cache` const FS_PLUGIN_DIR = `gatsby-source-filesystem` /** @@ -180,7 +178,6 @@ const requestRemoteNode = (url, headers, tmpFilename) => */ async function processRemoteNode({ url, - store, cache, createNode, parentNodeId, @@ -190,11 +187,7 @@ async function processRemoteNode({ name, }) { // Ensure our cache directory exists. - const pluginCacheDir = path.join( - store.getState().program.directory, - CACHE_DIR, - FS_PLUGIN_DIR - ) + const pluginCacheDir = cache.rootPath(FS_PLUGIN_DIR) await fs.ensureDir(pluginCacheDir) // See if there's response headers for this url @@ -307,7 +300,6 @@ let totalJobs = 0 */ module.exports = ({ url, - store, cache, createNode, parentNodeId = null, @@ -327,9 +319,6 @@ module.exports = ({ if (typeof createNode !== `function`) { throw new Error(`createNode must be a function, was ${typeof createNode}`) } - if (typeof store !== `object`) { - throw new Error(`store must be the redux store, was ${typeof store}`) - } if (typeof cache !== `object`) { throw new Error(`cache must be the Gatsby cache, was ${typeof cache}`) } @@ -351,7 +340,6 @@ module.exports = ({ const fileDownloadPromise = pushTask({ url, - store, cache, createNode, parentNodeId, diff --git a/packages/gatsby-transformer-sharp/src/gatsby-node.js b/packages/gatsby-transformer-sharp/src/gatsby-node.js index 3f9433c15f639..cfdbfbdef1947 100644 --- a/packages/gatsby-transformer-sharp/src/gatsby-node.js +++ b/packages/gatsby-transformer-sharp/src/gatsby-node.js @@ -3,18 +3,16 @@ const fs = require(`fs-extra`) exports.onCreateNode = require(`./on-node-create`) exports.setFieldsOnGraphQLNodeType = require(`./extend-node-type`) -exports.onPreExtractQueries = async ({ store, getNodesByType }) => { - const program = store.getState().program - +exports.onPreExtractQueries = async ({ cache, getNodesByType }) => { // Check if there are any ImageSharp nodes. If so add fragments for ImageSharp. // The fragment will cause an error if there are no ImageSharp nodes. if (getNodesByType(`ImageSharp`).length == 0) { return } - // We have ImageSharp nodes so let's add our fragments to .cache/fragments. + // We have ImageSharp nodes so let's add our fragments to cache/fragments. await fs.copy( require.resolve(`gatsby-transformer-sharp/src/fragments.js`), - `${program.directory}/.cache/fragments/image-sharp-fragments.js` + cache.rootPath(`fragments/image-sharp-fragments.js`) ) } diff --git a/packages/gatsby-transformer-sqip/src/extend-node-type.js b/packages/gatsby-transformer-sqip/src/extend-node-type.js index 5ed8261a51c2c..97d0ccbd5a333 100644 --- a/packages/gatsby-transformer-sqip/src/extend-node-type.js +++ b/packages/gatsby-transformer-sqip/src/extend-node-type.js @@ -41,9 +41,8 @@ module.exports = async args => { return {} } -async function sqipSharp({ type, cache, getNodeAndSavePathDependency, store }) { - const program = store.getState().program - const cacheDir = resolve(`${program.directory}/.cache/sqip/`) +async function sqipSharp({ type, cache, getNodeAndSavePathDependency }) { + const cacheDir = resolve(cache.rootPath(`/sqip/`)) await ensureDir(cacheDir) @@ -130,15 +129,14 @@ async function sqipSharp({ type, cache, getNodeAndSavePathDependency, store }) { } } -async function sqipContentful({ type, cache, store }) { +async function sqipContentful({ type, cache }) { const { schemes: { ImageResizingBehavior, ImageCropFocusType }, } = require(`gatsby-source-contentful`) const cacheImage = require(`gatsby-source-contentful/cache-image`) - const program = store.getState().program - const cacheDir = resolve(`${program.directory}/.cache/sqip/`) + const cacheDir = resolve(cache.rootPath(`/sqip/`)) await ensureDir(cacheDir) @@ -217,7 +215,7 @@ async function sqipContentful({ type, cache, store }) { background, } - const absolutePath = await cacheImage(store, asset, options) + const absolutePath = await cacheImage(cache, asset, options) return generateSqip({ cache, diff --git a/packages/gatsby/src/bootstrap/index.js b/packages/gatsby/src/bootstrap/index.js index f29a1b63beb1d..026b53b8536d7 100644 --- a/packages/gatsby/src/bootstrap/index.js +++ b/packages/gatsby/src/bootstrap/index.js @@ -12,6 +12,7 @@ const Promise = require(`bluebird`) const apiRunnerNode = require(`../utils/api-runner-node`) const getBrowserslist = require(`../utils/browserslist`) +const { getCachePath } = require(`../utils/cache`) const { graphql } = require(`graphql`) const { store, emitter } = require(`../redux`) const loadPlugins = require(`./load-plugins`) @@ -165,7 +166,7 @@ module.exports = async (args: BootstrapArgs) => { let state = store.getState() const oldPluginsHash = state && state.status ? state.status.PLUGINS_HASH : `` - // Check if anything has changed. If it has, delete the site's .cache + // Check if anything has changed. If it has, delete the site's cache // directory and tell reducers to empty themselves. // // Also if the hash isn't there, then delete things just in case something @@ -177,14 +178,14 @@ module.exports = async (args: BootstrapArgs) => { data `) } - const cacheDirectory = `${program.directory}/.cache` + const cacheDirectory = getCachePath() if (!oldPluginsHash || pluginsHash !== oldPluginsHash) { try { // Attempt to empty dir if remove fails, // like when directory is mount point await fs.remove(cacheDirectory).catch(() => fs.emptyDir(cacheDirectory)) } catch (e) { - report.error(`Failed to remove .cache files.`, e) + report.error(`Failed to remove cache files.`, e) } // Tell reducers to delete their data (the store will already have // been loaded from the file system cache). @@ -199,7 +200,7 @@ module.exports = async (args: BootstrapArgs) => { payload: pluginsHash, }) - // Now that we know the .cache directory is safe, initialize the cache + // Now that we know the cache directory is safe, initialize the cache // directory. await fs.ensureDir(cacheDirectory) @@ -251,12 +252,12 @@ module.exports = async (args: BootstrapArgs) => { }) await fs.ensureDirSync(`${cacheDirectory}/json`) - // Ensure .cache/fragments exists and is empty. We want fragments to be + // Ensure cache/fragments exists and is empty. We want fragments to be // added on every run in response to data as fragments can only be added if // the data used to create the schema they're dependent on is available. await fs.emptyDir(`${cacheDirectory}/fragments`) } catch (err) { - report.panic(`Unable to copy site files to .cache`, err) + report.panic(`Unable to copy site files to cache`, err) } // Find plugins which implement gatsby-browser and gatsby-ssr and write diff --git a/packages/gatsby/src/commands/clean.js b/packages/gatsby/src/commands/clean.js index b9e0752c21694..1fcfb5f5c222e 100644 --- a/packages/gatsby/src/commands/clean.js +++ b/packages/gatsby/src/commands/clean.js @@ -1,10 +1,11 @@ const fs = require(`fs-extra`) const path = require(`path`) +const { getCachePath } = require(`../utils/cache`) module.exports = async function clean(args) { const { directory, report } = args - const directories = [`.cache`, `public`] + const directories = [getCachePath(directory), `public`] report.info(`Deleting ${directories.join(`, `)}`) diff --git a/packages/gatsby/src/commands/serve.js b/packages/gatsby/src/commands/serve.js index 9ed5fe0a74d36..07271833d7b96 100644 --- a/packages/gatsby/src/commands/serve.js +++ b/packages/gatsby/src/commands/serve.js @@ -7,12 +7,13 @@ const compression = require(`compression`) const express = require(`express`) const getConfigFile = require(`../bootstrap/get-config-file`) const preferDefault = require(`../bootstrap/prefer-default`) +const { getCachePath } = require(`../utils/cache`) const chalk = require(`chalk`) const { match: reachMatch } = require(`@reach/router/lib/utils`) const getPages = directory => fs - .readFile(path.join(directory, `.cache`, `pages.json`)) + .readFile(path.join(getCachePath(directory), `pages.json`)) .then(contents => JSON.parse(contents)) .catch(() => []) diff --git a/packages/gatsby/src/internal-plugins/dev-404-page/gatsby-node.js b/packages/gatsby/src/internal-plugins/dev-404-page/gatsby-node.js index 1204fa110c985..ebf91ec1f87df 100644 --- a/packages/gatsby/src/internal-plugins/dev-404-page/gatsby-node.js +++ b/packages/gatsby/src/internal-plugins/dev-404-page/gatsby-node.js @@ -2,16 +2,11 @@ const path = require(`path`) const fs = require(`fs-extra`) const chokidar = require(`chokidar`) -exports.createPagesStatefully = async ({ store, actions }, options, done) => { +exports.createPagesStatefully = async ({ actions, cache }, options, done) => { if (process.env.NODE_ENV !== `production`) { - const { program } = store.getState() const { createPage } = actions const source = path.join(__dirname, `./raw_dev-404-page.js`) - const destination = path.join( - program.directory, - `.cache`, - `dev-404-page.js` - ) + const destination = cache.rootPath(`dev-404-page.js`) const copy = () => fs.copy(source, destination) await copy() createPage({ diff --git a/packages/gatsby/src/internal-plugins/load-babel-config/gatsby-node.js b/packages/gatsby/src/internal-plugins/load-babel-config/gatsby-node.js index 5f0cf62307ef6..5042a271245b2 100644 --- a/packages/gatsby/src/internal-plugins/load-babel-config/gatsby-node.js +++ b/packages/gatsby/src/internal-plugins/load-babel-config/gatsby-node.js @@ -3,11 +3,9 @@ const fs = require(`fs-extra`) const apiRunnerNode = require(`../../utils/api-runner-node`) -const { withBasePath } = require(`../../utils/path`) -exports.onPreBootstrap = async ({ store }) => { - const { directory, browserslist } = store.getState().program - const directoryPath = withBasePath(directory) +exports.onPreBootstrap = async ({ cache, store }) => { + const { browserslist } = store.getState().program await apiRunnerNode(`onCreateBabelConfig`, { stage: `develop`, @@ -31,5 +29,5 @@ exports.onPreBootstrap = async ({ store }) => { 2 ) - await fs.writeFile(directoryPath(`.cache/babelState.json`), babelState) + await fs.writeFile(cache.rootPath(`babelState.json`), babelState) } diff --git a/packages/gatsby/src/internal-plugins/query-runner/pages-writer.js b/packages/gatsby/src/internal-plugins/query-runner/pages-writer.js index 10e8c21e76bd9..b59f8fec8bd3f 100644 --- a/packages/gatsby/src/internal-plugins/query-runner/pages-writer.js +++ b/packages/gatsby/src/internal-plugins/query-runner/pages-writer.js @@ -3,6 +3,7 @@ const fs = require(`fs-extra`) const crypto = require(`crypto`) const { store, emitter } = require(`../../redux/`) +const { getCachePath } = require(`../../utils/cache`) import { joinPath } from "../../utils/path" @@ -58,6 +59,8 @@ const writePages = async () => { return Promise.resolve() } + const cacheDirectory = getCachePath() + lastHash = newHash // Get list of components, and json files. @@ -102,13 +105,12 @@ const preferDefault = m => m && m.default || m }\n\n` asyncRequires += `exports.data = () => import(/* webpackChunkName: "pages-manifest" */ "${joinPath( - program.directory, - `.cache`, + cacheDirectory, `data.json` )}")\n\n` const writeAndMove = (file, data) => { - const destination = joinPath(program.directory, `.cache`, file) + const destination = joinPath(cacheDirectory, file) const tmp = `${destination}.${Date.now()}` return fs .writeFile(tmp, data) diff --git a/packages/gatsby/src/internal-plugins/query-runner/query-compiler.js b/packages/gatsby/src/internal-plugins/query-runner/query-compiler.js index 9965885e72762..6e85efc3d8100 100644 --- a/packages/gatsby/src/internal-plugins/query-runner/query-compiler.js +++ b/packages/gatsby/src/internal-plugins/query-runner/query-compiler.js @@ -21,6 +21,7 @@ import { } from "./graphql-errors" import report from "gatsby-cli/lib/reporter" const websocketManager = require(`../../utils/websocket-manager`) +const { getCachePath } = require(`../../utils/cache`) import type { DocumentNode, GraphQLSchema } from "graphql" @@ -101,7 +102,7 @@ class Runner { const filesRegex = path.join(`/**`, `*.+(t|j)s?(x)`) let files = [ path.join(this.base, `src`), - path.join(this.base, `.cache`, `fragments`), + path.join(getCachePath(this.base), `fragments`), ] .concat(this.additional.map(additional => path.join(additional, `src`))) .reduce( diff --git a/packages/gatsby/src/internal-plugins/query-runner/redirects-writer.js b/packages/gatsby/src/internal-plugins/query-runner/redirects-writer.js index da2452107af2d..f1294329b1f21 100644 --- a/packages/gatsby/src/internal-plugins/query-runner/redirects-writer.js +++ b/packages/gatsby/src/internal-plugins/query-runner/redirects-writer.js @@ -3,6 +3,7 @@ import crypto from "crypto" import fs from "fs-extra" import { store, emitter } from "../../redux/" import { joinPath } from "../../utils/path" +const { getCachePath } = require(`../../utils/cache`) let lastHash = null @@ -26,7 +27,7 @@ const writeRedirects = async () => { lastHash = newHash return await fs.writeFile( - joinPath(program.directory, `.cache/redirects.json`), + joinPath(getCachePath(program.directory), `redirects.json`), JSON.stringify(browserRedirects, null, 2) ) } diff --git a/packages/gatsby/src/redux/actions.js b/packages/gatsby/src/redux/actions.js index 313a47c9e8677..90da89a5e53d3 100644 --- a/packages/gatsby/src/redux/actions.js +++ b/packages/gatsby/src/redux/actions.js @@ -17,6 +17,7 @@ const { store } = require(`./index`) const fileExistsSync = require(`fs-exists-cached`).sync const joiSchemas = require(`../joi-schemas/joi`) const { generateComponentChunkName } = require(`../utils/js-chunk-names`) +const { getCachePath } = require(`../utils/cache`) const actions = {} @@ -288,7 +289,7 @@ ${reservedFields.map(f => ` * "${f}"`).join(`\n`)} // // Only run validation once during builds. if ( - !internalPage.component.includes(`/.cache/`) && + !internalPage.component.includes(getCachePath()) && (process.env.NODE_ENV === `production` && !fileOkCache[internalPage.component]) ) { diff --git a/packages/gatsby/src/redux/index.js b/packages/gatsby/src/redux/index.js index 856c58c6ec5d0..076d4642087ec 100644 --- a/packages/gatsby/src/redux/index.js +++ b/packages/gatsby/src/redux/index.js @@ -3,6 +3,7 @@ const _ = require(`lodash`) const fs = require(`fs-extra`) const mitt = require(`mitt`) const stringify = require(`json-stringify-safe`) +const { getCachePath } = require(`../utils/cache`) // Create event emitter for actions const emitter = mitt() @@ -29,7 +30,7 @@ const mapToObject = map => { // Read from cache the old node data. let initialState = {} try { - const file = fs.readFileSync(`${process.cwd()}/.cache/redux-state.json`) + const file = fs.readFileSync(`${getCachePath()}/redux-state.json`) // Apparently the file mocking in node-tracking-test.js // can override the file reading replacing the mocked string with // an already parsed object. @@ -89,7 +90,7 @@ function saveState() { pickedState.components = mapToObject(pickedState.components) pickedState.nodes = pickedState.nodes ? mapToObject(pickedState.nodes) : [] const stringified = stringify(pickedState, null, 2) - return fs.writeFile(`${process.cwd()}/.cache/redux-state.json`, stringified) + return fs.writeFile(`${getCachePath()}/redux-state.json`, stringified) } exports.saveState = saveState diff --git a/packages/gatsby/src/utils/babel-loader-helpers.js b/packages/gatsby/src/utils/babel-loader-helpers.js index 8d7b9ea837494..205b5d4b2b461 100644 --- a/packages/gatsby/src/utils/babel-loader-helpers.js +++ b/packages/gatsby/src/utils/babel-loader-helpers.js @@ -1,5 +1,6 @@ const path = require(`path`) const _ = require(`lodash`) +const { getCachePath } = require(`./cache`) const loadCachedConfig = () => { let pluginBabelConfig = { @@ -8,10 +9,7 @@ const loadCachedConfig = () => { }, } if (process.env.NODE_ENV !== `test`) { - pluginBabelConfig = require(path.join( - process.cwd(), - `./.cache/babelState.json` - )) + pluginBabelConfig = require(path.join(getCachePath(), `./babelState.json`)) } return pluginBabelConfig } diff --git a/packages/gatsby/src/utils/cache.js b/packages/gatsby/src/utils/cache.js index 7dbac24859a62..5108dc6a47d9c 100644 --- a/packages/gatsby/src/utils/cache.js +++ b/packages/gatsby/src/utils/cache.js @@ -6,6 +6,21 @@ const path = require(`path`) const MAX_CACHE_SIZE = 250 const TTL = Number.MAX_SAFE_INTEGER +function getCachePath(cwd) { + const { GATSBY_CACHE } = process.env + if (GATSBY_CACHE) { + if (path.isAbsolute(GATSBY_CACHE)) { + return GATSBY_CACHE + } + return path.join(cwd || process.cwd(), GATSBY_CACHE) + } + return path.join(cwd || process.cwd(), `./.cache`) +} + +function cachePath(filePath, cwd) { + return path.join(getCachePath(cwd), filePath) +} + class Cache { constructor({ name = `db`, store = fsStore } = {}) { this.name = name @@ -13,7 +28,15 @@ class Cache { } get directory() { - return path.join(process.cwd(), `.cache/caches/${this.name}`) + return cachePath(`caches/${this.name}`) + } + + get rootDirectory() { + return getCachePath() + } + + rootPath(filePath) { + return cachePath(filePath) } init() { @@ -56,3 +79,5 @@ class Cache { } module.exports = Cache +module.exports.getCachePath = getCachePath +module.exports.cachePath = cachePath diff --git a/packages/gatsby/src/utils/test-require-error.js b/packages/gatsby/src/utils/test-require-error.js index 7f44a2f87ad05..64e2f0e0b7b84 100644 --- a/packages/gatsby/src/utils/test-require-error.js +++ b/packages/gatsby/src/utils/test-require-error.js @@ -1,4 +1,4 @@ -// This module is also copied into the .cache directory some modules copied there +// This module is also copied into the cache directory some modules copied there // from cache-dir can also use this module. export default (moduleName, err) => { const regex = new RegExp( diff --git a/packages/gatsby/src/utils/webpack.config.js b/packages/gatsby/src/utils/webpack.config.js index c3cbcb05db7e0..58e9c519b7ad2 100644 --- a/packages/gatsby/src/utils/webpack.config.js +++ b/packages/gatsby/src/utils/webpack.config.js @@ -13,6 +13,7 @@ const { withBasePath } = require(`./path`) const apiRunnerNode = require(`./api-runner-node`) const createUtils = require(`./webpack-utils`) const hasLocalEslint = require(`./local-eslint-config-finder`) +const { getCachePath } = require(`./cache`) // Four stages or modes: // 1) develop: for `gatsby develop` command, hot reload and CSS injection into page @@ -27,6 +28,7 @@ module.exports = async ( webpackPort = 1500 ) => { const directoryPath = withBasePath(directory) + const cachePath = withBasePath(getCachePath(directory)) process.env.GATSBY_BUILD_STAGE = suppliedStage @@ -153,20 +155,20 @@ module.exports = async ( `${require.resolve( `webpack-hot-middleware/client` )}?path=${getHmrPath()}`, - directoryPath(`.cache/app`), + cachePath(`app`), ], } case `develop-html`: return { - main: directoryPath(`.cache/develop-static-entry`), + main: cachePath(`develop-static-entry`), } case `build-html`: return { - main: directoryPath(`.cache/static-entry`), + main: cachePath(`static-entry`), } case `build-javascript`: return { - app: directoryPath(`.cache/production-app`), + app: cachePath(`production-app`), } default: throw new Error(`The state requested ${stage} doesn't exist.`) @@ -316,7 +318,7 @@ module.exports = async ( // 'resolvableExtensions' API hook). extensions: [...program.extensions], alias: { - gatsby$: directoryPath(path.join(`.cache`, `gatsby-browser-entry.js`)), + gatsby$: cachePath(`gatsby-browser-entry.js`), // Using directories for module resolution is mandatory because // relative path imports are used sometimes // See https://stackoverflow.com/a/49455609/6420957 for more details @@ -327,10 +329,8 @@ module.exports = async ( "react-hot-loader": path.dirname( require.resolve(`react-hot-loader/package.json`) ), - "react-lifecycles-compat": directoryPath( - `.cache/react-lifecycles-compat.js` - ), - "create-react-context": directoryPath(`.cache/create-react-context.js`), + "react-lifecycles-compat": cachePath(`react-lifecycles-compat.js`), + "create-react-context": cachePath(`create-react-context.js`), }, } } From f14527999fc6cfa9cc2e649902d4fddba5c61d89 Mon Sep 17 00:00:00 2001 From: mathieudutour Date: Mon, 11 Mar 2019 17:09:26 -0400 Subject: [PATCH 02/21] make public page configurable --- .../src/index.js | 16 ++++++++--- packages/gatsby-cli/src/create-cli.js | 19 +++++++++++++ .../gatsby-plugin-feed/src/gatsby-node.js | 6 ++--- .../gatsby-plugin-guess-js/src/gatsby-ssr.js | 6 ++--- .../gatsby-plugin-manifest/src/gatsby-node.js | 12 ++++----- .../src/gatsby-node.js | 18 +++++-------- .../gatsby-plugin-netlify/src/gatsby-node.js | 7 +++-- .../gatsby-plugin-netlify/src/plugin-data.js | 16 +++++------ .../gatsby-plugin-offline/src/gatsby-node.js | 27 +++++++++---------- packages/gatsby-plugin-sharp/src/index.js | 14 ++++++++-- .../gatsby-plugin-sitemap/src/gatsby-node.js | 7 ++--- .../gatsby-plugin-subfont/src/gatsby-node.js | 10 ++++--- .../src/index.js | 13 ++++----- .../src/extend-file-node.js | 14 +++++----- .../src/extend-node-type.js | 7 +---- packages/gatsby/cache-dir/static-entry.js | 14 ++++------ packages/gatsby/src/bootstrap/index.js | 25 ++++++++++------- packages/gatsby/src/commands/build-html.js | 3 ++- packages/gatsby/src/commands/clean.js | 4 +-- packages/gatsby/src/commands/develop-html.js | 3 ++- packages/gatsby/src/commands/develop.js | 7 +++-- packages/gatsby/src/commands/serve.js | 6 ++--- .../query-runner/query-runner.js | 10 ++----- .../gatsby/src/utils/babel-loader-helpers.js | 19 ++++++++----- packages/gatsby/src/utils/cache.js | 27 +++++++++++++++++++ .../utils/gatsby-webpack-stats-extractor.js | 5 ++-- packages/gatsby/src/utils/get-static-dir.js | 7 ++--- packages/gatsby/src/utils/webpack.config.js | 9 +++---- .../gatsby/src/utils/websocket-manager.js | 9 ++----- packages/gatsby/src/utils/worker.js | 3 ++- 30 files changed, 199 insertions(+), 144 deletions(-) diff --git a/packages/babel-plugin-remove-graphql-queries/src/index.js b/packages/babel-plugin-remove-graphql-queries/src/index.js index 40055485d1cd9..9515173e1fb54 100644 --- a/packages/babel-plugin-remove-graphql-queries/src/index.js +++ b/packages/babel-plugin-remove-graphql-queries/src/index.js @@ -141,8 +141,12 @@ export default function({ types: t }) { ) { const identifier = t.identifier(`staticQueryData`) const filename = state.file.opts.filename - const shortResultPath = `public/static/d/${this.queryHash}.json` - const resultPath = nodePath.join(process.cwd(), shortResultPath) + const shortResultPath = `static/d/${this.queryHash}.json` + const resultPath = nodePath.join( + (state.opts || {}).publicPath || + nodePath.join(process.cwd(), `public`), + shortResultPath + ) // Add query path2.parent.attributes.push( t.jSXAttribute( @@ -179,8 +183,12 @@ export default function({ types: t }) { ) { const identifier = t.identifier(`staticQueryData`) const filename = state.file.opts.filename - const shortResultPath = `public/static/d/${this.queryHash}.json` - const resultPath = nodePath.join(process.cwd(), shortResultPath) + const shortResultPath = `static/d/${this.queryHash}.json` + const resultPath = nodePath.join( + (state.opts || {}).publicPath || + nodePath.join(process.cwd(), `public`), + shortResultPath + ) // Remove query variable since it is useless now if (this.templatePath.parentPath.isVariableDeclarator()) { diff --git a/packages/gatsby-cli/src/create-cli.js b/packages/gatsby-cli/src/create-cli.js index 3cf4dc31c672b..cdc5d84135a2e 100644 --- a/packages/gatsby-cli/src/create-cli.js +++ b/packages/gatsby-cli/src/create-cli.js @@ -16,6 +16,7 @@ const handlerP = fn => (...args) => { function buildLocalCommands(cli, isLocalSite) { const defaultHost = `localhost` const defaultCache = `.cache` + const defaultBuildDir = `public` const directory = path.resolve(`.`) // 'not dead' query not available in browserslist used in Gatsby v1 @@ -148,11 +149,17 @@ function buildLocalCommands(cli, isLocalSite) { type: `string`, default: defaultCache, describe: `Set cache location. Defaults to ${defaultCache}`, + }) + .option(`build-dir`, { + type: `string`, + default: defaultBuildDir, + describe: `Set build directory location. Defaults to ${defaultBuildDir}`, }), handler: handlerP( getCommandHandler(`develop`, (args, cmd) => { process.env.NODE_ENV = process.env.NODE_ENV || `development` process.env.GATSBY_CACHE = args.cacheDir + process.env.GATSBY_BUILD_DIR = args.buildDir cmd(args) // Return an empty promise to prevent handlerP from exiting early. // The development server shouldn't ever exit until the user directly @@ -184,11 +191,17 @@ function buildLocalCommands(cli, isLocalSite) { type: `string`, default: defaultCache, describe: `Set cache location. Defaults to ${defaultCache}`, + }) + .option(`build-dir`, { + type: `string`, + default: defaultBuildDir, + describe: `Set build directory location. Defaults to ${defaultBuildDir}`, }), handler: handlerP( getCommandHandler(`build`, (args, cmd) => { process.env.NODE_ENV = `production` process.env.GATSBY_CACHE = args.cacheDir + process.env.GATSBY_BUILD_DIR = args.buildDir return cmd(args) }) ), @@ -224,10 +237,16 @@ function buildLocalCommands(cli, isLocalSite) { type: `string`, default: defaultCache, describe: `Set cache location. Defaults to ${defaultCache}`, + }) + .option(`build-dir`, { + type: `string`, + default: defaultBuildDir, + describe: `Set build directory location. Defaults to ${defaultBuildDir}`, }), handler: getCommandHandler(`serve`, (args, cmd) => { process.env.GATSBY_CACHE = args.cacheDir + process.env.GATSBY_BUILD_DIR = args.buildDir return cmd(args) }), }) diff --git a/packages/gatsby-plugin-feed/src/gatsby-node.js b/packages/gatsby-plugin-feed/src/gatsby-node.js index 17fd5bd58bc5b..7996a81dc3edc 100644 --- a/packages/gatsby-plugin-feed/src/gatsby-node.js +++ b/packages/gatsby-plugin-feed/src/gatsby-node.js @@ -5,8 +5,6 @@ import merge from "lodash.merge" import mkdirp from "mkdirp" import { defaultOptions, runQuery, writeFile } from "./internals" -const publicPath = `./public` - // A default function to transform query data into feed entries. const serialize = ({ query: { site, allMarkdownRemark } }) => allMarkdownRemark.edges.map(edge => { @@ -19,7 +17,7 @@ const serialize = ({ query: { site, allMarkdownRemark } }) => } }) -exports.onPostBuild = async ({ graphql }, pluginOptions) => { +exports.onPostBuild = async ({ graphql, cache }, pluginOptions) => { delete pluginOptions.plugins /* @@ -55,7 +53,7 @@ exports.onPostBuild = async ({ graphql }, pluginOptions) => { items.forEach(i => feed.item(i)) - const outputPath = path.join(publicPath, f.output) + const outputPath = cache.publicPath(f.output) const outputDir = path.dirname(outputPath) if (!fs.existsSync(outputDir)) { mkdirp.sync(outputDir) diff --git a/packages/gatsby-plugin-guess-js/src/gatsby-ssr.js b/packages/gatsby-plugin-guess-js/src/gatsby-ssr.js index 3f36be504a126..5d354479ea4c3 100644 --- a/packages/gatsby-plugin-guess-js/src/gatsby-ssr.js +++ b/packages/gatsby-plugin-guess-js/src/gatsby-ssr.js @@ -22,12 +22,12 @@ const readPageData = cache => { } let s -const readStats = () => { +const readStats = cache => { if (s) { return s } else { s = JSON.parse( - fs.readFileSync(`${process.cwd()}/public/webpack.stats.json`, `utf-8`) + fs.readFileSync(cache.publicPath(`webpack.stats.json`, `utf-8`)) ) return s } @@ -39,7 +39,7 @@ exports.onRenderBody = ( ) => { if (process.env.NODE_ENV === `production`) { const pagesData = readPageData(cache) - const stats = readStats() + const stats = readStats(cache) const matchedPaths = Object.keys( guess({ path: pathname, threshold: pluginOptions.minimumThreshold }) ) diff --git a/packages/gatsby-plugin-manifest/src/gatsby-node.js b/packages/gatsby-plugin-manifest/src/gatsby-node.js index 4823741070619..cdeef1aed8fa9 100644 --- a/packages/gatsby-plugin-manifest/src/gatsby-node.js +++ b/packages/gatsby-plugin-manifest/src/gatsby-node.js @@ -17,10 +17,10 @@ try { // doesn't support cpu-core-count utility. } -function generateIcons(icons, srcIcon) { +function generateIcons(cache, icons, srcIcon) { return Promise.map(icons, icon => { const size = parseInt(icon.sizes.substring(0, icon.sizes.lastIndexOf(`x`))) - const imgPath = path.join(`public`, icon.src) + const imgPath = cache.publicPath(icon.src) // For vector graphics, instruct sharp to use a pixel density // suitable for the resolution we're rasterizing to. @@ -34,7 +34,7 @@ function generateIcons(icons, srcIcon) { }) } -exports.onPostBootstrap = (args, pluginOptions) => +exports.onPostBootstrap = ({ cache }, pluginOptions) => new Promise((resolve, reject) => { const { icon, ...manifest } = pluginOptions @@ -51,7 +51,7 @@ exports.onPostBootstrap = (args, pluginOptions) => } // Determine destination path for icons. - const iconPath = path.join(`public`, path.dirname(manifest.icons[0].src)) + const iconPath = cache.publicPath(path.dirname(manifest.icons[0].src)) //create destination directory if it doesn't exist if (!fs.existsSync(iconPath)) { @@ -59,7 +59,7 @@ exports.onPostBootstrap = (args, pluginOptions) => } fs.writeFileSync( - path.join(`public`, `manifest.webmanifest`), + cache.publicPath(`manifest.webmanifest`), JSON.stringify(manifest) ) @@ -71,7 +71,7 @@ exports.onPostBootstrap = (args, pluginOptions) => `icon (${icon}) does not exist as defined in gatsby-config.js. Make sure the file exists relative to the root of the site.` ) } - generateIcons(manifest.icons, icon).then(() => { + generateIcons(cache, manifest.icons, icon).then(() => { //images have been generated console.log(`done generating icons for manifest`) resolve() diff --git a/packages/gatsby-plugin-netlify-cms/src/gatsby-node.js b/packages/gatsby-plugin-netlify-cms/src/gatsby-node.js index c2ba06b7758a5..592355555d6b5 100644 --- a/packages/gatsby-plugin-netlify-cms/src/gatsby-node.js +++ b/packages/gatsby-plugin-netlify-cms/src/gatsby-node.js @@ -32,22 +32,18 @@ function deepMap(obj, fn) { return obj } -exports.onCreateDevServer = ({ app, store }) => { - const { program } = store.getState() +exports.onCreateDevServer = ({ app, cache }) => { app.get(`/admin`, function(req, res) { - res.sendFile( - path.join(program.directory, `public/admin/index.html`), - err => { - if (err) { - res.status(500).end(err.message) - } + res.sendFile(cache.publicPath(`admin/index.html`), err => { + if (err) { + res.status(500).end(err.message) } - ) + }) }) } exports.onCreateWebpackConfig = ( - { store, stage, getConfig, plugins, pathPrefix }, + { store, stage, getConfig, plugins, pathPrefix, cache }, { modulePath, publicPath = `admin`, @@ -71,7 +67,7 @@ exports.onCreateWebpackConfig = ( ].filter(p => p), }, output: { - path: path.join(program.directory, `public`, publicPathClean), + path: cache.publicPath(publicPathClean), }, module: { /** diff --git a/packages/gatsby-plugin-netlify/src/gatsby-node.js b/packages/gatsby-plugin-netlify/src/gatsby-node.js index afe7787de7c35..fc28aa3ef8e20 100644 --- a/packages/gatsby-plugin-netlify/src/gatsby-node.js +++ b/packages/gatsby-plugin-netlify/src/gatsby-node.js @@ -25,8 +25,11 @@ exports.onCreateWebpackConfig = ({ actions, stage }) => { }) } -exports.onPostBuild = async ({ store, pathPrefix }, userPluginOptions) => { - const pluginData = makePluginData(store, assetsManifest, pathPrefix) +exports.onPostBuild = async ( + { store, cache, pathPrefix }, + userPluginOptions +) => { + const pluginData = makePluginData(store, cache, assetsManifest, pathPrefix) const pluginOptions = { ...DEFAULT_OPTIONS, ...userPluginOptions } const { redirects } = store.getState() diff --git a/packages/gatsby-plugin-netlify/src/plugin-data.js b/packages/gatsby-plugin-netlify/src/plugin-data.js index 079c86f89d971..1b42d4f142115 100644 --- a/packages/gatsby-plugin-netlify/src/plugin-data.js +++ b/packages/gatsby-plugin-netlify/src/plugin-data.js @@ -1,9 +1,4 @@ import _ from "lodash" -import path from "path" - -export function buildPrefixer(prefix, ...paths) { - return (...subpaths) => path.join(prefix, ...paths, ...subpaths) -} // Webpack stats map to an array if source maps are enabled. // We normalize to make direct map. @@ -16,9 +11,14 @@ function normalizeStats(stats) { // This function assembles data across the manifests and store to match a similar // shape of `static-entry.js`. With it, we can build headers that point to the correct // hashed filenames and ensure we pull in the componentChunkName. -export default function makePluginData(store, assetsManifest, pathPrefix) { - const { program, pages: storePages } = store.getState() - const publicFolder = buildPrefixer(program.directory, `public`) +export default function makePluginData( + store, + cache, + assetsManifest, + pathPrefix +) { + const { pages: storePages } = store.getState() + const publicFolder = cache.publicPath const stats = require(publicFolder(`webpack.stats.json`)) const chunkManifest = normalizeStats(stats) const pages = storePages diff --git a/packages/gatsby-plugin-offline/src/gatsby-node.js b/packages/gatsby-plugin-offline/src/gatsby-node.js index 4d014c439ed8a..22a6445e05a0f 100644 --- a/packages/gatsby-plugin-offline/src/gatsby-node.js +++ b/packages/gatsby-plugin-offline/src/gatsby-node.js @@ -17,30 +17,29 @@ exports.createPages = ({ actions }) => { } let s -const readStats = () => { +const readStats = cache => { if (s) { return s } else { s = JSON.parse( - fs.readFileSync(`${process.cwd()}/public/webpack.stats.json`, `utf-8`) + fs.readFileSync(cache.publicPath(`webpack.stats.json`), `utf-8`) ) return s } } -const getAssetsForChunks = chunks => { +const getAssetsForChunks = (cache, chunks) => { const files = _.flatten( - chunks.map(chunk => readStats().assetsByChunkName[chunk]) + chunks.map(chunk => readStats(cache).assetsByChunkName[chunk]) ) return _.compact(files) } exports.onPostBuild = (args, pluginOptions) => { - const { pathPrefix } = args - const rootDir = `public` + const { pathPrefix, cache } = args // Get exact asset filenames for app and offline app shell chunks - const files = getAssetsForChunks([ + const files = getAssetsForChunks(cache, [ `app`, `webpack-runtime`, `component---node-modules-gatsby-plugin-offline-app-shell-js`, @@ -53,9 +52,9 @@ exports.onPostBuild = (args, pluginOptions) => { const criticalFilePaths = _.uniq( _.concat( - getResourcesFromHTML(`${process.cwd()}/${rootDir}/404.html`), + getResourcesFromHTML(cache.publicPath(`404.html`)), getResourcesFromHTML( - `${process.cwd()}/${rootDir}/offline-plugin-app-shell-fallback/index.html` + cache.publicPath(`offline-plugin-app-shell-fallback/index.html`) ) ) ).map(omitPrefix) @@ -67,12 +66,12 @@ exports.onPostBuild = (args, pluginOptions) => { const manifests = [`manifest.json`, `manifest.webmanifest`] manifests.forEach(file => { - if (fs.existsSync(`${rootDir}/${file}`)) globPatterns.push(file) + if (fs.existsSync(cache.publicPath(`${file}`))) globPatterns.push(file) }) const options = { importWorkboxFrom: `local`, - globDirectory: rootDir, + globDirectory: cache.publicCache(), globPatterns, modifyUrlPrefix: { // If `pathPrefix` is configured by user, we should replace @@ -113,10 +112,10 @@ exports.onPostBuild = (args, pluginOptions) => { const idbKeyvalFile = `idb-keyval-iife.min.js` const idbKeyvalSource = require.resolve(`idb-keyval/dist/${idbKeyvalFile}`) - const idbKeyvalDest = `public/${idbKeyvalFile}` + const idbKeyvalDest = cache.publicPath(`${idbKeyvalFile}`) fs.createReadStream(idbKeyvalSource).pipe(fs.createWriteStream(idbKeyvalDest)) - const swDest = `public/sw.js` + const swDest = cache.publicPath(`sw.js`) return workboxBuild .generateSW({ swDest, ...combinedOptions }) .then(({ count, size, warnings }) => { @@ -126,7 +125,7 @@ exports.onPostBuild = (args, pluginOptions) => { .readFileSync(`${__dirname}/sw-append.js`, `utf8`) .replace(/%pathPrefix%/g, pathPrefix) - fs.appendFileSync(`public/sw.js`, `\n` + swAppend) + fs.appendFileSync(swDest, `\n` + swAppend) console.log( `Generated ${swDest}, which will precache ${count} files, totaling ${size} bytes.` ) diff --git a/packages/gatsby-plugin-sharp/src/index.js b/packages/gatsby-plugin-sharp/src/index.js index fc31465c4c8e6..3a4484c20b692 100644 --- a/packages/gatsby-plugin-sharp/src/index.js +++ b/packages/gatsby-plugin-sharp/src/index.js @@ -124,6 +124,17 @@ const healOptions = ( return options } +function getPublicPath(cwd) { + const { GATSBY_BUILD_DIR } = process.env + if (GATSBY_BUILD_DIR) { + if (path.isAbsolute(GATSBY_BUILD_DIR)) { + return GATSBY_BUILD_DIR + } + return path.join(cwd || process.cwd(), GATSBY_BUILD_DIR) + } + return path.join(cwd || process.cwd(), `./public`) +} + function queueImageResizing({ file, args = {}, reporter }) { const options = healOptions(pluginOptions, args, file.extension) // Filter out false args, and args not for this extension and put width at @@ -154,8 +165,7 @@ function queueImageResizing({ file, args = {}, reporter }) { const imgSrc = `/${file.name}.${fileExtension}` const dirPath = path.join( - process.cwd(), - `public`, + getPublicPath(), `static`, file.internal.contentDigest, argsDigestShort diff --git a/packages/gatsby-plugin-sitemap/src/gatsby-node.js b/packages/gatsby-plugin-sitemap/src/gatsby-node.js index d4957c386579b..b680767e04620 100644 --- a/packages/gatsby-plugin-sitemap/src/gatsby-node.js +++ b/packages/gatsby-plugin-sitemap/src/gatsby-node.js @@ -1,10 +1,7 @@ -import path from "path" import sitemap from "sitemap" import { defaultOptions, runQuery, writeFile } from "./internals" -const publicPath = `./public` - -exports.onPostBuild = async ({ graphql, pathPrefix }, pluginOptions) => { +exports.onPostBuild = async ({ graphql, pathPrefix, cache }, pluginOptions) => { const options = { ...pluginOptions } delete options.plugins delete options.createLinkInHead @@ -15,7 +12,7 @@ exports.onPostBuild = async ({ graphql, pathPrefix }, pluginOptions) => { } const map = sitemap.createSitemap(rest) - const saved = path.join(publicPath, output) + const saved = cache.publicPath(output) // Paths we're excluding... const excludeOptions = exclude.concat(defaultOptions.exclude) diff --git a/packages/gatsby-plugin-subfont/src/gatsby-node.js b/packages/gatsby-plugin-subfont/src/gatsby-node.js index 20b012e0fb8d1..7c8b5466d8aab 100644 --- a/packages/gatsby-plugin-subfont/src/gatsby-node.js +++ b/packages/gatsby-plugin-subfont/src/gatsby-node.js @@ -1,16 +1,18 @@ const path = require(`path`) const { execSync } = require(`child_process`) -exports.onPostBuild = ({ store }) => { - const root = path.join(store.getState().program.directory, `public`) +exports.onPostBuild = ({ store, cache }) => { // TODO make this configurable const urlPaths = [`/`] const filePaths = urlPaths.reduce( (accumulator, currentPath) => - `${accumulator} ${path.join(root, currentPath, `index.html`)}`, + `${accumulator} ${path.join( + cache.publicPath(currentPath), + `index.html` + )}`, `` ) - const command = `node_modules/.bin/subfont -i --no-recursive --inline-css --root file://${root}${filePaths}` + const command = `node_modules/.bin/subfont -i --no-recursive --inline-css --root file://${cache.publicPath()}${filePaths}` execSync(command) } diff --git a/packages/gatsby-remark-copy-linked-files/src/index.js b/packages/gatsby-remark-copy-linked-files/src/index.js index 7e1c8011fed71..180603577ac6b 100644 --- a/packages/gatsby-remark-copy-linked-files/src/index.js +++ b/packages/gatsby-remark-copy-linked-files/src/index.js @@ -7,8 +7,6 @@ const _ = require(`lodash`) const cheerio = require(`cheerio`) const imageSize = require(`probe-image-size`) -const DEPLOY_DIR = `public` - const invalidDestinationDirMessage = dir => `[gatsby-remark-copy-linked-files You have supplied an invalid destination directory. The destination directory must be a child but was: ${dir}` @@ -21,16 +19,15 @@ const validateDestinationDir = dir => const newFileName = linkNode => `${linkNode.name}-${linkNode.internal.contentDigest}.${linkNode.extension}` -const newPath = (linkNode, destinationDir) => { +const newPath = (cache, linkNode, destinationDir) => { if (destinationDir) { return path.posix.join( - process.cwd(), - DEPLOY_DIR, + cache.publicPath(), destinationDir, newFileName(linkNode) ) } - return path.posix.join(process.cwd(), DEPLOY_DIR, newFileName(linkNode)) + return path.posix.join(cache.publicPath(), newFileName(linkNode)) } const newLinkURL = (linkNode, destinationDir, pathPrefix) => { @@ -58,7 +55,7 @@ function toArray(buf) { } module.exports = ( - { files, markdownNode, markdownAST, pathPrefix, getNode }, + { files, markdownNode, markdownAST, pathPrefix, getNode, cache }, pluginOptions = {} ) => { const defaults = { @@ -89,7 +86,7 @@ module.exports = ( return null }) if (linkNode && linkNode.absolutePath) { - const newFilePath = newPath(linkNode, options.destinationDir) + const newFilePath = newPath(cache, linkNode, options.destinationDir) // Prevent uneeded copying if (linkPath === newFilePath) return diff --git a/packages/gatsby-source-filesystem/src/extend-file-node.js b/packages/gatsby-source-filesystem/src/extend-file-node.js index 52991f4d1616f..665d3da2f4c7e 100644 --- a/packages/gatsby-source-filesystem/src/extend-file-node.js +++ b/packages/gatsby-source-filesystem/src/extend-file-node.js @@ -2,7 +2,12 @@ const { GraphQLString } = require(`gatsby/graphql`) const fs = require(`fs-extra`) const path = require(`path`) -module.exports = ({ type, getNodeAndSavePathDependency, pathPrefix = `` }) => { +module.exports = ({ + type, + getNodeAndSavePathDependency, + pathPrefix = ``, + cache, +}) => { if (type.name !== `File`) { return {} } @@ -18,12 +23,7 @@ module.exports = ({ type, getNodeAndSavePathDependency, pathPrefix = `` }) => { details.ext }` - const publicPath = path.join( - process.cwd(), - `public`, - `static`, - fileName - ) + const publicPath = path.join(cache.publicPath(), `static`, fileName) if (!fs.existsSync(publicPath)) { fs.copy(details.absolutePath, publicPath, err => { diff --git a/packages/gatsby-transformer-sharp/src/extend-node-type.js b/packages/gatsby-transformer-sharp/src/extend-node-type.js index 935bb52e31b46..bd47cfcbf90de 100644 --- a/packages/gatsby-transformer-sharp/src/extend-node-type.js +++ b/packages/gatsby-transformer-sharp/src/extend-node-type.js @@ -360,12 +360,7 @@ module.exports = ({ const imageName = `${details.name}-${image.internal.contentDigest}${ details.ext }` - const publicPath = path.join( - process.cwd(), - `public`, - `static`, - imageName - ) + const publicPath = path.join(cache.publicPath(), `static`, imageName) if (!fsExtra.existsSync(publicPath)) { fsExtra.copy(details.absolutePath, publicPath, err => { diff --git a/packages/gatsby/cache-dir/static-entry.js b/packages/gatsby/cache-dir/static-entry.js index 3e0cb708ba184..fbdcbc1e44ddd 100644 --- a/packages/gatsby/cache-dir/static-entry.js +++ b/packages/gatsby/cache-dir/static-entry.js @@ -9,17 +9,18 @@ const apiRunner = require(`./api-runner-ssr`) const syncRequires = require(`./sync-requires`) const { dataPaths, pages } = require(`./data.json`) const { version: gatsbyVersion } = require(`gatsby/package.json`) +const { publicPath } = require(`gatsby/dist/utils/cache`) // Speed up looking up pages. const pagesObjectMap = new Map() pages.forEach(p => pagesObjectMap.set(p.path, p)) const stats = JSON.parse( - fs.readFileSync(`${process.cwd()}/public/webpack.stats.json`, `utf-8`) + fs.readFileSync(publicPath(`webpack.stats.json`), `utf-8`) ) const chunkMapping = JSON.parse( - fs.readFileSync(`${process.cwd()}/public/chunk-map.json`, `utf-8`) + fs.readFileSync(publicPath(`chunk-map.json`), `utf-8`) ) // const testRequireError = require("./test-require-error") @@ -117,9 +118,7 @@ export default (pagePath, callback) => { const pathToJsonData = `../public/` + dataPaths[page.jsonName] try { dataAndContext = JSON.parse( - fs.readFileSync( - `${process.cwd()}/public/static/d/${dataPaths[page.jsonName]}.json` - ) + fs.readFileSync(publicPath(`static/d/${dataPaths[page.jsonName]}.json`)) ) } catch (e) { console.log(`error`, pathToJsonData, e) @@ -311,10 +310,7 @@ export default (pagePath, callback) => {