nextjs.tsx 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  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 = ({isSelfHosted, urlPrefix}: Params) => {
  33. const urlParam = !isSelfHosted && urlPrefix ? `--url ${urlPrefix}` : '';
  34. return [
  35. {
  36. description: tct(
  37. 'Configure your app automatically with the [wizardLink:Sentry wizard].',
  38. {
  39. wizardLink: (
  40. <ExternalLink href="https://docs.sentry.io/platforms/javascript/guides/nextjs/#install" />
  41. ),
  42. }
  43. ),
  44. language: 'bash',
  45. code: `npx @sentry/wizard@latest -i nextjs ${urlParam}`,
  46. },
  47. ];
  48. };
  49. const getManualInstallConfig = () => [
  50. {
  51. language: 'bash',
  52. code: [
  53. {
  54. label: 'npm',
  55. value: 'npm',
  56. language: 'bash',
  57. code: 'npm install --save @sentry/nextjs',
  58. },
  59. {
  60. label: 'yarn',
  61. value: 'yarn',
  62. language: 'bash',
  63. code: 'yarn add @sentry/nextjs',
  64. },
  65. ],
  66. },
  67. ];
  68. const onboarding: OnboardingConfig = {
  69. install: (params: Params) => [
  70. {
  71. type: StepType.INSTALL,
  72. configurations: getInstallConfig(params),
  73. additionalInfo: (
  74. <Fragment>
  75. {t(
  76. 'The Sentry wizard will automatically patch your application to configure the Sentry SDK:'
  77. )}
  78. <List symbol="bullet">
  79. <ListItem>
  80. {tct(
  81. 'Create [code:sentry.server.config.js], [code:sentry.client.config.js] and [code:sentry.edge.config.js] with the default [code:Sentry.init].',
  82. {
  83. code: <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.public}
  147. </TextCopyInput>
  148. )}
  149. </Fragment>
  150. ),
  151. },
  152. ],
  153. configure: () => [],
  154. verify: () => [],
  155. };
  156. const replayOnboarding: OnboardingConfig = {
  157. install: (params: Params) => [
  158. {type: StepType.INSTALL, configurations: getInstallConfig(params)},
  159. ],
  160. configure: (params: Params) => [
  161. {
  162. type: StepType.CONFIGURE,
  163. description: getReplayConfigureDescription({
  164. link: 'https://docs.sentry.io/platforms/javascript/guides/nextjs/session-replay/',
  165. }),
  166. configurations: [
  167. {
  168. code: [
  169. {
  170. label: 'sentry.client.config.js',
  171. value: 'javascript',
  172. language: 'javascript',
  173. code: getReplaySDKSetupSnippet({
  174. importStatement: `import * as Sentry from "@sentry/nextjs";`,
  175. dsn: params.dsn.public,
  176. mask: params.replayOptions?.mask,
  177. block: params.replayOptions?.block,
  178. }),
  179. },
  180. ],
  181. },
  182. ],
  183. additionalInfo: (
  184. <Fragment>
  185. <TracePropagationMessage />
  186. {tct(
  187. 'Note: The Replay integration only needs to be added to your [code:sentry.client.config.js] file. Adding it to any server-side configuration files (like [code:instrumentation.ts]) will break your build because the Replay integration depends on Browser APIs.',
  188. {
  189. code: <code />,
  190. }
  191. )}
  192. </Fragment>
  193. ),
  194. },
  195. ],
  196. verify: () => [],
  197. nextSteps: () => [],
  198. };
  199. const feedbackOnboarding: OnboardingConfig = {
  200. install: (params: Params) => [
  201. {
  202. type: StepType.INSTALL,
  203. description: tct(
  204. '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.',
  205. {
  206. code: <code />,
  207. }
  208. ),
  209. configurations: getInstallConfig(params),
  210. },
  211. ],
  212. configure: (params: Params) => [
  213. {
  214. type: StepType.CONFIGURE,
  215. description: getFeedbackConfigureDescription({
  216. linkConfig:
  217. 'https://docs.sentry.io/platforms/javascript/guides/nextjs/user-feedback/configuration/',
  218. linkButton:
  219. 'https://docs.sentry.io/platforms/javascript/guides/nextjs/user-feedback/configuration/#bring-your-own-button',
  220. }),
  221. configurations: [
  222. {
  223. code: [
  224. {
  225. label: 'sentry.client.config.js',
  226. value: 'javascript',
  227. language: 'javascript',
  228. code: getFeedbackSDKSetupSnippet({
  229. importStatement: `import * as Sentry from "@sentry/nextjs";`,
  230. dsn: params.dsn.public,
  231. feedbackOptions: params.feedbackOptions,
  232. }),
  233. },
  234. ],
  235. },
  236. ],
  237. additionalInfo: (
  238. <AdditionalInfoWrapper>
  239. <div>
  240. {tct(
  241. 'Note: The User Feedback integration only needs to be added to your [code:sentry.client.config.js] file. Adding it to any server-side configuration files (like [code:instrumentation.ts]) will break your build because the Replay integration depends on Browser APIs.',
  242. {
  243. code: <code />,
  244. }
  245. )}
  246. </div>
  247. <div>
  248. {crashReportCallout({
  249. link: 'https://docs.sentry.io/platforms/javascript/guides/nextjs/user-feedback/#crash-report-modal',
  250. })}
  251. </div>
  252. </AdditionalInfoWrapper>
  253. ),
  254. },
  255. ],
  256. verify: () => [],
  257. nextSteps: () => [],
  258. };
  259. const crashReportOnboarding: OnboardingConfig = {
  260. introduction: () => getCrashReportModalIntroduction(),
  261. install: (params: Params) => getCrashReportJavaScriptInstallStep(params),
  262. configure: () => [
  263. {
  264. type: StepType.CONFIGURE,
  265. description: getCrashReportModalConfigDescription({
  266. link: 'https://docs.sentry.io/platforms/javascript/guides/nextjs/user-feedback/configuration/#crash-report-modal',
  267. }),
  268. additionalInfo: widgetCallout({
  269. link: 'https://docs.sentry.io/platforms/javascript/guides/nextjs/user-feedback/#user-feedback-widget',
  270. }),
  271. },
  272. ],
  273. verify: () => [],
  274. nextSteps: () => [],
  275. };
  276. const docs: Docs = {
  277. onboarding,
  278. feedbackOnboardingNpm: feedbackOnboarding,
  279. replayOnboarding,
  280. customMetricsOnboarding: getJSMetricsOnboarding({
  281. getInstallConfig: getManualInstallConfig,
  282. }),
  283. crashReportOnboarding,
  284. };
  285. export default docs;
  286. const DSNText = styled('div')`
  287. margin-bottom: ${space(0.5)};
  288. `;
  289. const ManualSetupTitle = styled('p')`
  290. font-size: ${p => p.theme.fontSizeLarge};
  291. font-weight: ${p => p.theme.fontWeightBold};
  292. `;
  293. const AdditionalInfoWrapper = styled('div')`
  294. display: flex;
  295. flex-direction: column;
  296. gap: ${space(2)};
  297. `;