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: show version staleness in error overlay #44234

Merged
merged 51 commits into from
Feb 17, 2023
Merged
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
33c79d5
feat: show version staleness in error overlay
balazsorban44 Dec 21, 2022
f5ed37b
move comparison to server
balazsorban44 Dec 21, 2022
97a59e5
add fallback title
balazsorban44 Dec 21, 2022
529953a
add comparison logic
balazsorban44 Dec 21, 2022
56faefc
rephrase, add link
balazsorban44 Dec 21, 2022
d9dc427
rephrase
balazsorban44 Dec 21, 2022
57093ac
add unknown state info
balazsorban44 Dec 21, 2022
de8472b
add message page
balazsorban44 Dec 21, 2022
33b84ac
remove unused variable
balazsorban44 Dec 21, 2022
5de1dcd
change default state to unknown
balazsorban44 Dec 21, 2022
0bd318d
assume cached endpoint
balazsorban44 Dec 21, 2022
d856b93
remove todo
balazsorban44 Dec 21, 2022
e072b87
Update packages/next/client/components/react-dev-overlay/internal/con…
balazsorban44 Jan 12, 2023
2875ee7
fix todo
balazsorban44 Jan 12, 2023
1664437
Merge branch 'canary' into feat/staleness-in-error-overlay
balazsorban44 Jan 12, 2023
3a8375a
revert
balazsorban44 Jan 12, 2023
24e2442
revert
balazsorban44 Jan 12, 2023
8c625f5
address review
balazsorban44 Jan 12, 2023
5907c7a
Update errors/version-staleness.md
balazsorban44 Jan 12, 2023
03263c6
simplify error message
balazsorban44 Jan 12, 2023
7229346
Merge branch 'canary' into feat/staleness-in-error-overlay
balazsorban44 Jan 12, 2023
59229e6
Merge branch 'canary' into feat/staleness-in-error-overlay
balazsorban44 Jan 19, 2023
b7f1c20
Apply suggestions from code review
balazsorban44 Jan 19, 2023
aec87d8
fix import
balazsorban44 Jan 19, 2023
5d05fad
show correct installed version if fetch fails
balazsorban44 Jan 19, 2023
932961f
fix test
balazsorban44 Jan 19, 2023
073cfa6
Merge branch 'canary' of https://github.com/hanneslund/next.js into f…
Feb 3, 2023
6292f75
Add null check
Feb 3, 2023
4a492f7
Merge branch 'canary' into feat/staleness-in-error-overlay
hanneslund Feb 3, 2023
606b431
Fix lint?
Feb 3, 2023
0b7babb
Fix parseVersionInfo
Feb 3, 2023
1cb3b4e
Apply suggestions from code review
styfle Feb 7, 2023
6a061ba
Update version-staleness.md
balazsorban44 Feb 8, 2023
f89337d
extract and use retrieving registry logic
balazsorban44 Feb 8, 2023
0d48a6c
Check if versionInfo is provided
Feb 10, 2023
65e8445
Move staleness indicator to seperate file
Feb 10, 2023
0ef83c8
Add staleness info to build errors and runtime errors
Feb 10, 2023
6b19f22
Fix types
Feb 10, 2023
a35bff5
Add tests
Feb 10, 2023
cdfdfa8
Merge branch 'canary' into feat/staleness-in-error-overlay
hanneslund Feb 10, 2023
d2bd162
Fix ts errors
Feb 10, 2023
8f7c535
Fix another ts error
Feb 10, 2023
83c12cb
Merge branch 'canary' into feat/staleness-in-error-overlay
hanneslund Feb 16, 2023
add39c8
Merge branch 'canary' into feat/staleness-in-error-overlay
hanneslund Feb 16, 2023
aadb826
Merge branch 'canary' into feat/staleness-in-error-overlay
hanneslund Feb 17, 2023
27be20d
Don't fetch staleness info if telemetry is disabled
Feb 17, 2023
f79dbbb
Reuse telemetry instance
Feb 17, 2023
5c7226c
Enable version staleness in tests
Feb 17, 2023
90c6b0c
Move version info parse function to its own file and colocate unit test
Feb 17, 2023
94eff66
Merge branch 'canary' into feat/staleness-in-error-overlay
hanneslund Feb 17, 2023
dcf268e
Merge branch 'canary' into feat/staleness-in-error-overlay
kodiakhq[bot] Feb 17, 2023
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
4 changes: 4 additions & 0 deletions errors/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,10 @@
{
"title": "app-static-to-dynamic-error",
"path": "/errors/app-static-to-dynamic-error.md"
},
{
"title": "version-staleness",
"path": "/errors/version-staleness.md"
}
]
}
Expand Down
5 changes: 4 additions & 1 deletion errors/opening-an-issue.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#### Why This Message Occurred

When `next info` was run, Next.js detected that it's was not on the latest canary release.
When `next info` was run, Next.js detected that it was not on the newest canary release.

`next@canary` is the canary version of Next.js that ships daily. It includes all features and fixes that have not been released to the stable version yet. Think of canary as a public beta.

Expand All @@ -26,3 +26,6 @@ And go through the prepared reproduction steps once again, and check if the issu

- [Video: How to Contribute to Open Source (Next.js)](https://www.youtube.com/watch?v=cuoNzXFLitc)
- [Contributing to Next.js](https://github.com/vercel/next.js/blob/canary/contributing.md)
- [Triaging issues](https://github.com/vercel/next.js/blob/canary/contributing/repository/triaging.md)
- [Verifiying canary](https://github.com/vercel/next.js/blob/canary/.github/actions/issue-validator/canary.md)
- [Adding a reproduction](https://github.com/vercel/next.js/blob/canary/.github/actions/issue-validator/repro.md)
52 changes: 52 additions & 0 deletions errors/version-staleness.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Version Staleness

#### Why This Error Occurred

In the error overlay, a message was shown that the detected Next.js version was out-of-date.

To get the newest features and bug fixes, it is recommended to stay up to date.

#### Possible Ways to Fix It

If you are testing out a canary release, upgrade Next.js with one of the following:

```sh
npm i next@canary
```

```sh
yarn add next@canary
```

```sh
pnpm add next@canary
```

If you are using a stable release, upgrade Next.js with one of the following:

```sh
npm i next@latest
```

```sh
yarn add next@latest
```

```sh
pnpm add next@latest
```

If you are coming from an older major version, check out our [upgrade guides](https://nextjs.org/docs/upgrading).

### Note

If you want to report a bug on GitHub, you should upgrade to the newest canary release of Next.js first, to see if the bug has already been fixed in canary.

### Useful Links

- [Upgrade guide](https://nextjs.org/docs/upgrading)
- [Video: How to Contribute to Open Source (Next.js)](https://www.youtube.com/watch?v=cuoNzXFLitc)
- [Contributing to Next.js](https://github.com/vercel/next.js/blob/canary/contributing.md)
- [Triaging issues](https://github.com/vercel/next.js/blob/canary/contributing/repository/triaging.md)
- [Verifiying canary](https://github.com/vercel/next.js/blob/canary/.github/actions/issue-validator/canary.md)
- [Adding a reproduction](https://github.com/vercel/next.js/blob/canary/.github/actions/issue-validator/repro.md)
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import React, {
import stripAnsi from 'next/dist/compiled/strip-ansi'
import formatWebpackMessages from '../../dev/error-overlay/format-webpack-messages'
import { useRouter } from '../navigation'
import { errorOverlayReducer } from './internal/error-overlay-reducer'
import {
ACTION_VERSION_INFO,
errorOverlayReducer,
} from './internal/error-overlay-reducer'
import {
ACTION_BUILD_OK,
ACTION_BUILD_ERROR,
Expand All @@ -31,10 +34,12 @@ import {
useWebsocketPing,
} from './internal/helpers/use-websocket'
import { parseComponentStack } from './internal/helpers/parse-component-stack'
import type { VersionInfo } from './internal/components/VersionStalenessInfo'

interface Dispatcher {
onBuildOk(): void
onBuildError(message: string): void
onVersionInfo(versionInfo: VersionInfo): void
onBeforeRefresh(): void
onRefresh(): void
}
Expand Down Expand Up @@ -218,7 +223,12 @@ function processMessage(
handleAvailableHash(obj.hash)
}

const { errors, warnings } = obj
const { errors, warnings, versionInfo } = obj

// Is undefined when it's a 'built' event
if (versionInfo) {
dispatcher.onVersionInfo(versionInfo)
}
const hasErrors = Boolean(errors && errors.length)
// Compilation with errors (e.g. syntax error or missing modules).
if (hasErrors) {
Expand Down Expand Up @@ -403,21 +413,25 @@ export default function HotReload({
buildError: null,
errors: [],
refreshState: { type: 'idle' },
versionInfo: { installed: '0.0.0', staleness: 'unknown' },
})
const dispatcher = useMemo((): Dispatcher => {
return {
onBuildOk(): void {
onBuildOk() {
dispatch({ type: ACTION_BUILD_OK })
},
onBuildError(message: string): void {
onBuildError(message) {
dispatch({ type: ACTION_BUILD_ERROR, message })
},
onBeforeRefresh(): void {
onBeforeRefresh() {
dispatch({ type: ACTION_BEFORE_REFRESH })
},
onRefresh(): void {
onRefresh() {
dispatch({ type: ACTION_REFRESH })
},
onVersionInfo(versionInfo) {
dispatch({ type: ACTION_VERSION_INFO, versionInfo })
},
}
}, [dispatch])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import {
import { ShadowPortal } from './components/ShadowPortal'
import { BuildError } from './container/BuildError'
import { Errors, SupportedErrorEvent } from './container/Errors'
import { RootLayoutError } from './container/RootLayoutError'
import { parseStack } from './helpers/parseStack'
import { Base } from './styles/Base'
import { ComponentStyles } from './styles/ComponentStyles'
import { CssReset } from './styles/CssReset'
import { parseStack } from './helpers/parseStack'
import { RootLayoutError } from './container/RootLayoutError'

interface ReactDevOverlayState {
reactError: SupportedErrorEvent | null
Expand Down Expand Up @@ -79,11 +79,22 @@ class ReactDevOverlay extends React.PureComponent<
missingTags={rootLayoutMissingTagsError.missingTags}
/>
) : hasBuildError ? (
<BuildError message={state.buildError!} />
<BuildError
message={state.buildError!}
versionInfo={state.versionInfo}
/>
) : reactError ? (
<Errors initialDisplayState="fullscreen" errors={[reactError]} />
<Errors
versionInfo={state.versionInfo}
initialDisplayState="fullscreen"
errors={[reactError]}
/>
) : hasRuntimeErrors ? (
<Errors initialDisplayState="minimized" errors={state.errors} />
<Errors
initialDisplayState="minimized"
errors={state.errors}
versionInfo={state.versionInfo}
/>
) : undefined}
</ShadowPortal>
) : undefined}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ const styles = css`
align-items: center;
justify-content: space-between;
}
[data-nextjs-dialog-left-right] > nav {
flex: 1;
display: flex;
align-items: center;
margin-right: var(--size-gap);
}
[data-nextjs-dialog-left-right] > nav > button {
display: inline-flex;
align-items: center;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React from 'react'

export interface VersionInfo {
installed: string
staleness:
| 'fresh'
| 'stale-patch'
| 'stale-minor'
| 'stale-major'
| 'stale-prerelease'
| 'newer-than-npm'
| 'unknown'
expected?: string
}

export function VersionStalenessInfo(props: VersionInfo) {
if (!props) return null
const { staleness, installed, expected } = props
let text = ''
let title = ''
let indicatorClass = ''
switch (staleness) {
case 'fresh':
text = 'Next.js is up to date'
title = `Latest available version is detected (${installed}).`
indicatorClass = 'fresh'
break
case 'stale-patch':
case 'stale-minor':
text = `Next.js (${installed}) out of date`
title = `There is a newer version (${expected}) available, upgrade recommended! `
indicatorClass = 'stale'
break
case 'stale-major': {
text = `Next.js (${installed}) is outdated`
title = `An outdated version detected (latest is ${expected}), upgrade is highly recommended!`
indicatorClass = 'outdated'
break
}
case 'stale-prerelease': {
text = `Next.js (${installed}) is outdated`
title = `There is a newer canary version (${expected}) available, please upgrade! `
indicatorClass = 'stale'
break
}
case 'newer-than-npm':
case 'unknown':
break
default:
break
}

if (!text) return null

return (
<small className="nextjs-container-build-error-version-status">
<span className={indicatorClass} />
<small
className="nextjs-container-build-error-version-status"
title={title}
>
{text}
</small>{' '}
<a
target="_blank"
rel="noopener noreferrer"
href="https://nextjs.org/docs/messages/version-staleness"
>
(learn more)
</a>
</small>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { styles } from './styles'
export { VersionStalenessInfo, VersionInfo } from './VersionStalenessInfo'
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { noop as css } from '../../helpers/noop-template'

const styles = css`
.nextjs-container-build-error-version-status {
flex: 1;
text-align: right;
}
.nextjs-container-build-error-version-status small {
margin-left: var(--size-gap);
font-size: var(--size-font-small);
}
.nextjs-container-build-error-version-status a {
font-size: var(--size-font-small);
}
.nextjs-container-build-error-version-status span {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 5px;
background: var(--color-ansi-bright-black);
}
.nextjs-container-build-error-version-status span.fresh {
background: var(--color-ansi-green);
}
.nextjs-container-build-error-version-status span.stale {
background: var(--color-ansi-yellow);
}
.nextjs-container-build-error-version-status span.outdated {
background: var(--color-ansi-red);
}
`

export { styles }
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,17 @@ import {
} from '../components/Dialog'
import { Overlay } from '../components/Overlay'
import { Terminal } from '../components/Terminal'
import {
VersionInfo,
VersionStalenessInfo,
} from '../components/VersionStalenessInfo'
import { noop as css } from '../helpers/noop-template'

export type BuildErrorProps = { message: string }
export type BuildErrorProps = { message: string; versionInfo?: VersionInfo }

export const BuildError: React.FC<BuildErrorProps> = function BuildError({
message,
versionInfo,
}) {
const noop = React.useCallback(() => {}, [])
return (
Expand All @@ -26,6 +31,7 @@ export const BuildError: React.FC<BuildErrorProps> = function BuildError({
<DialogContent>
<DialogHeader className="nextjs-container-build-error-header">
<h4 id="nextjs__container_build_error_label">Failed to compile</h4>
{versionInfo ? <VersionStalenessInfo {...versionInfo} /> : null}
</DialogHeader>
<DialogBody className="nextjs-container-build-error-body">
<Terminal content={message} />
Expand All @@ -45,6 +51,10 @@ export const BuildError: React.FC<BuildErrorProps> = function BuildError({
}

export const styles = css`
.nextjs-container-build-error-header {
display: flex;
align-items: center;
}
.nextjs-container-build-error-header > h4 {
line-height: 1.5;
margin: 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ import { getErrorSource } from '../helpers/nodeStackFrames'
import { noop as css } from '../helpers/noop-template'
import { CloseIcon } from '../icons/CloseIcon'
import { RuntimeError } from './RuntimeError'
import {
VersionInfo,
VersionStalenessInfo,
} from '../components/VersionStalenessInfo'

export type SupportedErrorEvent = {
id: number
Expand All @@ -27,6 +31,7 @@ export type SupportedErrorEvent = {
export type ErrorsProps = {
errors: SupportedErrorEvent[]
initialDisplayState: DisplayState
versionInfo?: VersionInfo
}

type ReadyErrorEvent = ReadyRuntimeError
Expand Down Expand Up @@ -81,6 +86,7 @@ const HotlinkedText: React.FC<{
export const Errors: React.FC<ErrorsProps> = function Errors({
errors,
initialDisplayState,
versionInfo,
}) {
const [lookups, setLookups] = React.useState(
{} as { [eventId: string]: ReadyErrorEvent }
Expand Down Expand Up @@ -271,6 +277,7 @@ export const Errors: React.FC<ErrorsProps> = function Errors({
<span>{readyErrors.length}</span> unhandled error
{readyErrors.length < 2 ? '' : 's'}
</small>
{versionInfo ? <VersionStalenessInfo {...versionInfo} /> : null}
</LeftRightDialogHeader>
<h1 id="nextjs__container_errors_label">
{isServerError ? 'Server Error' : 'Unhandled Runtime Error'}
Expand Down
Loading