Skip to content

Commit

Permalink
fix(next15): support older browsers with client side rendering (#1757)
Browse files Browse the repository at this point in the history
  • Loading branch information
emilielr authored Dec 9, 2024
1 parent a64f50d commit d850f17
Show file tree
Hide file tree
Showing 13 changed files with 52 additions and 420 deletions.
2 changes: 1 addition & 1 deletion tavla/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const { withSentryConfig } = require("@sentry/nextjs");
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone',
transpilePackages: ['swr', 'tailwindcss'],
transpilePackages: ['swr', 'tailwindcss', 'next', '@sentry/nextjs', '@sentry/browser', '@sentry/react', '@sentry/core', '@sentry/utils', '@sentry-internal'],
i18n: {
locales: ['nb'],
defaultLocale: 'nb',
Expand Down
4 changes: 1 addition & 3 deletions tavla/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,8 @@
"posthog-js": "1.176.0",
"react": "18.3.1",
"react-dom": "18.3.1",
"semver": "7.6.3",
"sharp": "0.33.5",
"swr": "2.2.5",
"ua-parser-js": "2.0.0"
"swr": "2.2.5"
},
"devDependencies": {
"@graphql-codegen/cli": "5.0.3",
Expand Down
74 changes: 1 addition & 73 deletions tavla/pages/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,7 @@ import { useRefresh } from 'hooks/useRefresh'
import { getBackendUrl } from 'utils/index'
import Head from 'next/head'
import { useEffect } from 'react'
import { fetchQuery } from 'graphql/utils'
import { addMinutesToDate, formatDateToISO } from 'utils/time'
import { TGetQuayQuery, TStopPlaceQuery } from 'graphql/index'
import { isUnsupportedBrowser } from 'utils/browserDetection'
import { GetServerSideProps } from 'next'
import { SSRQuayQuery, SSRStopPlaceQuery } from 'graphql/ssrQueries'
import * as Sentry from '@sentry/nextjs'

export const getServerSideProps: GetServerSideProps = async (context) => {
Expand All @@ -28,8 +23,6 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
}
}
const { id } = params as { id: string }
const ua = req.headers['user-agent'] || ''
const fetchBoardServerSide = isUnsupportedBrowser(ua)

if (!id) {
Sentry.captureMessage('Missing board ID in getServerSideProps')
Expand All @@ -49,17 +42,11 @@ export const getServerSideProps: GetServerSideProps = async (context) => {

const organization = await getOrganizationWithBoard(id)

let tileData = null
if (fetchBoardServerSide) {
tileData = await getTileData(board)
}

return {
props: {
board,
organization,
backend_url: getBackendUrl(),
tileData,
},
}
} catch (error) {
Expand All @@ -78,12 +65,10 @@ function BoardPage({
board,
organization,
backend_url,
tileData,
}: {
board: TBoard
organization: TOrganization | null
backend_url: string
tileData?: (TStopPlaceQuery | TGetQuayQuery | null)[]
}) {
const updatedBoard = useRefresh(board, backend_url)

Expand Down Expand Up @@ -112,7 +97,7 @@ function BoardPage({
theme={updatedBoard.theme}
organizationLogo={organization?.logo}
/>
<Board board={updatedBoard} data={tileData} />
<Board board={updatedBoard} />
<Footer
board={updatedBoard}
logo={organization?.logo !== undefined}
Expand All @@ -124,60 +109,3 @@ function BoardPage({
}

export default BoardPage

// Fetch data for each tile on the board
// Used for server side rendering on unsupported browsers
const getTileData = async (board: TBoard) => {
const tileData = await Promise.all(
board.tiles.map(async (tile) => {
if (tile.type === 'stop_place') {
const variables = {
stopPlaceId: tile.placeId,
whitelistedTransportModes: tile.whitelistedTransportModes,
whitelistedLines: tile.whitelistedLines,
startTime: formatDateToISO(
addMinutesToDate(new Date(), tile.offset ?? 0),
),
}
try {
const data = await fetchQuery(SSRStopPlaceQuery, variables)
return data
} catch (error) {
Sentry.captureException(error, {
extra: {
message:
'Server-side fetching of departures for stopPlace failed',
queryVariables: variables,
},
})
return null
}
} else if (tile.type === 'quay') {
const variables = {
quayId: tile.placeId,
whitelistedLines: tile.whitelistedLines,
whitelistedTransportModes: tile.whitelistedTransportModes,
startTime: formatDateToISO(
addMinutesToDate(new Date(), tile.offset ?? 0),
),
}
try {
const data = await fetchQuery(SSRQuayQuery, variables)
return data
} catch (error) {
Sentry.captureException(error, {
extra: {
message:
'Server-side fetching of departures for quay failed',
queryVariables: variables,
},
})
return null
}
} else {
return null
}
}),
)
return tileData
}
35 changes: 6 additions & 29 deletions tavla/pages/_document.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,15 @@
import Document, {
Html,
Head,
Main,
NextScript,
DocumentContext,
DocumentInitialProps,
} from 'next/document'
import { isUnsupportedBrowser } from 'utils/browserDetection'

interface TavlaDocumentProps extends DocumentInitialProps {
needsRefresh: boolean
}
import Document, { Html, Head, Main, NextScript } from 'next/document'
import Script from 'next/script'

class TavlaDocument extends Document {
static async getInitialProps(
context: DocumentContext,
): Promise<TavlaDocumentProps> {
const initialProps = await Document.getInitialProps(context)
const ua = context.req?.headers['user-agent'] || ''

const needsRefresh = isUnsupportedBrowser(ua)
return {
...initialProps,
needsRefresh,
}
}

render() {
const { needsRefresh } = this.props as unknown as TavlaDocumentProps

return (
<Html>
<Head>
{needsRefresh && <meta httpEquiv="refresh" content="45" />}
<Script
strategy="beforeInteractive"
src="global-this.js"
></Script>
<link
rel="apple-touch-icon"
sizes="180x180"
Expand Down
15 changes: 15 additions & 0 deletions tavla/public/global-this.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
;(function (Object) {
typeof globalThis !== 'object' &&
(this
? get()
: (Object.defineProperty(Object.prototype, '_T_', {
configurable: true,
get: get,
}),
_T_))
function get() {
var global = this || self
global.globalThis = global
delete Object.prototype._T_
}
})(Object)
48 changes: 6 additions & 42 deletions tavla/src/Board/scenarios/Board/index.tsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,21 @@
import { TBoard, TTheme } from 'types/settings'
import { TBoard } from 'types/settings'
import { TTile } from 'types/tile'
import { StopPlaceTile } from '../StopPlaceTile'
import { QuayTile } from '../QuayTile'
import { Tile } from 'components/Tile'
import { defaultFontSize, getFontScale } from 'Board/scenarios/Board/utils'
import { CSSProperties } from 'react'
import { TGetQuayQuery, TStopPlaceQuery } from 'graphql/index'

function BoardTile({
tileSpec,
data,
theme,
}: {
tileSpec: TTile
data?: TStopPlaceQuery | TGetQuayQuery | null
theme: TTheme
}) {
function BoardTile({ tileSpec }: { tileSpec: TTile }) {
switch (tileSpec.type) {
case 'stop_place':
return (
<StopPlaceTile
{...tileSpec}
data={data as TStopPlaceQuery | undefined}
theme={theme}
/>
)
return <StopPlaceTile {...tileSpec} />
case 'quay':
return (
<QuayTile
{...tileSpec}
data={data as TGetQuayQuery | undefined}
theme={theme}
/>
)
return <QuayTile {...tileSpec} />
}
}

function Board({
board,
style,
data,
}: {
board: TBoard
style?: CSSProperties
data?: (TStopPlaceQuery | TGetQuayQuery | null)[]
}) {
function Board({ board, style }: { board: TBoard; style?: CSSProperties }) {
if (!board.tiles || !board.tiles.length)
return (
<Tile className="flex items-center justify-center">
Expand All @@ -62,14 +33,7 @@ function Board({
}}
>
{board.tiles.map((tile, index) => {
return (
<BoardTile
key={index}
tileSpec={tile}
data={data ? data[index] : undefined}
theme={board.theme || 'dark'}
/>
)
return <BoardTile key={index} tileSpec={tile} />
})}
</div>
)
Expand Down
10 changes: 3 additions & 7 deletions tavla/src/Board/scenarios/QuayTile/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TQuayTile } from 'types/tile'
import { Table } from '../Table'
import { GetQuayQuery, TGetQuayQuery } from 'graphql/index'
import { GetQuayQuery } from 'graphql/index'
import { Tile } from 'components/Tile'
import { TableHeader } from '../Table/components/TableHeader'
import { isNotNullOrUndefined } from 'utils/typeguards'
Expand All @@ -10,7 +10,6 @@ import {
DataFetchingFailed,
FetchErrorTypes,
} from 'Board/components/DataFetchingFailed'
import { TTheme } from 'types/settings'
import * as Sentry from '@sentry/nextjs'

export function QuayTile({
Expand All @@ -21,17 +20,15 @@ export function QuayTile({
walkingDistance,
offset,
displayName,
data: initialData,
theme,
}: TQuayTile & { data?: TGetQuayQuery; theme: TTheme }) {
}: TQuayTile) {
const { data, isLoading, error } = useQuery(
GetQuayQuery,
{
quayId: placeId,
whitelistedLines,
whitelistedTransportModes,
},
{ poll: true, offset: offset ?? 0, fallbackData: initialData },
{ poll: true, offset: offset ?? 0 },
)

if (isLoading && !data) {
Expand Down Expand Up @@ -76,7 +73,6 @@ export function QuayTile({
columns={columns}
departures={data.quay.estimatedCalls}
situations={data.quay.situations}
theme={theme}
/>
</Tile>
)
Expand Down
10 changes: 3 additions & 7 deletions tavla/src/Board/scenarios/StopPlaceTile/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TStopPlaceTile } from 'types/tile'
import { Table } from '../Table'
import { StopPlaceQuery, TStopPlaceQuery } from 'graphql/index'
import { StopPlaceQuery } from 'graphql/index'
import { Tile } from 'components/Tile'
import { TableHeader } from '../Table/components/TableHeader'
import { TileLoader } from 'Board/components/TileLoader'
Expand All @@ -9,7 +9,6 @@ import {
DataFetchingFailed,
FetchErrorTypes,
} from 'Board/components/DataFetchingFailed'
import { TTheme } from 'types/settings'
import * as Sentry from '@sentry/nextjs'

export function StopPlaceTile({
Expand All @@ -20,17 +19,15 @@ export function StopPlaceTile({
walkingDistance,
offset,
displayName,
data: initialData,
theme,
}: TStopPlaceTile & { data?: TStopPlaceQuery; theme?: TTheme }) {
}: TStopPlaceTile) {
const { data, isLoading, error } = useQuery(
StopPlaceQuery,
{
stopPlaceId: placeId,
whitelistedTransportModes,
whitelistedLines,
},
{ poll: true, offset: offset, fallbackData: initialData },
{ poll: true, offset: offset },
)

if (isLoading && !data) {
Expand Down Expand Up @@ -71,7 +68,6 @@ export function StopPlaceTile({
departures={data.stopPlace.estimatedCalls}
situations={data.stopPlace.situations}
columns={columns}
theme={theme}
/>
</Tile>
)
Expand Down
6 changes: 4 additions & 2 deletions tavla/src/Board/scenarios/Table/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ function Table({
departures,
columns,
situations,
theme,
}: {
departures: TDepartureFragment[]
columns?: TColumn[]
situations?: TSituationFragment[]
theme?: string
}) {
const theme = document
.querySelector('[data-theme]')
?.getAttribute('data-theme')

if (!columns || !isArray(columns))
return (
<div className="flex shrink-0">
Expand Down
Loading

0 comments on commit d850f17

Please sign in to comment.