Skip to content
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

fix(gatsby-plugin-gatsby-cloud): Remove sibling detection code and rely on match paths #29610

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 0 additions & 22 deletions packages/gatsby-plugin-gatsby-cloud/src/__tests__/is-sibling.js

This file was deleted.

77 changes: 2 additions & 75 deletions packages/gatsby-plugin-gatsby-cloud/src/create-redirects.js
Original file line number Diff line number Diff line change
@@ -1,90 +1,17 @@
import { writeFile } from "fs-extra"
import { REDIRECTS_FILENAME } from "./constants"

/**
* Get all rewrites and sort them by most specific at the top
* code is based on @reach/router match utility (https://github.com/reach/router/blob/152aff2352bc62cefc932e1b536de9efde6b64a5/src/lib/utils.js#L224-L254)
*/

const paramRe = /^:(.+)/

const SEGMENT_POINTS = 4
const STATIC_POINTS = 3
const DYNAMIC_POINTS = 2
const SPLAT_PENALTY = 1
const ROOT_POINTS = 1

const isRootSegment = segment => segment === ``
const isDynamic = segment => paramRe.test(segment)
const isSplat = segment => segment === `*`

const rankRoute = (route, index) => {
const score = route.default
? 0
: segmentize(route).reduce((score, segment) => {
score += SEGMENT_POINTS
if (isRootSegment(segment)) score += ROOT_POINTS
else if (isDynamic(segment)) score += DYNAMIC_POINTS
else if (isSplat(segment)) score -= SEGMENT_POINTS + SPLAT_PENALTY
else score += STATIC_POINTS
return score
}, 0)
return { route, score, index }
}

const rankRoutes = routes =>
routes
.map(rankRoute)
.sort((a, b) =>
a.score < b.score ? 1 : a.score > b.score ? -1 : a.index - b.index
)

const segmentize = uri =>
uri
// strip starting/ending slashes
.replace(/(^\/+|\/+$)/g, ``)
.split(`/`)

/**
* rankRewrites
*
* We need to order rewrites in order of specificity because more specific rewrites have to be first in order.
* i.e. /url_that_is/ugly is more specific than /path4/:param1 even though both have 2 url segments
*/
const rankRewrites = rewrites => {
let sortedRewrites = []

const fromPaths = rewrites.map(({ fromPath }) => fromPath)
const rankedRoutes = rankRoutes(fromPaths)

for (let { route } of rankedRoutes) {
const rewrite = rewrites.find(rewrite => rewrite.fromPath === route)
if (rewrite) {
sortedRewrites.push(rewrite)
}
}

return sortedRewrites
}

export default async function writeRedirectsFile(
pluginData,
redirects,
rewrites,
siblingStaticPaths
rewrites
) {
const { publicFolder } = pluginData

if (!redirects.length && !rewrites.length) return null

// order rewrites based on priority
const rankedRewrites = rankRewrites(rewrites)

// Is it ok to pass through the data or should we format it so that we don't have dependencies
// between the redirects and rewrites formats? What are the chances those will change?
const FILE_PATH = publicFolder(REDIRECTS_FILENAME)
return writeFile(
FILE_PATH,
JSON.stringify({ redirects, rewrites: rankedRewrites, siblingStaticPaths })
)
return writeFile(FILE_PATH, JSON.stringify({ redirects, rewrites }))
}
67 changes: 35 additions & 32 deletions packages/gatsby-plugin-gatsby-cloud/src/gatsby-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import WebpackAssetsManifest from "webpack-assets-manifest"
import makePluginData from "./plugin-data"
import buildHeadersProgram from "./build-headers-program"
import createRedirects from "./create-redirects"
import { isSibling } from "./is-sibling"
import { readJSON } from "fs-extra"
import { joinPath } from "gatsby-core-utils"
import { DEFAULT_OPTIONS, BUILD_HTML_STAGE, BUILD_CSS_STAGE } from "./constants"

let assetsManifest = {}
Expand Down Expand Up @@ -34,56 +35,58 @@ exports.onPostBuild = async (
const { redirects } = store.getState()

let rewrites = []
let siblingStaticPaths = []
if (pluginOptions.generateMatchPathRewrites) {
const { pages } = store.getState()
rewrites = Array.from(pages.values())
.filter(page => page.matchPath && page.matchPath !== page.path)
.map(page => {
const siblings = Array.from(pages.values())
.filter(maybeSiblingPage => {
if (maybeSiblingPage.matchPath) return false
const matchPathsFile = joinPath(
pluginData.program.directory,
`.cache`,
`match-paths.json`
)

return isSibling(page.matchPath, maybeSiblingPage.path)
})
.map(p => p.path)
const matchPaths = await readJSON(matchPathsFile)

siblingStaticPaths.push(...siblings)

return {
fromPath: page.matchPath,
toPath: page.path,
}
})
rewrites = matchPaths.map(({ matchPath, path }) => {
return {
fromPath: matchPath,
toPath: path,
}
})
}

await Promise.all([
buildHeadersProgram(pluginData, pluginOptions, reporter),
createRedirects(pluginData, redirects, rewrites, siblingStaticPaths),
createRedirects(pluginData, redirects, rewrites),
])
}

exports.pluginOptionsSchema = ({ Joi }) =>
Joi.object({
headers: Joi.object()
.pattern(/^/, Joi.array().items(Joi.string()))
.description(`Option to add headers for a filename`),
const MATCH_ALL_KEYS = /^/
const pluginOptionsSchema = function ({ Joi }) {
const headersSchema = Joi.object()
.pattern(MATCH_ALL_KEYS, Joi.array().items(Joi.string()))
.description(`Add more headers to specific pages`)

return Joi.object({
headers: headersSchema,
allPageHeaders: Joi.array()
.items(Joi.string())
.description(`Option to add headers for all files`),
.description(`Add more headers to all the pages`),
mergeSecurityHeaders: Joi.boolean().description(
`Option to include default Gatsby Cloud security headers (true by default)`
`When set to false, turns off the default security headers`
),
mergeLinkHeaders: Joi.boolean().description(
`Option to include default Gatsby Cloud link headers (true by default)`
`When set to false, turns off the default gatsby js headers`
),
mergeCachingHeaders: Joi.boolean().description(
`Option to include default Gatsby Cloud caching headers (true by default)`
`When set to false, turns off the default caching headers`
),
transformHeaders: Joi.function()
.arity(2)
.description(`Option to transform headers using a function`),
.maxArity(2)
.description(
`Transform function for manipulating headers under each path (e.g.sorting), etc. This should return an object of type: { key: Array<string> }`
),
generateMatchPathRewrites: Joi.boolean().description(
`Option to include redirect rules for client only paths (set to true by default)`
`When set to false, turns off automatic creation of redirect rules for client only paths`
),
})
}

exports.pluginOptionsSchema = pluginOptionsSchema
45 changes: 0 additions & 45 deletions packages/gatsby-plugin-gatsby-cloud/src/is-sibling.js

This file was deleted.

1 change: 1 addition & 0 deletions packages/gatsby-plugin-gatsby-cloud/src/plugin-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default function makePluginData(store, assetsManifest, pathPrefix) {
return {
pages,
manifest,
program,
pathPrefix,
publicFolder,
}
Expand Down