nextjs.tsx 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  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 [clientCode:sentry.client.config.js] and [serverCode:sentry.server.config.js] with the default [sentryInitCode:Sentry.init].',
  79. {
  80. clientCode: <code />,
  81. serverCode: <code />,
  82. sentryInitCode: <code />,
  83. }
  84. )}
  85. </ListItem>
  86. <ListItem>
  87. {tct(
  88. 'Create or update your Next.js config [nextConfig:next.config.js] with the default Sentry configuration.',
  89. {
  90. nextConfig: <code />,
  91. }
  92. )}
  93. </ListItem>
  94. <ListItem>
  95. {tct(
  96. 'Create [sentryClircCode:.sentryclirc] and [sentryPropertiesCode:sentry.properties] files with configuration for sentry-cli (which is used when automatically uploading source maps).',
  97. {
  98. sentryClircCode: <code />,
  99. sentryPropertiesCode: <code />,
  100. }
  101. )}
  102. </ListItem>
  103. <ListItem>
  104. {tct('Add an example page to your app to verify your Sentry setup.', {
  105. sentryClircCode: <code />,
  106. })}
  107. </ListItem>
  108. </List>
  109. <br />
  110. <ManualSetupTitle>{t('Manual Setup')}</ManualSetupTitle>
  111. <p>
  112. {tct(
  113. 'Alternatively, you can also [manualSetupLink:set up the SDK manually].',
  114. {
  115. manualSetupLink: (
  116. <ExternalLink href="https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/" />
  117. ),
  118. }
  119. )}
  120. </p>
  121. <br />
  122. <DSNText>
  123. <p>
  124. {tct(
  125. "If you already have the configuration for Sentry in your application, and just need this project's ([projectSlug]) DSN, you can find it below:",
  126. {
  127. projectSlug: <code>{params.projectSlug}</code>,
  128. }
  129. )}
  130. </p>
  131. </DSNText>
  132. {params.organization && (
  133. <TextCopyInput
  134. onCopy={() =>
  135. trackAnalytics('onboarding.nextjs-dsn-copied', {
  136. organization: params.organization,
  137. })
  138. }
  139. >
  140. {params.dsn}
  141. </TextCopyInput>
  142. )}
  143. </Fragment>
  144. ),
  145. },
  146. ],
  147. configure: () => [],
  148. verify: () => [],
  149. };
  150. const replayOnboarding: OnboardingConfig = {
  151. install: () => [{type: StepType.INSTALL, configurations: getInstallConfig()}],
  152. configure: (params: Params) => [
  153. {
  154. type: StepType.CONFIGURE,
  155. description: getReplayConfigureDescription({
  156. link: 'https://docs.sentry.io/platforms/javascript/guides/nextjs/session-replay/',
  157. }),
  158. configurations: [
  159. {
  160. code: [
  161. {
  162. label: 'JavaScript',
  163. value: 'javascript',
  164. language: 'javascript',
  165. code: getReplaySDKSetupSnippet({
  166. importStatement: `import * as Sentry from "@sentry/nextjs";`,
  167. dsn: params.dsn,
  168. mask: params.replayOptions?.mask,
  169. block: params.replayOptions?.block,
  170. }),
  171. },
  172. ],
  173. },
  174. ],
  175. additionalInfo: (
  176. <Fragment>
  177. <TracePropagationMessage />
  178. {tct(
  179. 'Alert: The Replay integration must be added to your [sentryClient:sentry.client.config.js] file. Adding it into [sentryServer:sentry.server.config.js] or [sentryEdge:sentry.edge.config.js] may break your build.',
  180. {sentryClient: <code />, sentryServer: <code />, sentryEdge: <code />}
  181. )}
  182. </Fragment>
  183. ),
  184. },
  185. ],
  186. verify: () => [],
  187. nextSteps: () => [],
  188. };
  189. const feedbackOnboarding: OnboardingConfig = {
  190. install: () => [
  191. {
  192. type: StepType.INSTALL,
  193. description: tct(
  194. '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.',
  195. {
  196. code: <code />,
  197. }
  198. ),
  199. configurations: getInstallConfig(),
  200. },
  201. ],
  202. configure: (params: Params) => [
  203. {
  204. type: StepType.CONFIGURE,
  205. description: getFeedbackConfigureDescription({
  206. linkConfig:
  207. 'https://docs.sentry.io/platforms/javascript/guides/nextjs/user-feedback/configuration/',
  208. linkButton:
  209. 'https://docs.sentry.io/platforms/javascript/guides/nextjs/user-feedback/configuration/#bring-your-own-button',
  210. }),
  211. configurations: [
  212. {
  213. code: [
  214. {
  215. label: 'JavaScript',
  216. value: 'javascript',
  217. language: 'javascript',
  218. code: getFeedbackSDKSetupSnippet({
  219. importStatement: `import * as Sentry from "@sentry/nextjs";`,
  220. dsn: params.dsn,
  221. feedbackOptions: params.feedbackOptions,
  222. }),
  223. },
  224. ],
  225. },
  226. ],
  227. additionalInfo: crashReportCallout({
  228. link: 'https://docs.sentry.io/platforms/javascript/guides/nextjs/user-feedback/#crash-report-modal',
  229. }),
  230. },
  231. ],
  232. verify: () => [],
  233. nextSteps: () => [],
  234. };
  235. const crashReportOnboarding: OnboardingConfig = {
  236. introduction: () => getCrashReportModalIntroduction(),
  237. install: (params: Params) => getCrashReportJavaScriptInstallStep(params),
  238. configure: () => [
  239. {
  240. type: StepType.CONFIGURE,
  241. description: getCrashReportModalConfigDescription({
  242. link: 'https://docs.sentry.io/platforms/javascript/guides/nextjs/user-feedback/configuration/#crash-report-modal',
  243. }),
  244. additionalInfo: widgetCallout({
  245. link: 'https://docs.sentry.io/platforms/javascript/guides/nextjs/user-feedback/#user-feedback-widget',
  246. }),
  247. },
  248. ],
  249. verify: () => [],
  250. nextSteps: () => [],
  251. };
  252. const docs: Docs = {
  253. onboarding,
  254. feedbackOnboardingNpm: feedbackOnboarding,
  255. replayOnboardingNpm: replayOnboarding,
  256. customMetricsOnboarding: getJSMetricsOnboarding({
  257. getInstallConfig: getManualInstallConfig,
  258. }),
  259. crashReportOnboarding,
  260. };
  261. export default docs;
  262. const DSNText = styled('div')`
  263. margin-bottom: ${space(0.5)};
  264. `;
  265. const ManualSetupTitle = styled('p')`
  266. font-size: ${p => p.theme.fontSizeLarge};
  267. font-weight: bold;
  268. `;