rsnext/packages/next/build/output/store.ts
OJ Kwon 46dde0dd4a
feat(next/swc): setup native next-swc crash reporter with platform supports (#38221)
This is second attempt to https://github.com/vercel/next.js/pull/38076 . Most of changes are identical to previous PR. Main difference is introducing features `native-tls` and `rustls` for the sentry's downstream feature. Few platform targets we build (mostly where we cross compiles) fails to find native openssl for the specified target. For those, we falls back to rustls instead. The only exception is aarch64_windows, neither openssl nor rustls can be compiled straightforwardly, For those platform we bail out and do not init sentry at all. There are nearly 0 users on aarch64_windows anyway. We could try to located target's openssl binary, but the effort required seems not worth enough. 

Also PR changed `server_name` property to not to include real device hostname to avoid possible PII concerns.

## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have helpful link attached, see `contributing.md`

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `pnpm lint`
- [ ] The examples guidelines are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing.md#adding-examples)
2022-07-07 17:37:50 +00:00

141 lines
3.5 KiB
TypeScript

import createStore from 'next/dist/compiled/unistore'
import stripAnsi from 'next/dist/compiled/strip-ansi'
import { flushAllTraces } from '../../trace'
import { teardownCrashReporter, teardownTraceSubscriber } from '../swc'
import * as Log from './log'
export type OutputState =
| { bootstrap: true; appUrl: string | null; bindAddr: string | null }
| ({ bootstrap: false; appUrl: string | null; bindAddr: string | null } & (
| {
loading: true
trigger: string | undefined
}
| {
loading: false
typeChecking: boolean
partial: 'client and server' | undefined
modules: number
errors: string[] | null
warnings: string[] | null
hasEdgeServer: boolean
}
))
export const store = createStore<OutputState>({
appUrl: null,
bindAddr: null,
bootstrap: true,
})
let lastStore: OutputState = { appUrl: null, bindAddr: null, bootstrap: true }
function hasStoreChanged(nextStore: OutputState) {
if (
(
[
...new Set([...Object.keys(lastStore), ...Object.keys(nextStore)]),
] as Array<keyof OutputState>
).every((key) => Object.is(lastStore[key], nextStore[key]))
) {
return false
}
lastStore = nextStore
return true
}
let startTime = 0
store.subscribe((state) => {
if (!hasStoreChanged(state)) {
return
}
if (state.bootstrap) {
if (state.appUrl) {
Log.ready(`started server on ${state.bindAddr}, url: ${state.appUrl}`)
}
return
}
if (state.loading) {
if (state.trigger) {
if (state.trigger !== 'initial') {
Log.wait(`compiling ${state.trigger}...`)
}
} else {
Log.wait('compiling...')
}
if (startTime === 0) {
startTime = Date.now()
}
return
}
if (state.errors) {
Log.error(state.errors[0])
const cleanError = stripAnsi(state.errors[0])
if (cleanError.indexOf('SyntaxError') > -1) {
const matches = cleanError.match(/\[.*\]=/)
if (matches) {
for (const match of matches) {
const prop = (match.split(']').shift() || '').slice(1)
console.log(
`AMP bind syntax [${prop}]='' is not supported in JSX, use 'data-amp-bind-${prop}' instead. https://nextjs.org/docs/messages/amp-bind-jsx-alt`
)
}
return
}
}
startTime = 0
// Ensure traces are flushed after each compile in development mode
flushAllTraces()
teardownTraceSubscriber()
teardownCrashReporter()
return
}
let timeMessage = ''
if (startTime) {
const time = Date.now() - startTime
startTime = 0
timeMessage =
time > 2000 ? ` in ${Math.round(time / 100) / 10}s` : ` in ${time} ms`
}
let modulesMessage = ''
if (state.modules) {
modulesMessage = ` (${state.modules} modules)`
}
let partialMessage = ''
if (state.partial) {
partialMessage = ` ${state.partial}`
}
if (state.warnings) {
Log.warn(state.warnings.join('\n\n'))
// Ensure traces are flushed after each compile in development mode
flushAllTraces()
teardownTraceSubscriber()
teardownCrashReporter()
return
}
if (state.typeChecking) {
Log.info(
`bundled${partialMessage} successfully${timeMessage}${modulesMessage}, waiting for typecheck results...`
)
return
}
Log.event(
`compiled${partialMessage} successfully${timeMessage}${modulesMessage}`
)
// Ensure traces are flushed after each compile in development mode
flushAllTraces()
teardownTraceSubscriber()
teardownCrashReporter()
})