Skip to content

Commit ecc95e7

Browse files
authored
feat(nuxt): Inject sentry config with Nuxt addPluginTemplate (#12760)
1 parent a2dcb28 commit ecc95e7

File tree

9 files changed

+89
-179
lines changed

9 files changed

+89
-179
lines changed

packages/nuxt/README.md

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,25 +62,31 @@ export default defineNuxtConfig({
6262
});
6363
```
6464

65-
2. Add a `sentry.client.config.(js|ts)` file to the root of your project:
65+
### 3. Client-side setup
66+
67+
Add a `sentry.client.config.(js|ts)` file to the root of your project:
6668

6769
```javascript
6870
import * as Sentry from '@sentry/nuxt';
6971

70-
if (!import.meta.env.SSR) {
71-
Sentry.init({
72-
dsn: env.DSN,
73-
replaysSessionSampleRate: 0.1,
74-
replaysOnErrorSampleRate: 1.0,
75-
});
76-
}
72+
Sentry.init({
73+
dsn: env.DSN,
74+
});
7775
```
7876

79-
### 3. Server-side Setup
77+
### 4. Server-side setup
78+
79+
Add a `sentry.server.config.(js|ts)` file to the root of your project:
80+
81+
```javascript
82+
import * as Sentry from '@sentry/nuxt';
8083

81-
todo: add server-side setup
84+
Sentry.init({
85+
dsn: env.DSN,
86+
});
87+
```
8288

83-
### 4. Vite Setup
89+
### 5. Vite Setup
8490

8591
todo: add vite setup
8692

packages/nuxt/rollup.npm.config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ import { makeBaseNPMConfig, makeNPMConfigVariants } from '@sentry-internal/rollu
22

33
export default makeNPMConfigVariants(
44
makeBaseNPMConfig({
5-
entrypoints: ['src/index.client.ts', 'src/client/index.ts'],
5+
entrypoints: ['src/index.server.ts', 'src/index.client.ts', 'src/client/index.ts', 'src/server/index.ts'],
66
}),
77
);

packages/nuxt/src/common/snippets.ts

Lines changed: 0 additions & 47 deletions
This file was deleted.

packages/nuxt/src/index.server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export {};
1+
export * from './server';

packages/nuxt/src/index.types.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,17 @@
1-
export * from './client';
1+
import type { Integration, Options, StackParser } from '@sentry/types';
2+
import type * as clientSdk from './index.client';
3+
import type * as serverSdk from './index.server';
4+
5+
// We export everything from both the client part of the SDK and from the server part. Some of the exports collide,
6+
// which is not allowed, unless we re-export the colliding exports in this file - which we do below.
7+
export * from './index.client';
8+
export * from './index.server';
9+
10+
// re-export colliding types
11+
export declare function init(options: Options | clientSdk.BrowserOptions | serverSdk.NodeOptions): void;
12+
export declare const linkedErrorsIntegration: typeof clientSdk.linkedErrorsIntegration;
13+
export declare const contextLinesIntegration: typeof clientSdk.contextLinesIntegration;
14+
export declare const getDefaultIntegrations: (options: Options) => Integration[];
15+
export declare const defaultStackParser: StackParser;
16+
export declare const continueTrace: typeof clientSdk.continueTrace;
17+
export declare const metrics: typeof clientSdk.metrics & typeof serverSdk.metrics;

packages/nuxt/src/module.ts

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import * as fs from 'fs';
22
import * as path from 'path';
3-
import { type Resolver, addPlugin, createResolver, defineNuxtModule } from '@nuxt/kit';
4-
import { addImportStatement, buildSdkInitFileImportSnippet } from './common/snippets';
3+
import { addPlugin, addPluginTemplate, createResolver, defineNuxtModule } from '@nuxt/kit';
54
import type { SentryNuxtOptions } from './common/types';
65

76
export type ModuleOptions = SentryNuxtOptions;
@@ -16,34 +15,46 @@ export default defineNuxtModule<ModuleOptions>({
1615
},
1716
defaults: {},
1817
setup(_moduleOptions, nuxt) {
19-
const resolver: Resolver = createResolver(import.meta.url);
20-
21-
const pathToClientInit = findDefaultSdkInitFile('client');
22-
23-
if (pathToClientInit) {
24-
nuxt.hook('app:templates', nuxtApp => {
25-
if (nuxtApp.rootComponent) {
26-
try {
27-
addImportStatement(nuxtApp.rootComponent, buildSdkInitFileImportSnippet(pathToClientInit));
28-
} catch (err) {
29-
// eslint-disable-next-line no-console
30-
console.error(`[Sentry] Could not add import statement to root component. ${err}`);
31-
}
32-
}
18+
const moduleDirResolver = createResolver(import.meta.url);
19+
const buildDirResolver = createResolver(nuxt.options.buildDir);
20+
21+
const clientConfigFile = findDefaultSdkInitFile('client');
22+
23+
if (clientConfigFile) {
24+
// Inject the client-side Sentry config file with a side effect import
25+
addPluginTemplate({
26+
mode: 'client',
27+
filename: 'sentry-client-config.mjs',
28+
getContents: () =>
29+
`import "${buildDirResolver.resolve(`/${clientConfigFile}`)}"\n` +
30+
'export default defineNuxtPlugin(() => {})',
3331
});
32+
33+
addPlugin({ src: moduleDirResolver.resolve('./runtime/plugins/sentry.client'), mode: 'client' });
3434
}
3535

36-
if (resolver) {
37-
addPlugin(resolver.resolve('./runtime/plugins/sentry.client'));
36+
const serverConfigFile = findDefaultSdkInitFile('server');
37+
38+
if (serverConfigFile) {
39+
// Inject the server-side Sentry config file with a side effect import
40+
addPluginTemplate({
41+
mode: 'server',
42+
filename: 'sentry-server-config.mjs',
43+
getContents: () =>
44+
`import "${buildDirResolver.resolve(`/${serverConfigFile}`)}"\n` +
45+
'export default defineNuxtPlugin(() => {})',
46+
});
3847
}
3948
},
4049
});
4150

42-
function findDefaultSdkInitFile(type: /* 'server' | */ 'client'): string | undefined {
51+
function findDefaultSdkInitFile(type: 'server' | 'client'): string | undefined {
4352
const possibleFileExtensions = ['ts', 'js', 'mjs', 'cjs', 'mts', 'cts'];
4453

4554
const cwd = process.cwd();
46-
return possibleFileExtensions
55+
const filePath = possibleFileExtensions
4756
.map(e => path.resolve(path.join(cwd, `sentry.${type}.config.${e}`)))
4857
.find(filename => fs.existsSync(filename));
58+
59+
return filePath ? path.basename(filePath) : undefined;
4960
}

packages/nuxt/src/server/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from '@sentry/node';
2+
3+
export { init } from './sdk';

packages/nuxt/src/server/sdk.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { applySdkMetadata } from '@sentry/core';
2+
import { init as initNode } from '@sentry/node';
3+
import type { Client } from '@sentry/types';
4+
import type { SentryNuxtOptions } from '../common/types';
5+
6+
/**
7+
* Initializes the server-side of the Nuxt SDK
8+
*
9+
* @param options Configuration options for the SDK.
10+
*/
11+
export function init(options: SentryNuxtOptions): Client | undefined {
12+
const sentryOptions = {
13+
...options,
14+
};
15+
16+
applySdkMetadata(sentryOptions, 'nuxt', ['nuxt', 'node']);
17+
18+
return initNode(sentryOptions);
19+
}

packages/nuxt/test/common/snippets.test.ts

Lines changed: 0 additions & 98 deletions
This file was deleted.

0 commit comments

Comments
 (0)