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

feat(og-gen): Update implementation of useLocation | Update App template #10441

Merged
merged 36 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
a78508a
Update prerender path to be URL
cannikin Feb 15, 2024
413294f
useLocation will return a full URL object instead of just three parts
cannikin Feb 15, 2024
52cb903
Include additional options when calling middleware
cannikin Feb 15, 2024
7891b35
Add server route for .png files
cannikin Feb 15, 2024
68b9ad0
Update App template to render children if present
cannikin Feb 29, 2024
5be594a
Tie into all extensions, not just png
cannikin Feb 29, 2024
4f97bb4
Move createServerAdapter calls for middleware to shared function, use…
cannikin Feb 29, 2024
1d62b74
Update types
cannikin Feb 29, 2024
2e58781
Updates App.tsx for test project fixture and rsc template
cannikin Feb 29, 2024
c627b31
Merge branch 'main' into rc-og-image-support
cannikin Feb 29, 2024
53c53e9
Adds useOgImageUrl() hook to return the URL to generate for the og:im…
cannikin Feb 29, 2024
c020090
Reorganize other web tests into __tests__ dir
cannikin Feb 29, 2024
4b9d39c
Modified to return separate width, height and ogProps in case you wan…
cannikin Feb 29, 2024
cc8ad07
Adds quality setting to useOgImage()
cannikin Mar 1, 2024
409357b
Merge branch 'main' of github.com:redwoodjs/redwood into rc-og-image-…
dac09 Mar 6, 2024
05e33d2
Update invokeMiddleware comments
dac09 Mar 6, 2024
e15fb10
Lint
dac09 Mar 6, 2024
5afcec2
Fix type linting warnings in skipNav
dac09 Mar 6, 2024
2be1e63
update fixture
dac09 Mar 6, 2024
dcdb43a
Add cssPaths to options
cannikin Mar 7, 2024
4ee6065
Merge branch 'main' into rc-og-image-support
dac09 Mar 7, 2024
04e7c49
Removes useOgImage hook code
cannikin Mar 7, 2024
5e4a453
Merge main | Fix conflicts
dac09 Mar 29, 2024
a44f28f
Bad merge
dac09 Mar 29, 2024
4b9f068
Update types in app template
dac09 Mar 29, 2024
787fa56
Lint fixes, Update project fixture
dac09 Mar 29, 2024
4f58b38
Merge branch 'main' into rc-og-image-support
dac09 Mar 30, 2024
cf90912
Merge main, and remove changes that are no longer required
dac09 Apr 11, 2024
183a7d9
Add changeset
dac09 Apr 11, 2024
3767eb8
Remove file thats no longer needed
dac09 Apr 11, 2024
1a81e23
Pass currentUrl in streaming handler instead of pathname
dac09 Apr 11, 2024
674f5f5
Merge branch 'main' into feat/rc-dc-uselocation-url
dac09 Apr 11, 2024
943c536
Merge branch 'main' into feat/rc-dc-uselocation-url
dac09 Apr 12, 2024
18f38f7
Update App.tsx fixture to put back auth provider and useAuth
dac09 Apr 12, 2024
5c4560d
Merge branch 'main' into feat/rc-dc-uselocation-url
dac09 Apr 12, 2024
df1386c
Update pkg json
dac09 Apr 12, 2024
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
10 changes: 10 additions & 0 deletions .changesets/10441.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
- feat(og-gen): Update implementation of useLocation | Update App template (#10441) by @dac09
**Updated App.tsx template**
We modified the `App.tsx` template to accept possible children, and render them if present. This lets the og:image handler inject your component into the Document tree, without including the entire Router, but still style your og:image component using whatever you used to style the rest of your app (Tailwind, perhaps?)

**Updated useLocation implementation**
We also modified the `useLocation()` hook to now return everything that the [URL API](https://developer.mozilla.org/en-US/docs/Web/API/URL) returns. Previously it only returned three attributes of the url (pathname, search, hash), now it returns everything available to a call to `new URL()` (origin, href, searchParams, etc.).

The reason for this is now that we have SSR, we can get access to more details in the hook - in this case we needed origin

Both changes should be non-breaking!
4 changes: 2 additions & 2 deletions __fixtures__/empty-project/web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import Routes from 'src/Routes'

import './index.css'

const App = () => (
const App = ({ children }) => (
<FatalErrorBoundary page={FatalErrorPage}>
<RedwoodProvider titleTemplate="%PageTitle | %AppTitle">
<RedwoodApolloProvider>
<Routes />
{children ? children : <Routes />}
</RedwoodApolloProvider>
</RedwoodProvider>
</FatalErrorBoundary>
Expand Down
9 changes: 7 additions & 2 deletions __fixtures__/test-project/web/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { ReactNode } from 'react'

import { FatalErrorBoundary, RedwoodProvider } from '@redwoodjs/web'
import { RedwoodApolloProvider } from '@redwoodjs/web/apollo'

Expand All @@ -8,13 +10,16 @@ import { AuthProvider, useAuth } from './auth'

import './scaffold.css'
import './index.css'
interface AppProps {
children?: ReactNode
}

const App = () => (
const App = ({ children }: AppProps) => (
<FatalErrorBoundary page={FatalErrorPage}>
<RedwoodProvider titleTemplate="%PageTitle | %AppTitle">
<AuthProvider>
<RedwoodApolloProvider useAuth={useAuth}>
<Routes />
{children ? children : <Routes />}
</RedwoodApolloProvider>
</AuthProvider>
</RedwoodProvider>
Expand Down
4 changes: 2 additions & 2 deletions packages/create-redwood-app/templates/js/web/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import Routes from 'src/Routes'

import './index.css'

const App = () => (
const App = ({ children }) => (
<FatalErrorBoundary page={FatalErrorPage}>
<RedwoodProvider titleTemplate="%PageTitle | %AppTitle">
<RedwoodApolloProvider>
<Routes />
{children ? children : <Routes />}
</RedwoodApolloProvider>
</RedwoodProvider>
</FatalErrorBoundary>
Expand Down
9 changes: 7 additions & 2 deletions packages/create-redwood-app/templates/ts/web/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import type { ReactNode } from 'react'

import { FatalErrorBoundary, RedwoodProvider } from '@redwoodjs/web'
import { RedwoodApolloProvider } from '@redwoodjs/web/apollo'

import FatalErrorPage from 'src/pages/FatalErrorPage'
import Routes from 'src/Routes'

import './index.css'
interface AppProps {
children?: ReactNode
}

const App = () => (
const App = ({ children }: AppProps) => (
<FatalErrorBoundary page={FatalErrorPage}>
<RedwoodProvider titleTemplate="%PageTitle | %AppTitle">
<RedwoodApolloProvider>
<Routes />
{children ? children : <Routes />}
</RedwoodApolloProvider>
</RedwoodProvider>
</FatalErrorBoundary>
Expand Down
1 change: 0 additions & 1 deletion packages/ogimage-gen/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
"files": [
"dist",
"cjsWrappers"

],
"scripts": {
"build": "tsx ./build.mts && yarn build:types",
Expand Down
10 changes: 9 additions & 1 deletion packages/prerender/src/runPrerender.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,16 @@ async function recursivelyRender(
}),
)

// `renderPath` is *just* a path, but the LocationProvider needs a full URL
// object so if you need the domain to be something specific when
// pre-rendering (because you're showing it in HTML output or the og:image
// uses useLocation().host) you can set the RWJS_PRERENDER_ORIGIN env variable
// so that it doesn't just default to localhost
const prerenderUrl =
process.env.RWJS_PRERENDER_ORIGIN || 'http://localhost' + renderPath

const componentAsHtml = ReactDOMServer.renderToString(
<LocationProvider location={{ pathname: renderPath }}>
<LocationProvider location={new URL(prerenderUrl)}>
<CellCacheContextProvider queryCache={queryCache}>
<App />
</CellCacheContextProvider>
Expand Down
31 changes: 8 additions & 23 deletions packages/router/src/location.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,20 @@ import { createNamedContext } from './createNamedContext'
import { gHistory } from './history'
import type { TrailingSlashesTypes } from './util'

export interface LocationContextType {
pathname: string
search?: string
hash?: string
}
export interface LocationContextType extends URL {}

const LocationContext = createNamedContext<LocationContextType>('Location')

interface Location {
pathname: string
search?: string
hash?: string
}
interface Location extends URL {}

interface LocationProviderProps {
location?: Location
trailingSlashes?: TrailingSlashesTypes
children?: React.ReactNode
}

interface LocationProviderState {
context: Location
context: Location | undefined
}

class LocationProvider extends React.Component<
Expand Down Expand Up @@ -75,27 +68,19 @@ class LocationProvider extends React.Component<
break
}

windowLocation = window.location
} else {
windowLocation = {
pathname: this.context?.pathname || '',
search: this.context?.search || '',
hash: this.context?.hash || '',
}
windowLocation = new URL(window.location.href)
}

const { pathname, search, hash } = this.props.location || windowLocation

return { pathname, search, hash }
return this.props.location || this.context || windowLocation
}

componentDidMount() {
this.HISTORY_LISTENER_ID = gHistory.listen(() => {
const context = this.getContext()
this.setState((lastState) => {
if (
context.pathname !== lastState.context.pathname ||
context.search !== lastState.context.search
context?.pathname !== lastState?.context?.pathname ||
context?.search !== lastState?.context?.search
) {
globalThis?.scrollTo(0, 0)
}
Expand Down
6 changes: 3 additions & 3 deletions packages/vite/src/streaming/createReactStreamingHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ export const createReactStreamingHandler = async (
let currentRoute: RWRouteManifestItem | undefined
let parsedParams: any = {}

const { pathname: currentPathName } = new URL(req.url)
const currentUrl = new URL(req.url)

// @TODO validate this is correct
for (const route of routes) {
const { match, ...rest } = matchPath(
route.pathDefinition,
currentPathName,
currentUrl.pathname,
)
if (match) {
currentRoute = route
Expand Down Expand Up @@ -174,7 +174,7 @@ export const createReactStreamingHandler = async (
{
ServerEntry,
FallbackDocument,
currentPathName,
currentUrl,
metaTags,
cssLinks,
isProd,
Expand Down
12 changes: 5 additions & 7 deletions packages/vite/src/streaming/streamHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { createServerInjectionTransform } from './transforms/serverInjectionTran
interface RenderToStreamArgs {
ServerEntry: ServerEntryType
FallbackDocument: React.FunctionComponent
currentPathName: string
currentUrl: URL
metaTags: TagDescriptor[]
cssLinks: string[]
isProd: boolean
Expand Down Expand Up @@ -64,7 +64,7 @@ export async function reactRenderToStreamResponse(
const {
ServerEntry,
FallbackDocument,
currentPathName,
currentUrl,
metaTags,
cssLinks,
isProd,
Expand Down Expand Up @@ -103,7 +103,7 @@ export async function reactRenderToStreamResponse(

const timeoutTransform = createTimeoutTransform(timeoutHandle)

const renderRoot = (path: string) => {
const renderRoot = (url: URL) => {
return React.createElement(
ServerAuthProvider,
{
Expand All @@ -112,9 +112,7 @@ export async function reactRenderToStreamResponse(
React.createElement(
LocationProvider,
{
location: {
pathname: path,
},
location: url,
},
React.createElement(
ServerHtmlProvider,
Expand Down Expand Up @@ -157,7 +155,7 @@ export async function reactRenderToStreamResponse(
},
}

const root = renderRoot(currentPathName)
const root = renderRoot(currentUrl)

const reactStream: ReactDOMServerReadableStream =
await renderToReadableStream(root, renderToStreamOptions)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { AuthContextInterface } from '@redwoodjs/auth'

globalThis.RWJS_API_GRAPHQL_URL = 'https://api.example.com/graphql'

import { FetchConfigProvider, useFetchConfig } from './FetchConfigProvider.js'
import { FetchConfigProvider, useFetchConfig } from '../FetchConfigProvider.js'

const FetchConfigToString: React.FunctionComponent = () => {
const c = useFetchConfig()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
useQuery,
useMutation,
useSubscription,
} from './GraphQLHooksProvider'
} from '../GraphQLHooksProvider'

const TestUseQueryHook: React.FunctionComponent = () => {
// @ts-expect-error - Purposefully not passing in a DocumentNode type here.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react'
import { render } from '@testing-library/react'
import { describe, beforeAll, it, expect } from 'vitest'

import { Metadata } from './Metadata.js'
import { Metadata } from '../Metadata.js'

// DOCS: can return a structured object from the database and just give it to `og` and it works

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import React from 'react'
import { render } from '@testing-library/react'
import { vi, describe, it, expect } from 'vitest'

import PortalHead from './PortalHead.js'
import * as ServerInject from './ServerInject.js'
import PortalHead from '../PortalHead.js'
import * as ServerInject from '../ServerInject.js'

const serverInsertionHookSpy = vi
.spyOn(ServerInject, 'useServerInsertedHTML')
Expand Down
Loading