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

Add helmet to web for meta tags | Prerender support #2909

Merged
merged 12 commits into from
Jul 7, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
exports[`Should add config lines to App.{js,tsx} Matches Auth0 Snapshot 1`] = `
"import { AuthProvider } from '@redwoodjs/auth'
import { Auth0Client } from '@auth0/auth0-spa-js'
import { FatalErrorBoundary } from '@redwoodjs/web'
import { FatalErrorBoundary, RedwoodProvider } from '@redwoodjs/web'
import { RedwoodApolloProvider } from '@redwoodjs/web/apollo'

import FatalErrorPage from 'src/pages/FatalErrorPage'
Expand Down Expand Up @@ -32,11 +32,13 @@ const auth0 = new Auth0Client({

const App = () => (
<FatalErrorBoundary page={FatalErrorPage}>
<AuthProvider client={auth0} type=\\"auth0\\">
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
</AuthProvider>
<RedwoodProvider>
<AuthProvider client={auth0} type=\\"auth0\\">
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
</AuthProvider>
</RedwoodProvider>
</FatalErrorBoundary>
)

Expand All @@ -48,7 +50,7 @@ exports[`Should add config lines to App.{js,tsx} Matches Firebase Snapshot 1`] =
"import { AuthProvider } from '@redwoodjs/auth'
import firebase from 'firebase/app'
import 'firebase/auth'
import { FatalErrorBoundary } from '@redwoodjs/web'
import { FatalErrorBoundary, RedwoodProvider } from '@redwoodjs/web'
import { RedwoodApolloProvider } from '@redwoodjs/web/apollo'

import FatalErrorPage from 'src/pages/FatalErrorPage'
Expand All @@ -74,11 +76,13 @@ const firebaseClient = ((config) => {

const App = () => (
<FatalErrorBoundary page={FatalErrorPage}>
<AuthProvider client={firebaseClient} type=\\"firebase\\">
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
</AuthProvider>
<RedwoodProvider>
<AuthProvider client={firebaseClient} type=\\"firebase\\">
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
</AuthProvider>
</RedwoodProvider>
</FatalErrorBoundary>
)

Expand All @@ -89,7 +93,7 @@ export default App
exports[`Should add config lines to App.{js,tsx} Matches azureActiveDirectory Snapshot 1`] = `
"import { AuthProvider } from '@redwoodjs/auth'
import { UserAgentApplication } from 'msal'
import { FatalErrorBoundary } from '@redwoodjs/web'
import { FatalErrorBoundary, RedwoodProvider } from '@redwoodjs/web'
import { RedwoodApolloProvider } from '@redwoodjs/web/apollo'

import FatalErrorPage from 'src/pages/FatalErrorPage'
Expand All @@ -108,11 +112,13 @@ const azureActiveDirectoryClient = new UserAgentApplication({

const App = () => (
<FatalErrorBoundary page={FatalErrorPage}>
<AuthProvider client={azureActiveDirectoryClient} type=\\"azureActiveDirectory\\">
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
</AuthProvider>
<RedwoodProvider>
<AuthProvider client={azureActiveDirectoryClient} type=\\"azureActiveDirectory\\">
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
</AuthProvider>
</RedwoodProvider>
</FatalErrorBoundary>
)

Expand All @@ -125,7 +131,7 @@ exports[`Should add config lines to App.{js,tsx} Matches ethereum Snapshot 1`] =
import EthereumAuthClient from '@oneclickdapp/ethereum-auth'
import { ApolloClient, InMemoryCache } from '@apollo/client'
import { FetchConfigProvider, useFetchConfig } from '@redwoodjs/web'
import { FatalErrorBoundary } from '@redwoodjs/web'
import { FatalErrorBoundary, RedwoodProvider } from '@redwoodjs/web'
import { RedwoodApolloProvider } from '@redwoodjs/web/apollo'

import FatalErrorPage from 'src/pages/FatalErrorPage'
Expand Down Expand Up @@ -170,15 +176,17 @@ let ethereum

const App = () => (
<FatalErrorBoundary page={FatalErrorPage}>
<FetchConfigProvider>
<ApolloInjector>
<AuthProvider client={ethereum} type=\\"ethereum\\">
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
</AuthProvider>
</ApolloInjector>
</FetchConfigProvider>
<RedwoodProvider>
<FetchConfigProvider>
<ApolloInjector>
<AuthProvider client={ethereum} type=\\"ethereum\\">
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
</AuthProvider>
</ApolloInjector>
</FetchConfigProvider>
</RedwoodProvider>
</FatalErrorBoundary>
)

Expand All @@ -189,7 +197,7 @@ export default App
exports[`Should add config lines to App.{js,tsx} Matches goTrue Snapshot 1`] = `
"import { AuthProvider } from '@redwoodjs/auth'
import GoTrue from 'gotrue-js'
import { FatalErrorBoundary } from '@redwoodjs/web'
import { FatalErrorBoundary, RedwoodProvider } from '@redwoodjs/web'
import { RedwoodApolloProvider } from '@redwoodjs/web/apollo'

import FatalErrorPage from 'src/pages/FatalErrorPage'
Expand All @@ -204,11 +212,13 @@ const goTrueClient = new GoTrue({

const App = () => (
<FatalErrorBoundary page={FatalErrorPage}>
<AuthProvider client={goTrueClient} type=\\"goTrue\\">
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
</AuthProvider>
<RedwoodProvider>
<AuthProvider client={goTrueClient} type=\\"goTrue\\">
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
</AuthProvider>
</RedwoodProvider>
</FatalErrorBoundary>
)

Expand All @@ -219,7 +229,7 @@ export default App
exports[`Should add config lines to App.{js,tsx} Matches magicLink Snapshot 1`] = `
"import { AuthProvider } from '@redwoodjs/auth'
import { Magic } from 'magic-sdk'
import { FatalErrorBoundary } from '@redwoodjs/web'
import { FatalErrorBoundary, RedwoodProvider } from '@redwoodjs/web'
import { RedwoodApolloProvider } from '@redwoodjs/web/apollo'

import FatalErrorPage from 'src/pages/FatalErrorPage'
Expand All @@ -231,11 +241,13 @@ const m = new Magic(process.env.MAGICLINK_PUBLIC)

const App = () => (
<FatalErrorBoundary page={FatalErrorPage}>
<AuthProvider client={m} type=\\"magicLink\\">
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
</AuthProvider>
<RedwoodProvider>
<AuthProvider client={m} type=\\"magicLink\\">
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
</AuthProvider>
</RedwoodProvider>
</FatalErrorBoundary>
)

Expand All @@ -247,7 +259,7 @@ exports[`Should add config lines to App.{js,tsx} Matches netlify Snapshot 1`] =
"import { AuthProvider } from '@redwoodjs/auth'
import netlifyIdentity from 'netlify-identity-widget'
import { isBrowser } from '@redwoodjs/prerender/browserUtils'
import { FatalErrorBoundary } from '@redwoodjs/web'
import { FatalErrorBoundary, RedwoodProvider } from '@redwoodjs/web'
import { RedwoodApolloProvider } from '@redwoodjs/web/apollo'

import FatalErrorPage from 'src/pages/FatalErrorPage'
Expand All @@ -259,11 +271,13 @@ isBrowser && netlifyIdentity.init()

const App = () => (
<FatalErrorBoundary page={FatalErrorPage}>
<AuthProvider client={netlifyIdentity} type=\\"netlify\\">
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
</AuthProvider>
<RedwoodProvider>
<AuthProvider client={netlifyIdentity} type=\\"netlify\\">
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
</AuthProvider>
</RedwoodProvider>
</FatalErrorBoundary>
)

Expand All @@ -274,7 +288,7 @@ export default App
exports[`Should add config lines to App.{js,tsx} Matches nhost Snapshot 1`] = `
"import { AuthProvider } from '@redwoodjs/auth'
import { createClient } from 'nhost-js-sdk'
import { FatalErrorBoundary } from '@redwoodjs/web'
import { FatalErrorBoundary, RedwoodProvider } from '@redwoodjs/web'
import { RedwoodApolloProvider } from '@redwoodjs/web/apollo'

import FatalErrorPage from 'src/pages/FatalErrorPage'
Expand All @@ -290,11 +304,13 @@ const nhostClient = createClient({

const App = () => (
<FatalErrorBoundary page={FatalErrorPage}>
<AuthProvider client={nhostClient} type=\\"nhost\\">
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
</AuthProvider>
<RedwoodProvider>
<AuthProvider client={nhostClient} type=\\"nhost\\">
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
</AuthProvider>
</RedwoodProvider>
</FatalErrorBoundary>
)

Expand All @@ -305,7 +321,7 @@ export default App
exports[`Should add config lines to App.{js,tsx} Matches supabase Snapshot 1`] = `
"import { AuthProvider } from '@redwoodjs/auth'
import { createClient } from '@supabase/supabase-js'
import { FatalErrorBoundary } from '@redwoodjs/web'
import { FatalErrorBoundary, RedwoodProvider } from '@redwoodjs/web'
import { RedwoodApolloProvider } from '@redwoodjs/web/apollo'

import FatalErrorPage from 'src/pages/FatalErrorPage'
Expand All @@ -320,11 +336,13 @@ const supabaseClient = createClient(

const App = () => (
<FatalErrorBoundary page={FatalErrorPage}>
<AuthProvider client={supabaseClient} type=\\"supabase\\">
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
</AuthProvider>
<RedwoodProvider>
<AuthProvider client={supabaseClient} type=\\"supabase\\">
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
</AuthProvider>
</RedwoodProvider>
</FatalErrorBoundary>
)

Expand Down
10 changes: 6 additions & 4 deletions packages/create-redwood-app/template/web/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FatalErrorBoundary } from '@redwoodjs/web'
import { FatalErrorBoundary, RedwoodProvider } from '@redwoodjs/web'
import { RedwoodApolloProvider } from '@redwoodjs/web/apollo'

import FatalErrorPage from 'src/pages/FatalErrorPage'
Expand All @@ -8,9 +8,11 @@ import './index.css'

const App = () => (
<FatalErrorBoundary page={FatalErrorPage}>
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
<RedwoodProvider>
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
</RedwoodProvider>
</FatalErrorBoundary>
)

Expand Down
4 changes: 4 additions & 0 deletions packages/prerender/ambient.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import type { HelmetData } from 'react-helmet-async'

export {}

declare global {
namespace NodeJS {
interface Global {
__REDWOOD__PRERENDERING: boolean
__REDWOOD__HELMET_CONTEXT: { helmet?: HelmetData }
}
}
}
1 change: 1 addition & 0 deletions packages/prerender/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@redwoodjs/structure": "0.34.1",
"@redwoodjs/web": "0.34.1",
"babel-plugin-ignore-html-and-css-imports": "0.1.0",
"cheerio": "^1.0.0-rc.10",
"node-fetch": "2.6.1"
},
"scripts": {
Expand Down
2 changes: 2 additions & 0 deletions packages/prerender/src/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export const registerShims = () => {

global.__REDWOOD__PRERENDERING = true

global.__REDWOOD__HELMET_CONTEXT = {}

// Let routes auto loader plugin know
process.env.__REDWOOD__PRERENDERING = '1'

Expand Down
29 changes: 25 additions & 4 deletions packages/prerender/src/runPrerender.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import path from 'path'
import React from 'react'

import babelRequireHook from '@babel/register'
import cheerio from 'cheerio'
import ReactDOMServer from 'react-dom/server'

import { getPaths } from '@redwoodjs/internal'
Expand Down Expand Up @@ -68,11 +69,31 @@ export const runPrerender = async ({
</LocationProvider>
)

const { helmet } = global.__REDWOOD__HELMET_CONTEXT

const indexHtmlTree = cheerio.load(indexContent)

if (helmet) {
const helmetElements = `
${helmet?.link.toString()}
${helmet?.meta.toString()}
${helmet?.script.toString()}
${helmet?.noscript.toString()}
`

// Add all head elements
indexHtmlTree('head').prepend(helmetElements)

// Only change the title, if its not empty
if (cheerio.load(helmet?.title.toString())('title').text() !== '') {
indexHtmlTree('title').replaceWith(helmet?.title.toString())
}
}

// This is set by webpack by the html plugin
const renderOutput = indexContent.replace(
'<server-markup></server-markup>',
componentAsHtml
)
indexHtmlTree('server-markup').replaceWith(componentAsHtml)

const renderOutput = indexHtmlTree.html()

return renderOutput
}
Expand Down
3 changes: 3 additions & 0 deletions packages/web/global.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { HelmetData } from 'react-helmet-async'

export {}

declare global {
Expand All @@ -7,6 +9,7 @@ declare global {
* This global is set to true by the prerendering CLI command.
*/
__REDWOOD__PRERENDERING: boolean
__REDWOOD__HELMET_CONTEXT: { helmet?: HelmetData }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this for pre-rendering?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup - helmet async gathers up all the headers in this variable during prerender - will also be the same if we do this in builder functions in the future.

}
}
}
1 change: 1 addition & 0 deletions packages/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"core-js": "3.13.1",
"graphql": "15.5.1",
"proptypes": "1.1.0",
"react-helmet-async": "1.0.9",
"react-hot-toast": "2.0.0"
},
"peerDependencies": {
Expand Down
Loading