Sentry-javascript: @sentry/browser size

Created on 20 Sep 2018  ·  69Comments  ·  Source: getsentry/sentry-javascript

Package + Version

  • [x] @sentry/browser
  • [ ] @sentry/node
  • [ ] raven-js
  • [ ] raven-node _(raven for node)_
  • [ ] other:

Version:

4.0.2

Description

The size of the @sentry/browser is more than twice as large as the size of raven-js: 86 kB vs 39 kB (minified). In my opinion, this is definitely a regression and the serious reason not to update to the new version.

Discussion Improvement

Most helpful comment

I think it's fair to first compare the gzip bundle sizes instead of the uncompressed minified file size:

I would argue it is also fair to compare minified sizes as perfomance issues not only arise from downloading javascript, but also from parsing and execution. ~92kb is quite hefty and could add up to 1s of parse time on low-end devices (just for this one library!).

I'm not sure where you take the number of < 1KB for the CDN'ed script from. Could you elaborate? When I open https://browser.sentry-cdn.com/4.0.4/bundle.min.js I see a gzipped size of 22KB.

You should be aware that sentry's sdk is just one of many libraries developers include.

PS: I love sentry, it's been super helpful for us. Web performance is just something I'm passionate about. ;)

All 69 comments

Hey, thanks for bringing this up.
While we understand and generally agree with your concerns about bundle size I think it's fair to first compare the gzip bundle sizes instead of the uncompressed minified file size:

@sentry/browser is 21.3799 KB
raven-js 13.44 KB

Also, while this might not be applicable to everyone, we provide and usually guide people to use our CDN Loader which will set up the SDK for you on your website.

see : https://docs.sentry.io/quickstart/?platform=browser

The footprint and impact on your pageload time of this script it <1KB gzipped while keeping the same functionality.

so tl;dr:
We are aware of it, we know there is room for improvement but it's not top priority right now.

I think it's fair to first compare the gzip bundle sizes instead of the uncompressed minified file size:

I would argue it is also fair to compare minified sizes as perfomance issues not only arise from downloading javascript, but also from parsing and execution. ~92kb is quite hefty and could add up to 1s of parse time on low-end devices (just for this one library!).

I'm not sure where you take the number of < 1KB for the CDN'ed script from. Could you elaborate? When I open https://browser.sentry-cdn.com/4.0.4/bundle.min.js I see a gzipped size of 22KB.

You should be aware that sentry's sdk is just one of many libraries developers include.

PS: I love sentry, it's been super helpful for us. Web performance is just something I'm passionate about. ;)

@klaemo
Hehe, no worries 😅

Like I said, we are aware and it's not like we don't want it to be smaller.
Highest prio for us was to ship the new SDK, we will work to improve the bundle size over time.
There are many more steps we can take, e.g.: use tslib, combine strings ...
So there is a lot of space for improvements.

Sorry, the link I posted before is already outdated 🙃
I was referring to the _Loader_: https://docs.sentry.io/platforms/javascript/loader/
While the _Loader_ also has it's limitations due it's async nature and in the end, it still fetches and injects the SDK (even if it's async) it's an alternative we offer because people asked for it.

@HazAT Sorry, guys, but can you provide next version release date?
I mean, there are some changes already at the #master branch but not released yet. That one is deciding is 4x version is usable for Angular5+ projects though.

@rayzru Just released 4.0.5, but please keep posts related to the topic.

In my opinion, this is definitely a regression and the serious reason not to update to the new version.

💯 I was just about to upgrade up until I noticed that:

capture d ecran 2018-10-03 a 15 07 27

At least the package size is smaller, but I think that ⚠️ +10 KB of gzipped JavaScript in a bundle is significant. We will wait, keep up the good work :)

@HazAT Could it be possible to generate esm files. It would allow webpack to have better result with concatenation and tree shaking.

You might want to add some CI tool to track the bundle size of the package for each merge request. Since this issue it has actually grown to 100 kB, see https://bundlephobia.com/result?p=@sentry/browser@4.3.0

Try for instance https://github.com/siddharthkp/bundlesize

The default performance budget for an entry point in Webpack is 250 kb to make sure you get decent performance on any device and network. 100 kb of Sentry takes up quite a lot of that budget.

Please keep us updated if fixing this regression is on the roadmap at all, or if the library will just keep growing without a size budget.

We are paying customers and heavily invested in Sentry on both backend, native and web, but an upgrade to over 3x the size of the library ([email protected] is 31 kB) is not something we can justify.

@jacobrask You can stick to the older version of the library, it's what we do at https://www.onepixel.com/, it's working fine 👌.
dont-confuse-motion-with-progress

@jacobrask It's definitely on our list and we also think there are some low hanging fruits where we can easily reduce our bundle size.
More and more people asking for this so we will probably tackle this sooner than expected.

@HazAT
Sentry browser SDK rollup bundle can be optimized. In bundle min js file, there are many tslib code repeatd. Such as __generator, __assign. In Browser env, it's best to share one code. Butthe browser project use another packages dist file. Maybe reduce the gzip size from 23K to 16K.

The bundle size is same in 4.3.2
https://bundlephobia.com/result?p=@sentry/browser@4.3.2 regardless of the changes from
https://github.com/getsentry/sentry-javascript/pull/1738 :(

@vkrol We had to revert the changes that @gaterking made, at least for the npm package.
The bundle on CDN on the other hand should be smaller.

We will for sure re-add the changes but we need to talk about it since we need a dep on tslib for example.
Also how typings were generated was broken.

@HazAT OK, thanks.

@vkrol We had to revert the changes that @gaterking made, at least for the npm package.
The bundle on CDN on the other hand should be smaller.

We will for sure re-add the changes but we need to talk about it since we need a dep on tslib for example.
Also how typings were generated was broken.

Hope as soon as possible.

@gaterking @kamilogorek Fixed it already https://github.com/getsentry/sentry-javascript/pull/1751
We just had to do an "urgent" release that's why we reverted it.

On the client-side, I basically want this to capture errors and submit them to the API.

What else is this library doing that's so complex?

It's really hard to understand why a simpler error-reporter needs to have such a substantial footprint 😐

@mindplay-dk It's mostly because JavaScript and Browsers are a mess ^^
We need to do a lot of fixing up broken/wrong stack traces.
The simple task of "just catching errors" is also way more complex than it seems.

It's really hard to understand why a simpler error-reporter needs to have such a substantial footprint 😐

@mindplay-dk because it's not simple.

Here's the code for just capturing errors in all the browsers and unifying them into a usable data structure: https://github.com/getsentry/sentry-javascript/blob/master/packages/browser/src/tracekit.ts

Well done on the recent size reduction, greatly appreciated. 👍

A quick glance at the linked file shows code to handle errors for Opera 10, is that really still required? TraceKit also does not account for the (currently) 2x size increase from Raven, which was already large.

Some suggestions:

Is there some shared code(app:///${base} in rewriteframes.ts) in another packages such as package/core? They are not used by client, but used by node.

because it's not simple.

@kamilogorek yikes, you're obviously right... I realized JavaScript was a mess - I guess I've never dug into this area before, I didn't realize how bad this was. I guess there's really no simple way to handle stack-traces in JS. Just. Yikes. 😐

Instead of just trying to minimize helpers you could just provide the already mentioned esm files, that's easy and even a best practice today.

Reduce usage of async/await, it compiles poorly to ES5. Compare https://github.com/getsentry/sentry-javascript/blob/master/packages/core/src/baseclient.ts#L307-L378 to the output code (search "processEvent" in the production bundle). That entire file becomes huge in the production bundle.

That's the wrong way, instead of optimizing further for ES5 it's more important to optimize for 80.07% who are using modern browsers.

For everyone who needs support old browsers:
Async functions are supported by any browser that supports <script type="module"> (caniuse: esm, async) so only users of older browsers need to wait longer (it takes longer for them anyway)

Proof:
160KB (es5, bundled) > 119KB (esm, plain files)

So please bundle esm file (too), it's as easy as changing setting module and target in /tsconfig.esm.json (that extends tsconfig.build.json) to esnext, adding tsconfig.esm.json files similar to the tsconfig.build.json files to the packages, add it to the build and package and specify a module entry in the package.json

If you want, I can add a PR for that.

If you want, I can add a PR for that.

I'd love that @cromefire :)

Would be awesome if there was an option to select between classic and modern mode, like vue cli. Where modern version has only support for most modern browsers and thus could be less bloated.

Or even better if it could work like webpack env, so that the user could specify the browser support needed. Ofc, this is not an easy peasy feature, but just wanted to throw it out there :)

Awesome product!

With that new PR you can configure babel however you want to support only the browsers you need

The size of the @sentry/browser is more than twice as large as the size of raven-js: 86 kB vs 39 kB (minified).

FYI: the size of the latest version of @sentry/browser is increased to 91.8 kB. Source: https://bundlephobia.com/result?p=@sentry/browser@4.5.0.

@cromefire Thanks for your work with optimizing the library size!

I just tried using the new esm build from v4.5.0 but I got a lot errors. All of them are triggered because modules from @sentry/utils/esm could not be resolved.

In fact I didn't found the folders in node_modules after a fresh yarn install. (See screenshot)

complete error list

ERROR in ./node_modules/@sentry/core/esm/baseclient.js
Module not found: Error: Can't resolve '@sentry/utils/esm/async' in './node_modules/@sentry/core/esm'
ERROR in ./node_modules/@sentry/browser/esm/backend.js
Module not found: Error: Can't resolve '@sentry/utils/esm/is' in './node_modules/@sentry/browser/esm'
ERROR in ./node_modules/@sentry/browser/esm/tracekit.js
Module not found: Error: Can't resolve '@sentry/utils/esm/is' in './node_modules/@sentry/browser/esm'
ERROR in ./node_modules/@sentry/browser/esm/integrations/breadcrumbs.js
Module not found: Error: Can't resolve '@sentry/utils/esm/is' in './node_modules/@sentry/browser/esm/integrations'
ERROR in ./node_modules/@sentry/browser/esm/integrations/helpers.js
Module not found: Error: Can't resolve '@sentry/utils/esm/is' in './node_modules/@sentry/browser/esm/integrations'
ERROR in ./node_modules/@sentry/browser/esm/integrations/pluggable/vue.js
Module not found: Error: Can't resolve '@sentry/utils/esm/is' in './node_modules/@sentry/browser/esm/integrations/pluggable'
ERROR in ./node_modules/@sentry/core/esm/baseclient.js
Module not found: Error: Can't resolve '@sentry/utils/esm/is' in './node_modules/@sentry/core/esm'
ERROR in ./node_modules/@sentry/core/esm/dsn.js
Module not found: Error: Can't resolve '@sentry/utils/esm/is' in './node_modules/@sentry/core/esm'
ERROR in ./node_modules/@sentry/core/esm/integrations/inboundfilters.js
Module not found: Error: Can't resolve '@sentry/utils/esm/is' in './node_modules/@sentry/core/esm/integrations'
ERROR in ./node_modules/@sentry/core/esm/integrations/extraerrordata.js
Module not found: Error: Can't resolve '@sentry/utils/esm/is' in './node_modules/@sentry/core/esm/integrations'
ERROR in ./node_modules/@sentry/browser/esm/integrations/globalhandlers.js
Module not found: Error: Can't resolve '@sentry/utils/esm/logger' in './node_modules/@sentry/browser/esm/integrations'
ERROR in ./node_modules/@sentry/browser/esm/integrations/breadcrumbs.js
Module not found: Error: Can't resolve '@sentry/utils/esm/logger' in './node_modules/@sentry/browser/esm/integrations'
ERROR in ./node_modules/@sentry/core/esm/baseclient.js
Module not found: Error: Can't resolve '@sentry/utils/esm/logger' in './node_modules/@sentry/core/esm'
ERROR in ./node_modules/@sentry/core/esm/basebackend.js
Module not found: Error: Can't resolve '@sentry/utils/esm/logger' in './node_modules/@sentry/core/esm'
ERROR in ./node_modules/@sentry/core/esm/sdk.js
Module not found: Error: Can't resolve '@sentry/utils/esm/logger' in './node_modules/@sentry/core/esm'
ERROR in ./node_modules/@sentry/core/esm/integration.js
Module not found: Error: Can't resolve '@sentry/utils/esm/logger' in './node_modules/@sentry/core/esm'
ERROR in ./node_modules/@sentry/core/esm/integrations/dedupe.js
Module not found: Error: Can't resolve '@sentry/utils/esm/logger' in './node_modules/@sentry/core/esm/integrations'
ERROR in ./node_modules/@sentry/core/esm/integrations/sdkinformation.js
Module not found: Error: Can't resolve '@sentry/utils/esm/logger' in './node_modules/@sentry/core/esm/integrations'
ERROR in ./node_modules/@sentry/core/esm/integrations/inboundfilters.js
Module not found: Error: Can't resolve '@sentry/utils/esm/logger' in './node_modules/@sentry/core/esm/integrations'
ERROR in ./node_modules/@sentry/hub/esm/hub.js
Module not found: Error: Can't resolve '@sentry/utils/esm/logger' in './node_modules/@sentry/hub/esm'
ERROR in ./node_modules/@sentry/browser/esm/client.js
Module not found: Error: Can't resolve '@sentry/utils/esm/misc' in './node_modules/@sentry/browser/esm'
ERROR in ./node_modules/@sentry/browser/esm/tracekit.js
Module not found: Error: Can't resolve '@sentry/utils/esm/misc' in './node_modules/@sentry/browser/esm'
ERROR in ./node_modules/@sentry/browser/esm/integrations/useragent.js
Module not found: Error: Can't resolve '@sentry/utils/esm/misc' in './node_modules/@sentry/browser/esm/integrations'
ERROR in ./node_modules/@sentry/browser/esm/integrations/breadcrumbs.js
Module not found: Error: Can't resolve '@sentry/utils/esm/misc' in './node_modules/@sentry/browser/esm/integrations'
ERROR in ./node_modules/@sentry/browser/esm/integrations/trycatch.js
Module not found: Error: Can't resolve '@sentry/utils/esm/misc' in './node_modules/@sentry/browser/esm/integrations'
ERROR in ./node_modules/@sentry/browser/esm/integrations/helpers.js
Module not found: Error: Can't resolve '@sentry/utils/esm/misc' in './node_modules/@sentry/browser/esm/integrations'
ERROR in ./node_modules/@sentry/browser/esm/integrations/pluggable/reportingobserver.js
Module not found: Error: Can't resolve '@sentry/utils/esm/misc' in './node_modules/@sentry/browser/esm/integrations/pluggable'
ERROR in ./node_modules/@sentry/browser/esm/integrations/pluggable/vue.js
Module not found: Error: Can't resolve '@sentry/utils/esm/misc' in './node_modules/@sentry/browser/esm/integrations/pluggable'
ERROR in ./node_modules/@sentry/browser/esm/integrations/pluggable/ember.js
Module not found: Error: Can't resolve '@sentry/utils/esm/misc' in './node_modules/@sentry/browser/esm/integrations/pluggable'
ERROR in ./node_modules/@sentry/browser/esm/transports/beacon.js
Module not found: Error: Can't resolve '@sentry/utils/esm/misc' in './node_modules/@sentry/browser/esm/transports'
ERROR in ./node_modules/@sentry/browser/esm/transports/fetch.js
Module not found: Error: Can't resolve '@sentry/utils/esm/misc' in './node_modules/@sentry/browser/esm/transports'
ERROR in ./node_modules/@sentry/core/esm/baseclient.js
Module not found: Error: Can't resolve '@sentry/utils/esm/misc' in './node_modules/@sentry/core/esm'
ERROR in ./node_modules/@sentry/core/esm/integrations/dedupe.js
Module not found: Error: Can't resolve '@sentry/utils/esm/misc' in './node_modules/@sentry/core/esm/integrations'
ERROR in ./node_modules/@sentry/core/esm/integrations/inboundfilters.js
Module not found: Error: Can't resolve '@sentry/utils/esm/misc' in './node_modules/@sentry/core/esm/integrations'
ERROR in ./node_modules/@sentry/hub/esm/scope.js
Module not found: Error: Can't resolve '@sentry/utils/esm/misc' in './node_modules/@sentry/hub/esm'
ERROR in ./node_modules/@sentry/hub/esm/hub.js
Module not found: Error: Can't resolve '@sentry/utils/esm/misc' in './node_modules/@sentry/hub/esm'
ERROR in ./node_modules/@sentry/browser/esm/parsers.js
Module not found: Error: Can't resolve '@sentry/utils/esm/object' in './node_modules/@sentry/browser/esm'
ERROR in ./node_modules/@sentry/browser/esm/integrations/breadcrumbs.js
Module not found: Error: Can't resolve '@sentry/utils/esm/object' in './node_modules/@sentry/browser/esm/integrations'
ERROR in ./node_modules/@sentry/browser/esm/integrations/trycatch.js
Module not found: Error: Can't resolve '@sentry/utils/esm/object' in './node_modules/@sentry/browser/esm/integrations'
ERROR in ./node_modules/@sentry/browser/esm/integrations/helpers.js
Module not found: Error: Can't resolve '@sentry/utils/esm/object' in './node_modules/@sentry/browser/esm/integrations'
ERROR in ./node_modules/@sentry/core/esm/api.js
Module not found: Error: Can't resolve '@sentry/utils/esm/object' in './node_modules/@sentry/core/esm'
ERROR in ./node_modules/@sentry/core/esm/basebackend.js
Module not found: Error: Can't resolve '@sentry/utils/esm/object' in './node_modules/@sentry/core/esm'
ERROR in ./node_modules/@sentry/core/esm/dsn.js
Module not found: Error: Can't resolve '@sentry/utils/esm/object' in './node_modules/@sentry/core/esm'
ERROR in ./node_modules/@sentry/hub/esm/scope.js
Module not found: Error: Can't resolve '@sentry/utils/esm/object' in './node_modules/@sentry/hub/esm'
ERROR in ./node_modules/@sentry/core/esm/integrations/pluggable/rewriteframes.js
Module not found: Error: Can't resolve '@sentry/utils/esm/path' in './node_modules/@sentry/core/esm/integrations/pluggable'
ERROR in ./node_modules/@sentry/browser/esm/parsers.js
Module not found: Error: Can't resolve '@sentry/utils/esm/string' in './node_modules/@sentry/browser/esm'
ERROR in ./node_modules/@sentry/browser/esm/integrations/breadcrumbs.js
Module not found: Error: Can't resolve '@sentry/utils/esm/string' in './node_modules/@sentry/browser/esm/integrations'
ERROR in ./node_modules/@sentry/core/esm/baseclient.js
Module not found: Error: Can't resolve '@sentry/utils/esm/string' in './node_modules/@sentry/core/esm'
ERROR in ./node_modules/@sentry/core/esm/integrations/inboundfilters.js
Module not found: Error: Can't resolve '@sentry/utils/esm/string' in './node_modules/@sentry/core/esm/integrations'
ERROR in ./node_modules/@sentry/browser/esm/backend.js
Module not found: Error: Can't resolve '@sentry/utils/esm/supports' in './node_modules/@sentry/browser/esm'
ERROR in ./node_modules/@sentry/browser/esm/integrations/breadcrumbs.js
Module not found: Error: Can't resolve '@sentry/utils/esm/supports' in './node_modules/@sentry/browser/esm/integrations'
ERROR in ./node_modules/@sentry/browser/esm/integrations/pluggable/reportingobserver.js
Module not found: Error: Can't resolve '@sentry/utils/esm/supports' in './node_modules/@sentry/browser/esm/integrations/pluggable'
ERROR in ./node_modules/@sentry/browser/esm/transports/fetch.js
Module not found: Error: Can't resolve '@sentry/utils/esm/supports' in './node_modules/@sentry/browser/esm/transports'

screenshot 2019-01-10 at 4 37 45 pm

@pascaliske esm build is still in the experimentation phase and we haven't documented it publicly yet. We'll do it once everything is tested throughout and will post our findings here.

@kamilogorek Yes, I know. Just wanted to let you know of theese errors. 🙂

Thanks, appreciate it @pascaliske! We will try to provide ESM support as soon as possible :)

@pascaliske try yarn build first

@cromefire No this won't help I think. I just downloaded the package from npm so there's no build environment available. 🙂

I searched a bit through the source code and compared @sentry/browser with @sentry/utils. I think this is the problem: packages/utils/tsconfig.build.json#L5 vs. packages/browser/tsconfig.build.json#L5. Is it possible that the normal build output overwrites the esm build output? 🤔

Inside my node_modules folder the browser package contains build output from both normal and esm. But the utils package only contains normal build output in the root folder.

Is it already released?

I searched a bit through the source code and compared @sentry/browser with @sentry/utils . I think this is the problem: packages/utils/tsconfig.build.json#L5 vs. packages/browser/tsconfig.build.json#L5 . Is it possible that the normal build output overwrites the esm build output? 🤔

No, you have to look at the esm tsconfig

Will look at it tomorrow

Hey all! We're also poking around some of the bundle sizes in Sentry, and came across this: https://github.com/getsentry/sentry-javascript/blob/master/packages/minimal/package.json#L20

Looks like it's adding a chunk of size for very few functions (spread and assign). I'm not super familiar with Typescript, but is it necessary for this at runtime?

It's also unclear to me why @sentry/types needs to be a _runtime_ dependency, and not located in devDependencies...

@evocateur for all users of typescript this is necessary. Typescript optimizes it all away.
(but it may be needed for the .d.ts files)

@IanMitchell It's not used for esm build, but for normal ones

The bundle.js of 4.5.0 contains a lot of duplicate code, like Severity, htmlElementAsString, htmlElementAsString, uuid4, parseUrl and so on. This cannot be intended!

The same happens when I do a Bundle via import * as Sentry from '@sentry/browser'; (as the only line in the file) using WebPack + Babel 7, then the bundled size is 326kb. See: sentry.bundle.js.txt
We use the same configuration for our other bundles too, but sentry is the only bundle with that issue.

The bundle.min.js does not have duplicate code inside, which may be a result of tree shaking with rollup.

So, a temporary solution is to use import '@sentry/browser/build/bundle.min.js';

The bundle.js of 4.5.0 contains a lot of duplicate code, like Severity, htmlElementAsString, htmlElementAsString, uuid4, parseUrl and so on. This cannot be intended!

This is why (or it's at least one reason) there is the esm build. If you have a bundler anyway it's more efficient than using a prebuild bundle. (It's just beta and right now still broken)

Looking at this again, and I don't believe this couldn't be smaller. Much smaller.

Stack-traces with source-map support ought to be by far the most complex thing in this library - and it doesn't look like it is? It seems like most of the footprint is from the core framework, which it shares with the node.js client, where I'm sure footprint isn't really a concern.

Don't get me wrong, this is a beautiful piece of architecture - very nice TypeScript work.

But on the client-side, that doesn't mean much. It needs to be small and load fast - especially for something as low-level as this, it doesn't really matter if the source-code is beautiful or not. As far as I can tell, all that impressive is architecture is costing a lot of bytes down the line.

For comparison:

I came across TrackJS, which has similar capabilities (cross-browser stack-trace with source-maps) in a ~10KB package.

The original TraceKit is ~3KB min+gz.

I found this library which can do the source-map bit (on the client-side) in ~8KB min+gz or ~10KB with x-browser polyfills.

Beyond that, it's a matter of collecting a few bits of browser information, wrapping in the expected JSON format, and posting it - which shouldn't be more than a few KB min+gz. Should it?

I feel like this is just way more architecture than what most people need. If I need any plugin support at all, maybe I need a simple hook that lets me plug information into the JSON post, but that's about it.

I know that it's common to deploy megabytes of JS these days, but we have strict content policies at work, to ensure we ship projects that load fast on mobiles, and I can't justify spending more than half of our JS budget on error-logging - maybe 10% tops, so something like ~15-20 KB seems reasonable.

I love your product, but I can't deploy this client 😐

For something like this it could be a good idea to delegate the stacktrace and source-map parsing to the server, where size is irrelevant

For something like this it could be a good idea to delegate the stacktrace and source-map parsing to the server, where size is irrelevant

@cromefire interesting idea. I wonder if that's what e.g. TrackJS does to keep the size down? (Their client is proprietary - only the minified source is available, so it's hard to say what they do. Suppose I could install it and see what travels over the wire...)

Here's a simpler package to resolve source-maps in the browser: source-map-resolve at ~2KB min+gz ... that's without polyfills, but (if this works) I'm thinking we should be able to hit ~10KB for modern browsers that don't need polyfills.

that's without polyfills

Polyfills shouldn't be in the esm build, so that could also work, but in the bachend it would be even less

@cromefire ESM build should be available in 4.5.1 now. Still not documented as we want to make sure it's battle-tested, but so far so good. I checked regular webpack build with babel loader and it works like a charm.

Beyond that, it's a matter of collecting a few bits of browser information, wrapping in the expected JSON format, and posting it - which shouldn't be more than a few KB min+gz. Should it?

@mindplay-dk we don't perform any stack-trace resolving on the client-side. It's all done on the server, that's why you need to upload source maps in the first place to get support for them.

What we do though is:

  • event processors to provide custom hooks that allow you to modify/filter/enhance data sent to Sentry
  • take care of all native API wrapping
  • capture breadcrumbs from all user interactions, network calls, navigations
  • extract user agent data
  • extract additional error data from linked errors, so you can make multiple-error levels like in other languages
  • listen to both global error handlers
  • provide multiple network transports, so that user will always get the best one for his current environment
  • take care of tenths of edge cases and various error (even custom ones) objects and various native implementations
  • provide fallbacks to spare or broken error information
  • buffer events so that you won't flood your own Sentry instance or run out of free events if something goes wrong

Just to name a few. I really wish it would be as easy as "catch error, add some data and send it through".
In the real world though, there are tens of inputs, tens of sources error can come from (which all provide different data) and tens of environments which vary in behavior.
We'll definitely keep working on how to get this down to ~10-15kB, but it'll take some time. We only have so many resources (read people/time) we can spend now.

I know that it's common to deploy megabytes of JS these days, but we have strict content policies at work, to ensure we ship projects that load fast on mobiles, and I can't justify spending more than half of our JS budget on error-logging - maybe 10% tops, so something like ~15-20 KB seems reasonable.

You can use our loader then – https://docs.sentry.io/platforms/javascript/loader/ :)

You can use our loader then – https://docs.sentry.io/platforms/javascript/loader/ :)

But there is sadly no solution for webpack

Just to name a few. I really wish it would be as easy as "catch error, add some data and send it through".

Maybe someone should propose something at tc39. I would have to look at how the process is, but maybe someone could propose a standardized API for like stacktrace reading

But there is sadly no solution for webpack

What do you mean exactly? Having a package that could co-exist with the loader, which could be imported and bundled, but then communicate with asynchronously loaded SDK once error or captureException call happens?

What do you mean exactly? Having a package that could co-exist with the loader, which could be imported and bundled, but then communicate with asynchronously loaded SDK once error or captureException call happens?

Yes, if I recap correctly, the loader is only available via a cdn

@cromefire yes, because it's meant to be used as a "snippet". However you can find it's code here https://github.com/getsentry/sentry-javascript/blob/master/packages/browser/src/loader.js

Seems like I have to open a new PR, because with esm this would also be usable from your own code

We have a solution coming that will let you use loader alongside minimal and will effectively add only a few kB to your final bundle.

It shouldn't be hard to write a loader that loads that in under 1kb, so why not, I will try writing a quick one

One thing that could help out a lot here is if some of the functionalities are optional.

For instance a really nice bare minimum could be:

  • native error stack trace (don't care that it's not optimal on some browsers)
  • user agent
  • timestamp
  • URL
  • match with source maps on the server

Any additional functionalities can just be an add on. We only support modern browsers, so we don't need to work around all the quirky behavior of old browsers.

We solved this by using webpack code splitting and load sentry client only on error.

sentry.js

import * as Sentry from '@sentry/browser';
Sentry.init({
  ...
  integrations: integrations => {
    return integrations.filter(integration => integration.name !== 'GlobalHandlers');
  },
});
export const logError = error => Sentry.captureException(error);

errors.js

const captureError = async error => {
 const { logError } await import(/* webpackChunkName: "sentry" */ './sentry');
 logError(error);
}
window.onerror = (message, url, line, column, error) => captureError(error);
window.onunhandledrejection = event => captureError(event.reason);

We do some more in there like populate breadcrumbs, add extra, add tags, etc.. but it's possible to use sentry client and not make your bundle bigger.

This is somewhat what I implemented in #1846

Might be helpful to others:
I used the ESM build with webpack (4.29.5) by:

  • adding a webpack alias to use the ESM build rather than the standard build as there's no module declaration in package.json
resolve: {
    alias: {
        // use sentry ESM build which is not declared in the @sentry/browser package.json
        '@sentry/browser': path.resolve(
            __dirname,
            'node_modules/@sentry/browser/esm',
        ),
    }
  • add an exclusion to sentry/.+/esm to our babel-loader config, as it seems that the ESM build includes features newer than ES2015.
{
    test: /\.m?jsx?$/,
    loader: 'babel-loader',
    // compile sentry as the ESM build is new and ships modern features which break our supported browsers
    exclude: /(node_modules\/(?!(@sentry\/[^/]+\/esm))|bower_components)\//,
}

Notes:

  • We used aliases so we don't have to worry about bundling when using it in code (we do similar for lodash-es among other things)

@Limess

You can just redirect to @sentry/browser/esm:

resolve: {
    alias: {
        // use sentry ESM build which is not declared in the @sentry/browser package.json
        '@sentry/browser': '@sentry/browser/esm'
    }

But you don't need to add an alias, just import @sentry/browser/esm

For the loader it's easier to write it like this:

  • If you have other things in babel:
{
    test: /other_things/,
    include: [/@sentry\/.+\/esm/],
    exclude: /node_modules/,
    // config
}
  • If you don't:
{
    test: /@sentry\/.+\/esm/,
    exclude: /node_modules/,
    // config
}

Also remember to customize the babel config for your needs: babel docs, else it's not worth to use the esm version

Update: We will soon release new major version of the SDK which reduces the bundle size significantly.

26.1 kB - https://bundlephobia.com/result?p=@sentry/browser@4.6.4
vs.
17.2 kB - https://bundlephobia.com/result?p=@sentry/browser@5.0.0-rc.1

Our prebuilt CDN versions even show better results (not sure how bundlephobia measures stuff)

ES6:  14.3535 kB
ES5:  15.6846 kB

Anyway, I wanted to let you know that were are still working on reducing the bundle size further but this should already be a huge step in the right direction.

Note on upgrading: It's a major bump since there are many internal changes in the SDK. There shouldn't be any code changes necessary on your side. We are currently testing the new version ourselves on sentry.io to see how it behaves. ref: https://github.com/getsentry/sentry/pull/12492

Disclaimer: Don't use 5.0.0-rc.x in production yet as we do 🙈

@HazAT thank you for taking this seriously! this is a big step forward - I am already much less concerned about deploying this now :-)

image

@kamilogorek Just out of curiosity, could you add to the comparison the last version from 3.x branch?

I am closing this issue, as of now, we think, the reduction we introduced moving from v4 to v5 is a trend in the right direction. We will still try to reduce it further and we will be very conscious about increasing it ever again.

As a quick remark, we really only like to compare our "bundle" size, since depending on what bundler you are using your mileage may vary, so here are the CDN bundle number we ship(ped):

| Package | Version | Size in Bytes | Size in kB | Link |
|-----------------|---------|---------------|------------|----------------------------------------------------|
| raven-js | 3.27.0 | 13741 Bytes | ~13.4kB | https://cdn.ravenjs.com/3.27.0/raven.min.js |
| @sentry/browser | 4.6.6 | 22607 Bytes | ~22.1kB | https://browser.sentry-cdn.com/4.6.6/bundle.min.js |
| @sentry/browser | 5.0.3 | 16059 Bytes | ~15.7kB | https://browser.sentry-cdn.com/5.0.3/bundle.min.js |

With v5 we also ship and esm build, meaning if your are using a bundler it should be able to treeshake unused code paths.

Thank you all for your patience 🙇

@HazAT @kamilogorek awesome!

@Limess Is it still relevant to use this today: @sentry/browser/esm instead of @sentry/browser?

It's imported like import * as Sentry from "@sentry/browser/esm"; and bundled with webpack -p but I see no difference in bundle sizes. I also have a bare webpack.config.js with no plugins or loaders.

@0xbkt It doesn't make difference in bundle size, at least now when using rollup to bundle app.

Was this page helpful?
0 / 5 - 0 ratings