Skip to content

feat(nextjs): Remove transpileClientSDK #11978

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 13, 2024
Merged
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
6 changes: 6 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,12 @@ in order to inject the `sentry.(server|edge).config.ts` files into the server-si
possible in the future, we are doing ourselves a favor and doing things the way Next.js intends us to do them -
hopefully reducing bugs and jank.

#### Removal of `transpileClientSDK`

Since we are dropping support for Internet Explorer 11 and other other older browser versions, we are also removing the
`transpileClientSDK` option from the Next.js SDK. If you need to support these browser versions, please configure
Webpack and Next.js to down-compile the SDK.

### Astro SDK

- [Removal of `trackHeaders` option for Astro middleware](./MIGRATION.md#removal-of-trackheaders-option-for-astro-middleware)
Expand Down
6 changes: 0 additions & 6 deletions packages/nextjs/src/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,12 +334,6 @@ export type SentryBuildOptions = {
*/
hideSourceMaps?: boolean;

/**
* Instructs webpack to apply the same transpilation rules to the SDK code as apply to user code. Helpful when
* targeting older browsers which don't support ES6 (or ES6+ features like object spread).
*/
transpileClientSDK?: boolean;

/**
* Include Next.js-internal code and code from dependencies when uploading source maps.
*
Expand Down
96 changes: 0 additions & 96 deletions packages/nextjs/src/config/webpack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import type {
WebpackConfigObject,
WebpackConfigObjectWithModuleRules,
WebpackEntryProperty,
WebpackModuleRule,
} from './types';
import { getWebpackPluginOptions } from './webpackPluginOptions';

Expand Down Expand Up @@ -305,35 +304,6 @@ export function constructWebpackConfigFunction(
}
}

// TODO(v8): Remove this logic since we are deprecating es5.
// The SDK uses syntax (ES6 and ES6+ features like object spread) which isn't supported by older browsers. For users
// who want to support such browsers, `transpileClientSDK` allows them to force the SDK code to go through the same
// transpilation that their code goes through. We don't turn this on by default because it increases bundle size
// fairly massively.
if (!isServer && userSentryOptions?.transpileClientSDK) {
// Find all loaders which apply transpilation to user code
const transpilationRules = findTranspilationRules(newConfig.module?.rules, projectDir);

// For each matching rule, wrap its `exclude` function so that it won't exclude SDK files, even though they're in
// `node_modules` (which is otherwise excluded)
transpilationRules.forEach(rule => {
// All matching rules will necessarily have an `exclude` property, but this keeps TS happy
if (rule.exclude && typeof rule.exclude === 'function') {
const origExclude = rule.exclude;

const newExclude = (filepath: string): boolean => {
if (filepath.includes('@sentry')) {
// `false` in this case means "don't exclude it"
return false;
}
return origExclude(filepath);
};

rule.exclude = newExclude;
}
});
}

if (!isServer) {
// Tell webpack to inject the client config files (containing the client-side `Sentry.init()` call) into the appropriate output
// bundles. Store a separate reference to the original `entry` value to avoid an infinite loop. (If we don't do
Expand Down Expand Up @@ -385,72 +355,6 @@ export function constructWebpackConfigFunction(
};
}

/**
* Determine if this `module.rules` entry is one which will transpile user code
*
* @param rule The rule to check
* @param projectDir The path to the user's project directory
* @returns True if the rule transpiles user code, and false otherwise
*/
function isMatchingRule(rule: WebpackModuleRule, projectDir: string): boolean {
// We want to run our SDK code through the same transformations the user's code will go through, so we test against a
// sample user code path
const samplePagePath = path.resolve(projectDir, 'pageFile.js');
if (rule.test && rule.test instanceof RegExp && !rule.test.test(samplePagePath)) {
return false;
}
if (Array.isArray(rule.include) && !rule.include.includes(projectDir)) {
return false;
}

// `rule.use` can be an object or an array of objects. For simplicity, force it to be an array.
const useEntries = arrayify(rule.use);

// Depending on the version of nextjs we're talking about, the loader which does the transpiling is either
//
// 'next-babel-loader' (next 10),
// '/abs/path/to/node_modules/next/more/path/babel/even/more/path/loader/yet/more/path/index.js' (next 11), or
// 'next-swc-loader' (next 12).
//
// The next 11 option is ugly, but thankfully 'next', 'babel', and 'loader' do appear in it in the same order as in
// 'next-babel-loader', so we can use the same regex to test for both.
if (!useEntries.some(entry => entry?.loader && /next.*(babel|swc).*loader/.test(entry.loader))) {
return false;
}

return true;
}

/**
* Find all rules in `module.rules` which transpile user code.
*
* @param rules The `module.rules` value
* @param projectDir The path to the user's project directory
* @returns An array of matching rules
*/
function findTranspilationRules(rules: WebpackModuleRule[] | undefined, projectDir: string): WebpackModuleRule[] {
if (!rules) {
return [];
}

const matchingRules: WebpackModuleRule[] = [];

// Each entry in `module.rules` is either a rule in and of itself or an object with a `oneOf` property, whose value is
// an array of rules
rules.forEach(rule => {
// if (rule.oneOf) {
if (isMatchingRule(rule, projectDir)) {
matchingRules.push(rule);
} else if (rule.oneOf) {
const matchingOneOfRules = rule.oneOf.filter(oneOfRule => isMatchingRule(oneOfRule, projectDir));
matchingRules.push(...matchingOneOfRules);
// } else if (isMatchingRule(rule, projectDir)) {
}
});

return matchingRules;
}

/**
* Modify the webpack `entry` property so that the code in `sentry.client.config.js` is
* included in the the necessary bundles.
Expand Down
Loading