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-manifest): remove fs from ssr #24097

Merged
merged 2 commits into from
May 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
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
43 changes: 23 additions & 20 deletions packages/gatsby-plugin-manifest/src/__tests__/gatsby-ssr.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@ jest.mock(`fs`, () => {
}
})

const { onRenderBody } = require(`../gatsby-ssr`)
const { onPreInit } = require(`../gatsby-node`)
const { onRenderBody: ssrOnRenderBody } = require(`../gatsby-ssr`)

const onRenderBody = (args, pluginOptions) => {
onPreInit({}, pluginOptions)
return ssrOnRenderBody(args, pluginOptions)
}

let headComponents
const setHeadComponents = args => (headComponents = headComponents.concat(args))

const defaultIcon = `pretend/this/exists.png`
const ssrArgs = {
setHeadComponents,
pathname: `/`,
Expand All @@ -25,7 +32,7 @@ describe(`gatsby-plugin-manifest`, () => {
global.__PATH_PREFIX__ = `/path-prefix`

onRenderBody(ssrArgs, {
icon: true,
icon: defaultIcon,
theme_color: `#000000`,
})

Expand Down Expand Up @@ -73,7 +80,7 @@ describe(`gatsby-plugin-manifest`, () => {

it(`Does not add a "theme_color" meta tag to head if "theme_color" option is not provided.`, () => {
onRenderBody(ssrArgs, {
icon: true,
icon: defaultIcon,
include_favicon: false,
cache_busting_mode: false,
legacy: false,
Expand All @@ -83,7 +90,7 @@ describe(`gatsby-plugin-manifest`, () => {

it(`Adds "icon" and "manifest" links and "theme_color" meta tag to head`, () => {
onRenderBody(ssrArgs, {
icon: true,
icon: defaultIcon,
theme_color: `#000000`,
})
expect(headComponents).toMatchSnapshot()
Expand Down Expand Up @@ -127,7 +134,7 @@ describe(`gatsby-plugin-manifest`, () => {
describe(`Does create legacy links`, () => {
it(`if "legacy" not specified in automatic mode`, () => {
onRenderBody(ssrArgs, {
icon: true,
icon: defaultIcon,
theme_color: `#000000`,
include_favicon: false,
cache_busting_mode: `none`,
Expand All @@ -138,7 +145,7 @@ describe(`gatsby-plugin-manifest`, () => {

it(`if "legacy" not specified in hybrid mode.`, () => {
onRenderBody(ssrArgs, {
icon: true,
icon: defaultIcon,
theme_color: `#000000`,
icons: [
{
Expand All @@ -161,7 +168,6 @@ describe(`gatsby-plugin-manifest`, () => {

it(`if "legacy" not specified in manual mode.`, () => {
onRenderBody(ssrArgs, {
icon: false,
icons: [
{
src: `/favicons/android-chrome-48x48.png`,
Expand All @@ -182,7 +188,7 @@ describe(`gatsby-plugin-manifest`, () => {
describe(`Does not create legacy links`, () => {
it(`If "legacy" options is false and in automatic`, () => {
onRenderBody(ssrArgs, {
icon: true,
icon: defaultIcon,
legacy: false,
include_favicon: false,
cache_busting_mode: false,
Expand All @@ -192,7 +198,6 @@ describe(`gatsby-plugin-manifest`, () => {

it(`If "legacy" options is false and in manual mode`, () => {
onRenderBody(ssrArgs, {
icon: false,
theme_color: `#000000`,
legacy: false,
icons: [
Expand All @@ -213,7 +218,7 @@ describe(`gatsby-plugin-manifest`, () => {

it(`If "legacy" options is false and in hybrid mode`, () => {
onRenderBody(ssrArgs, {
icon: true,
icon: defaultIcon,
legacy: false,
icons: [
{
Expand All @@ -238,7 +243,6 @@ describe(`gatsby-plugin-manifest`, () => {
describe(`Cache Busting`, () => {
it(`doesn't add cache busting in manual mode`, () => {
onRenderBody(ssrArgs, {
icon: false,
icons: [
{
src: `/favicons/android-chrome-48x48.png`,
Expand All @@ -257,17 +261,17 @@ describe(`gatsby-plugin-manifest`, () => {
})

it(`doesn't add cache busting if "cache_busting_mode" option is set to none`, () => {
onRenderBody(ssrArgs, { icon: true, cache_busting_mode: `none` })
onRenderBody(ssrArgs, { icon: defaultIcon, cache_busting_mode: `none` })
expect(headComponents).toMatchSnapshot()
})

it(`Does file name cache busting if "cache_busting_mode" option is set to name`, () => {
onRenderBody(ssrArgs, { icon: true, cache_busting_mode: `name` })
onRenderBody(ssrArgs, { icon: defaultIcon, cache_busting_mode: `name` })
expect(headComponents).toMatchSnapshot()
})

it(`Does query cache busting if "cache_busting_mode" option is set to query`, () => {
onRenderBody(ssrArgs, { icon: true, cache_busting_mode: `query` })
onRenderBody(ssrArgs, { icon: defaultIcon, cache_busting_mode: `query` })
expect(headComponents).toMatchSnapshot()
})

Expand All @@ -280,8 +284,8 @@ describe(`gatsby-plugin-manifest`, () => {
describe(`Favicon`, () => {
it(`Adds link favicon tag if "include_favicon" is set to true`, () => {
onRenderBody(ssrArgs, {
icon: true,
include_favicon: true,
icon: defaultIcon,
include_favicon: defaultIcon,
legacy: false,
cache_busting_mode: `none`,
})
Expand All @@ -290,7 +294,7 @@ describe(`gatsby-plugin-manifest`, () => {

it(`Does not add a link favicon if "include_favicon" option is set to false`, () => {
onRenderBody(ssrArgs, {
icon: true,
icon: defaultIcon,
include_favicon: false,
legacy: false,
cache_busting_mode: `none`,
Expand All @@ -300,7 +304,6 @@ describe(`gatsby-plugin-manifest`, () => {

it(`Does not add a link favicon if in manual mode`, () => {
onRenderBody(ssrArgs, {
icon: false,
icons: [
{
src: `/favicons/android-chrome-48x48.png`,
Expand Down Expand Up @@ -333,7 +336,7 @@ describe(`gatsby-plugin-manifest`, () => {

it(`Add crossOrigin when 'crossOrigin' is anonymous`, () => {
onRenderBody(ssrArgs, {
icon: true,
icon: defaultIcon,
crossOrigin: `anonymous`,
legacy: false,
include_favicon: false,
Expand All @@ -344,7 +347,7 @@ describe(`gatsby-plugin-manifest`, () => {

it(`Does not add crossOrigin when 'crossOrigin' is blank`, () => {
onRenderBody(ssrArgs, {
icon: true,
icon: defaultIcon,
legacy: false,
include_favicon: false,
cache_busting_mode: `none`,
Expand Down
30 changes: 22 additions & 8 deletions packages/gatsby-plugin-manifest/src/gatsby-node.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import fs from "fs"
import path from "path"
import * as fs from "fs"
import * as path from "path"
import sharp from "./safe-sharp"
import { createContentDigest, cpuCoreCount, slash } from "gatsby-core-utils"
import {
Expand Down Expand Up @@ -45,20 +45,33 @@ async function generateIcon(icon, srcIcon) {
async function checkCache(cache, icon, srcIcon, srcIconDigest, callback) {
const cacheKey = createContentDigest(`${icon.src}${srcIcon}${srcIconDigest}`)

let created = cache.get(cacheKey, srcIcon)

const created = cache.get(cacheKey, srcIcon)
if (!created) {
cache.set(cacheKey, true)

try {
// console.log(`creating icon`, icon.src, srcIcon)
await callback(icon, srcIcon)
} catch (e) {
cache.set(cacheKey, false)
throw e
}
} else {
// console.log(`icon exists`, icon.src, srcIcon)
}
}

/**
* Setup pluginOption defaults
*/
exports.onPreInit = (_, pluginOptions) => {
pluginOptions.cache_busting_mode = pluginOptions.cache_busting_mode ?? `query`
pluginOptions.include_favicon = pluginOptions.include_favicon ?? true
pluginOptions.legacy = pluginOptions.legacy ?? true
pluginOptions.theme_color_in_head = pluginOptions.theme_color_in_head ?? true
pluginOptions.cacheDigest = null

if (pluginOptions.cache_busting_mode !== `none` && pluginOptions.icon) {
pluginOptions.cacheDigest = createContentDigest(
fs.readFileSync(pluginOptions.icon)
)
}
}

Expand All @@ -69,6 +82,7 @@ exports.onPostBootstrap = async (
const activity = reporter.activityTimer(`Build manifest and related icons`, {
parentSpan,
})

activity.start()

let cache = new Map()
Expand Down Expand Up @@ -172,7 +186,7 @@ const makeManifest = async ({
})

// Only auto-generate icons if a src icon is defined.
if (icon !== undefined) {
if (typeof icon !== `undefined`) {
// Check if the icon exists
if (!doesIconExist(icon)) {
throw new Error(
Expand Down
103 changes: 43 additions & 60 deletions packages/gatsby-plugin-manifest/src/gatsby-ssr.js
Original file line number Diff line number Diff line change
@@ -1,108 +1,91 @@
import React from "react"
import * as React from "react"
import { withPrefix as fallbackWithPrefix, withAssetPrefix } from "gatsby"
import fs from "fs"
import { createContentDigest } from "gatsby-core-utils"
import { defaultIcons, addDigestToPath, favicons } from "./common.js"
import getManifestForPathname from "./get-manifest-pathname"

// TODO: remove for v3
const withPrefix = withAssetPrefix || fallbackWithPrefix

let iconDigest = null

exports.onRenderBody = (
{ setHeadComponents, pathname = `/` },
{ localize, ...pluginOptions }
{
localize,
legacy,
cache_busting_mode: cacheBusting,
cacheDigest,
icon,
icons: pluginIcons,
include_favicon: insertFaviconLinkTag,
theme_color_in_head: insertMetaTag,
theme_color,
crossOrigin,
}
) => {
// We use this to build a final array to pass as the argument to setHeadComponents at the end of onRenderBody.
let headComponents = []

const srcIconExists = !!pluginOptions.icon
const headComponents = []

const icons = pluginOptions.icons || defaultIcons
const legacy =
typeof pluginOptions.legacy !== `undefined` ? pluginOptions.legacy : true

const cacheBusting =
typeof pluginOptions.cache_busting_mode !== `undefined`
? pluginOptions.cache_busting_mode
: `query`
const srcIconExists = !!icon
const icons = pluginIcons || defaultIcons
const manifestFileName = getManifestForPathname(pathname, localize)

// If icons were generated, also add a favicon link.
if (srcIconExists) {
if (cacheBusting !== `none`) {
iconDigest = createContentDigest(fs.readFileSync(pluginOptions.icon))
}

const insertFaviconLinkTag =
typeof pluginOptions.include_favicon !== `undefined`
? pluginOptions.include_favicon
: true

if (insertFaviconLinkTag) {
favicons.forEach(favicon => {
headComponents.push(
<link
key={`gatsby-plugin-manifest-icon-link`}
rel="icon"
href={withPrefix(
addDigestToPath(favicon.src, iconDigest, cacheBusting)
addDigestToPath(favicon.src, cacheDigest, cacheBusting)
)}
/>
)
})
}
}

const manifestFileName = getManifestForPathname(pathname, localize)

// Add manifest link tag.
headComponents.push(
<link
key={`gatsby-plugin-manifest-link`}
rel="manifest"
href={withPrefix(`/${manifestFileName}`)}
crossOrigin={pluginOptions.crossOrigin}
crossOrigin={crossOrigin}
/>
)

// The user has an option to opt out of the theme_color meta tag being inserted into the head.
if (pluginOptions.theme_color) {
const insertMetaTag =
typeof pluginOptions.theme_color_in_head !== `undefined`
? pluginOptions.theme_color_in_head
: true
if (theme_color && insertMetaTag) {
headComponents.push(
<meta
key={`gatsby-plugin-manifest-meta`}
name="theme-color"
content={theme_color}
/>
)
}

if (insertMetaTag) {
if (legacy) {
icons.forEach(icon => {
headComponents.push(
<meta
key={`gatsby-plugin-manifest-meta`}
name="theme-color"
content={pluginOptions.theme_color}
<link
key={`gatsby-plugin-manifest-apple-touch-icon-${icon.sizes}`}
rel="apple-touch-icon"
sizes={icon.sizes}
href={withPrefix(
addDigestToPath(
icon.src,
cacheDigest,
srcIconExists ? cacheBusting : `none`
)
)}
/>
)
}
}

if (legacy) {
const iconLinkTags = icons.map(icon => (
<link
key={`gatsby-plugin-manifest-apple-touch-icon-${icon.sizes}`}
rel="apple-touch-icon"
sizes={icon.sizes}
href={withPrefix(
addDigestToPath(
icon.src,
iconDigest,
srcIconExists ? cacheBusting : `none`
)
)}
/>
))

headComponents = [...headComponents, ...iconLinkTags]
})
}

setHeadComponents(headComponents)

return true
}