Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@sentry/tanstackstart-react": "latest || *",
"@tanstack/react-start": "^1.136.0",
"@tanstack/react-router": "^1.136.0",
"nitro": "latest",
"react": "^19.2.0",
"react-dom": "^19.2.0"
},
Expand All @@ -29,7 +30,6 @@
"typescript": "^5.9.0",
"vite": "7.2.0",
"vite-tsconfig-paths": "^5.1.4",
"nitro": "^3.0.0",
"@playwright/test": "~1.56.0",
"@sentry-internal/test-utils": "link:../../../test-utils"
},
Expand Down
23 changes: 23 additions & 0 deletions packages/tanstackstart-react/src/vite/nitro.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { Plugin, UserConfig } from 'vite';

/**
* Creates a Vite plugin that configures Nitro to treat `@sentry/*` packages as external dependencies.
*
* We need this to prevent build issues we were seeing with recent versions of Nitro.
*/
export function makeNitroSentryExternalPlugin(): Plugin {
return {
name: 'sentry-tanstack-start-nitro-external',
enforce: 'pre',
config() {
// The `nitro` property is not part of Vite's UserConfig type but is read by the Nitro Vite plugin
return {
nitro: {
rollupConfig: {
external: [/^@sentry\//],
},
},
} as UserConfig;
},
};
}
3 changes: 2 additions & 1 deletion packages/tanstackstart-react/src/vite/sentryTanstackStart.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { BuildTimeOptionsBase } from '@sentry/core';
import type { Plugin } from 'vite';
import { makeAutoInstrumentMiddlewarePlugin } from './autoInstrumentMiddleware';
import { makeNitroSentryExternalPlugin } from './nitro';
import { makeAddSentryVitePlugin, makeEnableSourceMapsVitePlugin } from './sourceMaps';

/**
Expand Down Expand Up @@ -51,7 +52,7 @@ export function sentryTanstackStart(options: SentryTanstackStartOptions = {}): P
return [];
}

const plugins: Plugin[] = [...makeAddSentryVitePlugin(options)];
const plugins: Plugin[] = [makeNitroSentryExternalPlugin(), ...makeAddSentryVitePlugin(options)];

// middleware auto-instrumentation
if (options.autoInstrumentMiddleware !== false) {
Expand Down
17 changes: 17 additions & 0 deletions packages/tanstackstart-react/test/vite/nitro.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { describe, expect, it } from 'vitest';
import { makeNitroSentryExternalPlugin } from '../../src/vite/nitro';

describe('makeNitroSentryExternalPlugin()', () => {
it('returns nitro config to externalize @sentry/* packages', () => {
const plugin = makeNitroSentryExternalPlugin();
const config = (plugin.config as () => unknown)();

expect(config).toEqual({
nitro: {
rollupConfig: {
external: [/^@sentry\//],
},
},
});
});
});
39 changes: 32 additions & 7 deletions packages/tanstackstart-react/test/vite/sentryTanstackStart.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ const mockMiddlewarePlugin: Plugin = {
transform: vi.fn(),
};

const expectedNitroExternalPlugin = expect.objectContaining({
name: 'sentry-tanstack-start-nitro-external',
config: expect.any(Function),
});

vi.mock('../../src/vite/sourceMaps', () => ({
makeAddSentryVitePlugin: vi.fn(() => [mockSourceMapsConfigPlugin, mockSentryVitePlugin]),
makeEnableSourceMapsVitePlugin: vi.fn(() => [mockEnableSourceMapsPlugin]),
Expand All @@ -51,7 +56,12 @@ describe('sentryTanstackStart()', () => {
it('returns source maps plugins in production mode', () => {
const plugins = sentryTanstackStart({ autoInstrumentMiddleware: false });

expect(plugins).toEqual([mockSourceMapsConfigPlugin, mockSentryVitePlugin, mockEnableSourceMapsPlugin]);
expect(plugins).toEqual([
expectedNitroExternalPlugin,
mockSourceMapsConfigPlugin,
mockSentryVitePlugin,
mockEnableSourceMapsPlugin,
]);
});

it('returns no plugins in development mode', () => {
Expand All @@ -68,7 +78,7 @@ describe('sentryTanstackStart()', () => {
sourcemaps: { disable: true },
});

expect(plugins).toEqual([mockSourceMapsConfigPlugin, mockSentryVitePlugin]);
expect(plugins).toEqual([expectedNitroExternalPlugin, mockSourceMapsConfigPlugin, mockSentryVitePlugin]);
});

it('returns Sentry Vite plugins but not enable source maps plugin when sourcemaps.disable is "disable-upload"', () => {
Expand All @@ -77,7 +87,7 @@ describe('sentryTanstackStart()', () => {
sourcemaps: { disable: 'disable-upload' },
});

expect(plugins).toEqual([mockSourceMapsConfigPlugin, mockSentryVitePlugin]);
expect(plugins).toEqual([expectedNitroExternalPlugin, mockSourceMapsConfigPlugin, mockSentryVitePlugin]);
});

it('returns Sentry Vite plugins and enable source maps plugin when sourcemaps.disable is false', () => {
Expand All @@ -86,15 +96,25 @@ describe('sentryTanstackStart()', () => {
sourcemaps: { disable: false },
});

expect(plugins).toEqual([mockSourceMapsConfigPlugin, mockSentryVitePlugin, mockEnableSourceMapsPlugin]);
expect(plugins).toEqual([
expectedNitroExternalPlugin,
mockSourceMapsConfigPlugin,
mockSentryVitePlugin,
mockEnableSourceMapsPlugin,
]);
});
});

describe('middleware auto-instrumentation', () => {
it('includes middleware plugin by default', () => {
const plugins = sentryTanstackStart({ sourcemaps: { disable: true } });

expect(plugins).toEqual([mockSourceMapsConfigPlugin, mockSentryVitePlugin, mockMiddlewarePlugin]);
expect(plugins).toEqual([
expectedNitroExternalPlugin,
mockSourceMapsConfigPlugin,
mockSentryVitePlugin,
mockMiddlewarePlugin,
]);
});

it('includes middleware plugin when autoInstrumentMiddleware is true', () => {
Expand All @@ -103,7 +123,12 @@ describe('sentryTanstackStart()', () => {
sourcemaps: { disable: true },
});

expect(plugins).toEqual([mockSourceMapsConfigPlugin, mockSentryVitePlugin, mockMiddlewarePlugin]);
expect(plugins).toEqual([
expectedNitroExternalPlugin,
mockSourceMapsConfigPlugin,
mockSentryVitePlugin,
mockMiddlewarePlugin,
]);
});

it('does not include middleware plugin when autoInstrumentMiddleware is false', () => {
Expand All @@ -112,7 +137,7 @@ describe('sentryTanstackStart()', () => {
sourcemaps: { disable: true },
});

expect(plugins).toEqual([mockSourceMapsConfigPlugin, mockSentryVitePlugin]);
expect(plugins).toEqual([expectedNitroExternalPlugin, mockSourceMapsConfigPlugin, mockSentryVitePlugin]);
});

it('passes correct options to makeAutoInstrumentMiddlewarePlugin', () => {
Expand Down
Loading