Summary
Reduces the base browser CDN bundle (bundle.min.js) gzipped size by ~2.3% (27.85 kB → 27.22 kB, saving 644 bytes gzipped / 3.4 KB raw).
These are safe, behavior-preserving changes found through systematic experimentation across 50 iterations. No public API changes, no removed functionality.
Changes by category
Terser minifier configuration (dev-packages/rollup-utils)
The existing terser config used defaults for compression. Enabling additional safe options yields ~300 bytes gzipped:
compress.passes: 5 — multi-pass optimization finds more dead code
compress.ecma: 2020 — allows modern syntax in output (nullish coalescing, optional chaining)
compress.toplevel: true — better variable inlining within the IIFE
compress.unsafe_arrows: true — converts function to => where this is unused (~1.3 KB raw)
compress.unsafe_methods: true — converts { m: function(){} } to { m(){} }
compress.unsafe_comps / unsafe_math / pure_getters — safe algebraic optimizations
mangle.toplevel: true — mangle top-level variable names within the IIFE scope
Remove redundant iframe-based native fetch check (packages/core/src/utils/supports.ts)
supportsNativeFetch() created a sandboxed iframe to check if fetch is natively implemented — identical logic to getNativeImplementation("fetch") in browser-utils. The function is only called behind a skipNativeFetchCheck guard that is never true in the base CDN bundle, making the iframe code dead weight. Simplified to delegate to _isFetchSupported(). Saves ~200 bytes gzipped.
Slim envelope type-to-category map (packages/core/src/utils/envelope.ts)
The ITEM_TYPE_TO_DATA_CATEGORY_MAP had 18 entries, 7 of which mapped a type to itself (e.g. session: "session"). Replaced with an 11-entry overrides map that falls back to the type name itself. Saves ~38 bytes gzipped.
Shorten default ignore-error patterns (packages/core/src/integrations/eventFilters.ts)
Converted verbose string literals in DEFAULT_IGNORE_ERRORS to shorter regex patterns with the same matching behavior:
"vv().getRestrictions is not a function. (In 'vv()..." → /vv\(\)\.getRestrictions is not a function/
"Can't find variable: _AutofillCallbackHandler" → regex equivalent
- Long CEFSharp
simulateEvent pattern → shorter partial match
Saves ~38 bytes gzipped.
Derive lazy-load integration bundle names (packages/browser/src/utils/lazyLoadIntegration.ts)
The LazyLoadableIntegrations object stored 21 key-value pairs where values were mostly derivable from keys (strip "Integration", lowercase). Replaced with an array of names + a derivation function, with a 3-entry exceptions map for hyphenated bundle names. Also uses string.split(",") for the array. Saves ~30 bytes gzipped.
Consolidate sendSession logic (packages/core/src/client.ts)
sendSession() had duplicate code blocks for session aggregates vs individual sessions, both checking and backfilling release and environment. Unified into a single code path. Saves ~16 bytes gzipped.
Use URLSearchParams in getReportDialogEndpoint (packages/core/src/api.ts)
Replaced manual encodeURIComponent string concatenation with URLSearchParams, which is more concise and already used elsewhere in the same file. Saves ~26 bytes gzipped.
Inline Vue ViewModel checks (packages/core/src/utils/normalize.ts, string.ts)
isVueViewModel() and getVueInternalName() were standalone exported functions only called from two sites (normalize and safeJoin). Inlined the checks directly, allowing tree-shaking to eliminate the standalone functions. Saves ~15 bytes gzipped.
Rename internal sentryWrapped → sW (packages/browser/src/helpers.ts, packages/core/src/utils/stacktrace.ts)
The sentryWrapped function name in the wrap() helper is reserved from mangling because it is matched by a regex in stripSentryFramesAndReverse() for internal frame stripping. Shortened to sW and updated the regex to match both names for backwards compatibility. Saves ~10 bytes gzipped.
Smaller cleanups
DEFAULT_EVENT_TARGET array → comma-separated string.split(",") (51 bytes raw)
getErrorPropertyFromObject — Object.values().find() instead of for...in loop
getOwnProperties — Object.fromEntries(Object.entries()) instead of manual loop
isNativeFunction — simplified regex from exact whitespace match to /\[native code\]/
- Browser extension detection — regex test instead of
array.some() with startsWith
_enhanceEventWithInitialFrame — removed redundant intermediate variable aliases
baggage.ts — .startsWith() instead of .match() for prefix check
- Unused
breadcrumbData variable removed from fetch breadcrumb handler
What was NOT changed
- No public API signatures were modified
- No functionality was removed
- No new dependencies were added
- All changes are in source code or build config — no test modifications
- The
unsafe_* terser options only apply to CDN .min.js bundles (not npm ESM/CJS output)
Co-Authored-By: Claude claude@anthropic.com
Note
The pull request "feat(bundle): Reduce browser CDN bundle size by ~2.3% (-644 bytes gzipped)" was created by @HazAT but did not reference an issue. Therefore this issue was created for better visibility in external tools like Linear.
Summary
Reduces the base browser CDN bundle (
bundle.min.js) gzipped size by ~2.3% (27.85 kB → 27.22 kB, saving 644 bytes gzipped / 3.4 KB raw).These are safe, behavior-preserving changes found through systematic experimentation across 50 iterations. No public API changes, no removed functionality.
Changes by category
Terser minifier configuration (
dev-packages/rollup-utils)The existing terser config used defaults for compression. Enabling additional safe options yields ~300 bytes gzipped:
compress.passes: 5— multi-pass optimization finds more dead codecompress.ecma: 2020— allows modern syntax in output (nullish coalescing, optional chaining)compress.toplevel: true— better variable inlining within the IIFEcompress.unsafe_arrows: true— convertsfunctionto=>wherethisis unused (~1.3 KB raw)compress.unsafe_methods: true— converts{ m: function(){} }to{ m(){} }compress.unsafe_comps / unsafe_math / pure_getters— safe algebraic optimizationsmangle.toplevel: true— mangle top-level variable names within the IIFE scopeRemove redundant iframe-based native fetch check (
packages/core/src/utils/supports.ts)supportsNativeFetch()created a sandboxed iframe to check iffetchis natively implemented — identical logic togetNativeImplementation("fetch")inbrowser-utils. The function is only called behind askipNativeFetchCheckguard that is nevertruein the base CDN bundle, making the iframe code dead weight. Simplified to delegate to_isFetchSupported(). Saves ~200 bytes gzipped.Slim envelope type-to-category map (
packages/core/src/utils/envelope.ts)The
ITEM_TYPE_TO_DATA_CATEGORY_MAPhad 18 entries, 7 of which mapped a type to itself (e.g.session: "session"). Replaced with an 11-entry overrides map that falls back to the type name itself. Saves ~38 bytes gzipped.Shorten default ignore-error patterns (
packages/core/src/integrations/eventFilters.ts)Converted verbose string literals in
DEFAULT_IGNORE_ERRORSto shorter regex patterns with the same matching behavior:"vv().getRestrictions is not a function. (In 'vv()..."→/vv\(\)\.getRestrictions is not a function/"Can't find variable: _AutofillCallbackHandler"→ regex equivalentsimulateEventpattern → shorter partial matchSaves ~38 bytes gzipped.
Derive lazy-load integration bundle names (
packages/browser/src/utils/lazyLoadIntegration.ts)The
LazyLoadableIntegrationsobject stored 21 key-value pairs where values were mostly derivable from keys (strip"Integration", lowercase). Replaced with an array of names + a derivation function, with a 3-entry exceptions map for hyphenated bundle names. Also usesstring.split(",")for the array. Saves ~30 bytes gzipped.Consolidate
sendSessionlogic (packages/core/src/client.ts)sendSession()had duplicate code blocks for session aggregates vs individual sessions, both checking and backfillingreleaseandenvironment. Unified into a single code path. Saves ~16 bytes gzipped.Use
URLSearchParamsingetReportDialogEndpoint(packages/core/src/api.ts)Replaced manual
encodeURIComponentstring concatenation withURLSearchParams, which is more concise and already used elsewhere in the same file. Saves ~26 bytes gzipped.Inline Vue ViewModel checks (
packages/core/src/utils/normalize.ts,string.ts)isVueViewModel()andgetVueInternalName()were standalone exported functions only called from two sites (normalize and safeJoin). Inlined the checks directly, allowing tree-shaking to eliminate the standalone functions. Saves ~15 bytes gzipped.Rename internal
sentryWrapped→sW(packages/browser/src/helpers.ts,packages/core/src/utils/stacktrace.ts)The
sentryWrappedfunction name in thewrap()helper is reserved from mangling because it is matched by a regex instripSentryFramesAndReverse()for internal frame stripping. Shortened tosWand updated the regex to match both names for backwards compatibility. Saves ~10 bytes gzipped.Smaller cleanups
DEFAULT_EVENT_TARGETarray → comma-separatedstring.split(",")(51 bytes raw)getErrorPropertyFromObject—Object.values().find()instead offor...inloopgetOwnProperties—Object.fromEntries(Object.entries())instead of manual loopisNativeFunction— simplified regex from exact whitespace match to/\[native code\]/array.some()withstartsWith_enhanceEventWithInitialFrame— removed redundant intermediate variable aliasesbaggage.ts—.startsWith()instead of.match()for prefix checkbreadcrumbDatavariable removed from fetch breadcrumb handlerWhat was NOT changed
unsafe_*terser options only apply to CDN.min.jsbundles (not npm ESM/CJS output)Co-Authored-By: Claude claude@anthropic.com