Skip to content

Commit 18deb3e

Browse files
committed
fix(sveltekit): Avoid loading vite config to determine source maps setting
1 parent 136370c commit 18deb3e

File tree

2 files changed

+49
-73
lines changed

2 files changed

+49
-73
lines changed

packages/browser/test/loader.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@
9797
console.error(o_O);
9898
}
9999
});
100-
101100
_currentScriptTag.parentNode.insertBefore(_newScriptTag, _currentScriptTag);
102101
}
103102

packages/sveltekit/src/vite/sourceMaps.ts

Lines changed: 49 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,6 @@ type Sorcery = {
2424
load(filepath: string): Promise<Chain>;
2525
};
2626

27-
type GlobalWithSourceMapSetting = typeof globalThis & {
28-
_sentry_sourceMapSetting?: {
29-
updatedSourceMapSetting?: boolean | 'inline' | 'hidden';
30-
previousSourceMapSetting?: UserSourceMapSetting;
31-
};
32-
};
33-
3427
// storing this in the module scope because `makeCustomSentryVitePlugin` is called multiple times
3528
// and we only want to generate a uuid once in case we have to fall back to it.
3629
const releaseName = detectSentryRelease();
@@ -57,8 +50,6 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
5750
const usedAdapter = options?.adapter || 'other';
5851
const adapterOutputDir = await getAdapterOutputDir(svelteConfig, usedAdapter);
5952

60-
const globalWithSourceMapSetting = globalThis as GlobalWithSourceMapSetting;
61-
6253
const defaultPluginOptions: SentryVitePluginOptions = {
6354
release: {
6455
name: releaseName,
@@ -70,61 +61,8 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
7061
},
7162
};
7263

73-
// Including all hidden (`.*`) directories by default so that folders like .vercel,
74-
// .netlify, etc are also cleaned up. Additionally, we include the adapter output
75-
// dir which could be a non-hidden directory, like `build` for the Node adapter.
76-
const defaultFileDeletionGlob = ['./.*/**/*.map', `./${adapterOutputDir}/**/*.map`];
77-
78-
if (!globalWithSourceMapSetting._sentry_sourceMapSetting) {
79-
let configFile: {
80-
path: string;
81-
config: UserConfig;
82-
dependencies: string[];
83-
} | null = null;
84-
85-
try {
86-
// @ts-expect-error - the dynamic import here works fine
87-
const Vite = await import('vite');
88-
configFile = await Vite.loadConfigFromFile({ command: 'build', mode: 'production' });
89-
} catch {
90-
if (options?.debug) {
91-
consoleSandbox(() => {
92-
// eslint-disable-next-line no-console
93-
console.warn(
94-
'[Sentry] Could not import Vite to load your vite config. Please set `build.sourcemap` to `true` or `hidden` to enable source map generation.',
95-
);
96-
});
97-
}
98-
}
99-
100-
if (configFile) {
101-
globalWithSourceMapSetting._sentry_sourceMapSetting = getUpdatedSourceMapSetting(configFile.config);
102-
} else {
103-
if (options?.debug) {
104-
consoleSandbox(() => {
105-
// eslint-disable-next-line no-console
106-
console.warn(
107-
'[Sentry] Could not load Vite config with Vite "production" mode. This is needed for Sentry to automatically update source map settings.',
108-
);
109-
});
110-
}
111-
}
112-
113-
if (options?.debug && globalWithSourceMapSetting._sentry_sourceMapSetting?.previousSourceMapSetting === 'unset') {
114-
consoleSandbox(() => {
115-
// eslint-disable-next-line no-console
116-
console.warn(
117-
`[Sentry] Automatically setting \`sourceMapsUploadOptions.sourcemaps.filesToDeleteAfterUpload: [${defaultFileDeletionGlob
118-
.map(file => `"${file}"`)
119-
.join(', ')}]\` to delete generated source maps after they were uploaded to Sentry.`,
120-
);
121-
});
122-
}
123-
}
124-
125-
const shouldDeleteDefaultSourceMaps =
126-
globalWithSourceMapSetting._sentry_sourceMapSetting?.previousSourceMapSetting === 'unset' &&
127-
!options?.sourcemaps?.filesToDeleteAfterUpload;
64+
const { promise: filesToDeleteAfterUpload, resolve: reportFilesToDeleteAfterUpload } =
65+
createFilesToDeleteAfterUploadPromise();
12866

12967
const mergedOptions = {
13068
...defaultPluginOptions,
@@ -135,9 +73,7 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
13573
},
13674
sourcemaps: {
13775
...options?.sourcemaps,
138-
filesToDeleteAfterUpload: shouldDeleteDefaultSourceMaps
139-
? defaultFileDeletionGlob
140-
: options?.sourcemaps?.filesToDeleteAfterUpload,
76+
filesToDeleteAfterUpload,
14177
},
14278
};
14379

@@ -208,24 +144,44 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
208144
config: (config: UserConfig) => {
209145
const settingKey = 'build.sourcemap';
210146

211-
if (globalWithSourceMapSetting._sentry_sourceMapSetting?.previousSourceMapSetting === 'unset') {
147+
const { updatedSourceMapSetting, previousSourceMapSetting } = getUpdatedSourceMapSetting(config);
148+
149+
if (previousSourceMapSetting === 'unset') {
212150
consoleSandbox(() => {
213151
// eslint-disable-next-line no-console
214152
console.log(`[Sentry] Enabled source map generation in the build options with \`${settingKey}: "hidden"\`.`);
215153
});
216154

155+
// Including all hidden (`.*`) directories by default so that folders like .vercel,
156+
// .netlify, etc are also cleaned up. Additionally, we include the adapter output
157+
// dir which could be a non-hidden directory, like `build` for the Node adapter.
158+
const defaultFileDeletionGlob = ['./.*/**/*.map', `./${adapterOutputDir}/**/*.map`];
159+
160+
consoleSandbox(() => {
161+
// eslint-disable-next-line no-console
162+
console.warn(
163+
`[Sentry] Automatically setting \`sourceMapsUploadOptions.sourcemaps.filesToDeleteAfterUpload: [${defaultFileDeletionGlob
164+
.map(file => `"${file}"`)
165+
.join(', ')}]\` to delete generated source maps after they were uploaded to Sentry.`,
166+
);
167+
});
168+
169+
// In case we enabled source map, we also want to delete them.
170+
// So either use the glob(s) that users specified, or the default one!
171+
reportFilesToDeleteAfterUpload(options?.sourcemaps?.filesToDeleteAfterUpload ?? defaultFileDeletionGlob);
172+
217173
return {
218174
...config,
219-
build: { ...config.build, sourcemap: 'hidden' },
175+
build: { ...config.build, sourcemap: updatedSourceMapSetting },
220176
};
221-
} else if (globalWithSourceMapSetting._sentry_sourceMapSetting?.previousSourceMapSetting === 'disabled') {
177+
} else if (previousSourceMapSetting === 'disabled') {
222178
consoleSandbox(() => {
223179
// eslint-disable-next-line no-console
224180
console.warn(
225181
`[Sentry] Parts of source map generation are currently disabled in your Vite configuration (\`${settingKey}: false\`). This setting is either a default setting or was explicitly set in your configuration. Sentry won't override this setting. Without source maps, code snippets on the Sentry Issues page will remain minified. To show unminified code, enable source maps in \`${settingKey}\` (e.g. by setting them to \`hidden\`).`,
226182
);
227183
});
228-
} else if (globalWithSourceMapSetting._sentry_sourceMapSetting?.previousSourceMapSetting === 'enabled') {
184+
} else if (previousSourceMapSetting === 'enabled') {
229185
if (mergedOptions?.debug) {
230186
consoleSandbox(() => {
231187
// eslint-disable-next-line no-console
@@ -236,6 +192,8 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
236192
}
237193
}
238194

195+
reportFilesToDeleteAfterUpload(options?.sourcemaps?.filesToDeleteAfterUpload);
196+
239197
return config;
240198
},
241199
};
@@ -387,7 +345,7 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
387345
const outDir = path.resolve(process.cwd(), adapterOutputDir);
388346
try {
389347
// @ts-expect-error - the writeBundle hook expects two args we can't pass in here (they're only available in `writeBundle`)
390-
await writeBundleFn({ dir: outDir });
348+
await writeBundleFn({ dir: outDir, _sentryFilesToDelete });
391349
} catch (e) {
392350
// eslint-disable-next-line no-console
393351
console.warn('Failed to delete source maps:', e);
@@ -499,3 +457,22 @@ function detectSentryRelease(): string {
499457

500458
return release;
501459
}
460+
461+
/**
462+
* Creates a deferred promise that can be resolved/rejected by calling the
463+
* `resolve` or `reject` function.
464+
* Inspired by: https://stackoverflow.com/a/69027809
465+
*/
466+
function createFilesToDeleteAfterUploadPromise(): {
467+
promise: Promise<string | string[] | undefined>;
468+
resolve: (value: string | string[] | undefined) => void;
469+
reject: (reason?: unknown) => void;
470+
} {
471+
let resolve!: (value: string | string[] | undefined) => void;
472+
let reject!: (reason?: unknown) => void;
473+
const promise = new Promise<string | string[] | undefined>((res, rej) => {
474+
resolve = res;
475+
reject = rej;
476+
});
477+
return { resolve, reject, promise };
478+
}

0 commit comments

Comments
 (0)