nextjs.tsx 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import ExternalLink from 'sentry/components/links/externalLink';
  4. import List from 'sentry/components/list/';
  5. import ListItem from 'sentry/components/list/listItem';
  6. import crashReportCallout from 'sentry/components/onboarding/gettingStartedDoc/feedback/crashReportCallout';
  7. import widgetCallout from 'sentry/components/onboarding/gettingStartedDoc/feedback/widgetCallout';
  8. import TracePropagationMessage from 'sentry/components/onboarding/gettingStartedDoc/replay/tracePropagationMessage';
  9. import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
  10. import type {
  11. Docs,
  12. DocsParams,
  13. OnboardingConfig,
  14. } from 'sentry/components/onboarding/gettingStartedDoc/types';
  15. import {
  16. getCrashReportJavaScriptInstallStep,
  17. getCrashReportModalConfigDescription,
  18. getCrashReportModalIntroduction,
  19. getFeedbackConfigureDescription,
  20. getFeedbackSDKSetupSnippet,
  21. } from 'sentry/components/onboarding/gettingStartedDoc/utils/feedbackOnboarding';
  22. import {getJSMetricsOnboarding} from 'sentry/components/onboarding/gettingStartedDoc/utils/metricsOnboarding';
  23. import {
  24. getReplayConfigureDescription,
  25. getReplaySDKSetupSnippet,
  26. } from 'sentry/components/onboarding/gettingStartedDoc/utils/replayOnboarding';
  27. import TextCopyInput from 'sentry/components/textCopyInput';
  28. import {t, tct} from 'sentry/locale';
  29. import {space} from 'sentry/styles/space';
  30. import {trackAnalytics} from 'sentry/utils/analytics';
  31. type Params = DocsParams;
  32. const getInstallConfig = () => [
  33. {
  34. description: tct(
  35. 'Configure your app automatically with the [wizardLink:Sentry wizard].',
  36. {
  37. wizardLink: (
  38. <ExternalLink href="https://docs.sentry.io/platforms/javascript/guides/nextjs/#install" />
  39. ),
  40. }
  41. ),
  42. language: 'bash',
  43. code: `npx @sentry/wizard@latest -i nextjs`,
  44. },
  45. ];
  46. const getManualInstallConfig = () => [
  47. {
  48. language: 'bash',
  49. code: [
  50. {
  51. label: 'npm',
  52. value: 'npm',
  53. language: 'bash',
  54. code: 'npm install --save @sentry/nextjs',
  55. },
  56. {
  57. label: 'yarn',
  58. value: 'yarn',
  59. language: 'bash',
  60. code: 'yarn add @sentry/nextjs',
  61. },
  62. ],
  63. },
  64. ];
  65. const onboarding: OnboardingConfig = {
  66. install: (params: Params) => [
  67. {
  68. type: StepType.INSTALL,
  69. configurations: getInstallConfig(),
  70. additionalInfo: (
  71. <Fragment>
  72. {t(
  73. 'The Sentry wizard will automatically patch your application to configure the Sentry SDK:'
  74. )}
  75. <List symbol="bullet">
  76. <ListItem>
  77. {tct(
  78. 'Create [serverCode:sentry.server.config.js], [clientCode:sentry.client.config.js] and [edgeCode:sentry.edge.config.js] with the default [sentryInitCode:Sentry.init].',
  79. {
  80. clientCode: <code />,
  81. serverCode: <code />,
  82. edgeCode: <code />,
  83. sentryInitCode: <code />,
  84. }
  85. )}
  86. </ListItem>
  87. <ListItem>
  88. {tct(
  89. 'Create or update the Next.js instrumentation file [instrumentationCode:instrumentation.ts] to initialize the SDK with the configuration files added in the previous step.',
  90. {
  91. instrumentationCode: <code />,
  92. }
  93. )}
  94. </ListItem>
  95. <ListItem>
  96. {tct(
  97. 'Create or update your Next.js config [nextConfig:next.config.js] with the default Sentry configuration.',
  98. {
  99. nextConfig: <code />,
  100. }
  101. )}
  102. </ListItem>
  103. <ListItem>
  104. {tct(
  105. 'Create a [bundlerPluginsEnv:.env.sentry-build-plugin] with an auth token (which is used to upload source maps when building the application).',
  106. {
  107. bundlerPluginsEnv: <code />,
  108. }
  109. )}
  110. </ListItem>
  111. <ListItem>
  112. {t('Add an example page to your app to verify your Sentry setup.')}
  113. </ListItem>
  114. </List>
  115. <br />
  116. <ManualSetupTitle>{t('Manual Setup')}</ManualSetupTitle>
  117. <p>
  118. {tct(
  119. 'Alternatively, you can also [manualSetupLink:set up the SDK manually].',
  120. {
  121. manualSetupLink: (
  122. <ExternalLink href="https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/" />
  123. ),
  124. }
  125. )}
  126. </p>
  127. <br />
  128. <DSNText>
  129. <p>
  130. {tct(
  131. "If you already have the configuration for Sentry in your application, and just need this project's ([projectSlug]) DSN, you can find it below:",
  132. {
  133. projectSlug: <code>{params.projectSlug}</code>,
  134. }
  135. )}
  136. </p>
  137. </DSNText>
  138. {params.organization && (
  139. <TextCopyInput
  140. onCopy={() =>
  141. trackAnalytics('onboarding.nextjs-dsn-copied', {
  142. organization: params.organization,
  143. })
  144. }
  145. >
  146. {params.dsn}
  147. </TextCopyInput>
  148. )}
  149. </Fragment>
  150. ),
  151. },
  152. ],
  153. configure: () => [],
  154. verify: () => [],
  155. };
  156. const replayOnboarding: OnboardingConfig = {
  157. install: () => [{type: StepType.INSTALL, configurations: getInstallConfig()}],
  158. configure: (params: Params) => [
  159. {
  160. type: StepType.CONFIGURE,
  161. description: getReplayConfigureDescription({
  162. link: 'https://docs.sentry.io/platforms/javascript/guides/nextjs/session-replay/',
  163. }),
  164. configurations: [
  165. {
  166. code: [
  167. {
  168. label: 'JavaScript',
  169. value: 'javascript',
  170. language: 'javascript',
  171. code: getReplaySDKSetupSnippet({
  172. importStatement: `import * as Sentry from "@sentry/nextjs";`,
  173. dsn: params.dsn,
  174. mask: params.replayOptions?.mask,
  175. block: params.replayOptions?.block,
  176. }),
  177. },
  178. ],
  179. },
  180. ],
  181. additionalInfo: (
  182. <Fragment>
  183. <TracePropagationMessage />
  184. {tct(
  185. 'Alert: The Replay integration must be added to your [sentryClient:sentry.client.config.js] file. Adding it to any server-side configuration files (like [instrumentation:instrumentation.ts]) will break your build because the Replay integration depends on Browser APIs.',
  186. {
  187. sentryClient: <code />,
  188. instrumentation: <code />,
  189. }
  190. )}
  191. </Fragment>
  192. ),
  193. },
  194. ],
  195. verify: () => [],
  196. nextSteps: () => [],
  197. };
  198. const feedbackOnboarding: OnboardingConfig = {
  199. install: () => [
  200. {
  201. type: StepType.INSTALL,
  202. description: tct(
  203. 'For the User Feedback integration to work, you must have the Sentry browser SDK package, or an equivalent framework SDK (e.g. [code:@sentry/nextjs]) installed, minimum version 7.85.0.',
  204. {
  205. code: <code />,
  206. }
  207. ),
  208. configurations: getInstallConfig(),
  209. },
  210. ],
  211. configure: (params: Params) => [
  212. {
  213. type: StepType.CONFIGURE,
  214. description: getFeedbackConfigureDescription({
  215. linkConfig:
  216. 'https://docs.sentry.io/platforms/javascript/guides/nextjs/user-feedback/configuration/',
  217. linkButton:
  218. 'https://docs.sentry.io/platforms/javascript/guides/nextjs/user-feedback/configuration/#bring-your-own-button',
  219. }),
  220. configurations: [
  221. {
  222. code: [
  223. {
  224. label: 'JavaScript',
  225. value: 'javascript',
  226. language: 'javascript',
  227. code: getFeedbackSDKSetupSnippet({
  228. importStatement: `import * as Sentry from "@sentry/nextjs";`,
  229. dsn: params.dsn,
  230. feedbackOptions: params.feedbackOptions,
  231. }),
  232. },
  233. ],
  234. },
  235. ],
  236. additionalInfo: (
  237. <Fragment>
  238. {tct(
  239. 'Alert: The User Feedback integration must be added to your [sentryClient:sentry.client.config.js] file. Adding it to any server-side configuration files (like [instrumentation:instrumentation.ts]) will break your build because the Replay integration depends on Browser APIs.',
  240. {
  241. sentryClient: <code />,
  242. instrumentation: <code />,
  243. }
  244. )}
  245. {crashReportCallout({
  246. link: 'https://docs.sentry.io/platforms/javascript/guides/nextjs/user-feedback/#crash-report-modal',
  247. })}
  248. </Fragment>
  249. ),
  250. },
  251. ],
  252. verify: () => [],
  253. nextSteps: () => [],
  254. };
  255. const crashReportOnboarding: OnboardingConfig = {
  256. introduction: () => getCrashReportModalIntroduction(),
  257. install: (params: Params) => getCrashReportJavaScriptInstallStep(params),
  258. configure: () => [
  259. {
  260. type: StepType.CONFIGURE,
  261. description: getCrashReportModalConfigDescription({
  262. link: 'https://docs.sentry.io/platforms/javascript/guides/nextjs/user-feedback/configuration/#crash-report-modal',
  263. }),
  264. additionalInfo: widgetCallout({
  265. link: 'https://docs.sentry.io/platforms/javascript/guides/nextjs/user-feedback/#user-feedback-widget',
  266. }),
  267. },
  268. ],
  269. verify: () => [],
  270. nextSteps: () => [],
  271. };
  272. const docs: Docs = {
  273. onboarding,
  274. feedbackOnboardingNpm: feedbackOnboarding,
  275. replayOnboardingNpm: replayOnboarding,
  276. customMetricsOnboarding: getJSMetricsOnboarding({
  277. getInstallConfig: getManualInstallConfig,
  278. }),
  279. crashReportOnboarding,
  280. };
  281. export default docs;
  282. const DSNText = styled('div')`
  283. margin-bottom: ${space(0.5)};
  284. `;
  285. const ManualSetupTitle = styled('p')`
  286. font-size: ${p => p.theme.fontSizeLarge};
  287. font-weight: ${p => p.theme.fontWeightBold};
  288. `;