mixpanel-browser is huge! Maybe support tree shaking? What can be done?
kazazor opened this issue · comments
According to webpack-bundle-analyzer
mixpanel-browser
is huge!
This is the one of the biggest vendor packages we have and it doesn't make any sense to me.
To put it into perspective, this is moment.js
:
This is even bigger tan moment
, and moment
is big!
I'm opening a discussion here with Mixpanel guys, how can we make it smaller?
can we support ES6 modules style in order to leverage tree shaking?
Any other ideas?
@jbwyme @ilyakamens @tdumitrescu any thoughts on the size of the package? is there any way we can decrease the size in the build step?
Totally in support of making the package size smaller. The mixpanel js library comes bundled with support for a number of different features like in-app notifications which bloats out the size. However, we should be able to restructure it a bit so that you can do more granular imports when using mixpanel-browser
. I'll take a look at the work required to see if we can get some easy wins but as always PRs are welcome :)
@jbwyme awesome, thank you! It would be great to have a core package for mixpanel, and then extras like in-app notifications could be separate packages. i like the way lodash does this, where a single helper function is packaged.
Thanks everyone for looking at doing that!
@baldwmic I actually disagree with the packages approach. This approach is kind of outdated and was replaced even in lodash
.
In lodash
instead of installing a specific package per function you can go ahead and do:
import get from 'lodash/get';
import remove from 'lodash/remove';
import isPlainObject from 'lodash/isPlainObject';
This way you don't need to go ahead and install each package and get your package.json
so big.
More than that, doing that you actually able to share the different functions from different packages that uses lodash
itself, which is very common. By doing so you're actually reducing the total size of your website. If you'll use individual packages, you'll make my life as a developer a little bit harder then just doing something like:
import X from 'mixpanel-browser/X';
I would suggest going with that option.
Tree shaking
In today's js frontend world, support for tree shaking is a must.
So instead of doing:
import X from 'mixpanel-browser/X';
import Y from 'mixpanel-browser/Y';
import Z from 'mixpanel-browser/Z';
I could do:
import { X, Y, Z } from 'mixpanel-browser';
tree shaking is really easy to have along side with commonjs support and it's just some babel configurations to add. You can take a look at lodash-es
& react-router/es
for reference..
IMO having both es
support (tree shaking) along with commonjs in the same package (link react-router
does) would be the best option. The other option like lodash-es
does makes it harder to share common packages so I wouldn't go with that option.
WDYT? :)
ooh @kazazor i do like the idea of installing only one package and then just modifying the import statements, good point! that does seem much easier from a developer perspective.
i also agree that tree-shaking would be awesome! removing code that is not used will definitely help decrease the size of developer builds :)
Note that if your main concern is just reducing download size on pageload, then the CommonJS and other bundled/synchronous versions of the lib will never be as efficient as the standard snippet-loaded version (where you just add the embed code to your page). In that version, just the small minified embed code runs initially, and the rest of the lib is downloaded asynchronously without blocking, and will also be more cacheable than if it is included in the main bundle of an application.
@tdumitrescu How about the idea of a mixpanel-lite package, which only contains say the code for tracking events, or something along those lines?
@tdumitrescu the problem with "installing" a package by embedding a script tag in html is that it's not very maintainable for our application. My team, and I'd be willing to bet many others, prefer to use npm
/ yarn
to manage our dependencies. Is it not possible to create a liter version of the package like @OllieJennings suggested?
Yes, there would definitely be advantages to improving the modularization of the lib and building separate versions with different parts included. Until we find the time to implement it (or shepherd through an acceptable pull request), I was suggesting the embed code as a way to remove the pageload impact of the extra 40K gzipped bundle.
@baldwmic you can totally use npm/yarn to install mixpanel-browser
and still use the embed code to load the lib asynchronously. The instructions are basically the same as for "Using Bower to load the entire library": point a script tag at the embed code downloaded with the npm package, and use the MIXPANEL_CUSTOM_LIB_URL
var to point at the npm-downloaded lib src (at whichever URL your asset pipeline ends up making it available).
@tdumitrescu To elaborate on your earlier message:
Note that if your main concern is just reducing download size on pageload, then the CommonJS and other bundled/synchronous versions of the lib will never be as efficient as the standard snippet-loaded version (where you just add the embed code to your page). In that version, just the small minified embed code runs initially, and the rest of the lib is downloaded asynchronously without blocking, and will also be more cacheable than if it is included in the main bundle of an application.
Our main concern is JS execution time. Larger JS payloads, even if they're cached by the browser, impart a pretty significant first-pass performance penalty. (V8 can't do any optimizations on the first pass + parsing + JIT compilation)
see https://medium.com/reloading/javascript-start-up-performance-69200f43b201 for more info.
@matthewoates sure, parsing a larger blob of js will take more time before the Mixpanel lib starts firing off events, no doubt about that. My point about using the embed code is that parsing the lib in that case does not block pageload (it loads the lib asynchronously, and any mixpanel.track
etc calls that you make until the lib loads are simply queued), and shouldn't measurably affect your page's startup time.
I think one good first step is defining what browsers should this library support.
Do we already have that?
With that in hand we might be able to do a nice cleanup on the utils.js module.
Created a PR to decrease its size #143
There is still a lot to be improved though, this is just the utils
module.
I use this library solely for sending events, and paying 70kB for that is hard to swallow. Is there any progress on repackaging using a more modular structure?
@bradleyayers I created a branch that is intended for logging only (we also use it only for logging).
I can't give you any guarantees that will work perfectly for you, but take a look, I hope it helps.
It currently has around 50% less code than the full library. (you can see that on the README badges). Feel free to branch it out and apply your own changes.
https://github.com/fabiomcosta/mixpanel-js/tree/mixpanel-logging-only
Any update here would be highly appreciated
Unfortunately, the only update at the moment is that this ask hasn't reached high priority in our product backlog. If you simply need to avoid blocking pageload with your JS loading, then the script tag embed code loader is the way to go (i.e. the "standard" mixpanel-js installation). For static bundles including mixpanel-browser via require/import, the amount of effort relative to the gains (your bundle will be a few kb smaller gzipped) simply hasn't yet justified prioritizing this over other engineering projects.
@tdumitrescu Totally fair, we switched to using the js library instead. Thank you.
The size is really frustrating. I still hope there will be updates.
Also could a non-build source file be exposed from the package.json
? E.g. a browser
or module
property that points to ./src/[entry-file]
. That would help whatever builder immensely with deduping common modules and thus reducing overall bundle size. I'd rather not be limited to whatever is pre-built but allow a builder to simple include the minimum set of modules required.
Similarly I don't see any reason for having inline styles being included with a library that is suppose to just track users. If these could be part of a special build just for when they are needed that would make a lot more sense.
@Swaagie which builder are you looking to support, or more to the point what exact entry would you like in package.json
? We can add it easily. FWIW if you just want to make a PR, the entrypoint file you want is src/loader-module.js
. There's an in-repo example of importing from it at
There is a plan to support alternative builds so you can drop modules that you don't use, but unfortunately no ETA right now on when we'll be able to work on it.
More granular functionality importing would definitely be nice. Hopefully this can help in migration toward this goal. It also introduces a no-notifications bundle as a stop-gap measure:
I think using dynamic import help this
I made the util of the dynamic load of the mixpanel and util components for React user here
https://gist.github.com/Ranatchai/6112c5c952299c6ac67bba7dff11c49c
It uses dynamic-import syntax, that is in a ECMAScript proposal and not currently part of the language standard. if you use babel you need
https://yarnpkg.com/en/package/babel-plugin-syntax-dynamic-import
Any progress here? 40k is way too huge for simply tracking
Any news? Mixpanel lib is almost the same size than react-dom... seriously? We are on our way to stop mixpanel because of this
any updates?
The purpose of mixpanel is to ultimately enhance user experience. Long initial loading times directly contribute to worse UX. It follows that decreasing bundle size should be mixpanels #1 priority imo.
It has been almost 2 years since I opened this issue. I'm afraid it seems to not be Mixpanel's priority at all even that this issue has a LOT of people interesting in.
Seems like if anyone would like it to be reduced the only way it's going to be is by using something else than Mixpanel :/
Any progress?
Any progress?
What's the current status? Any improvements?
I assume they have 0 interest in this, might end just ripping apart their library to create a tiny version for tracking only when l get a chance
Would be really appreciated to see progress on this.
@valentinkostadinov first cut is done, it has track
, identify
and alias
with ability for bulk sending events. Give me a week to fully test it, then will put it on NPM. It sits at around 13KB Gzipped and 39KB minified only
Hi @OllieJennings, any news on this? Thanks!
@jpreynat yes, apologies, just came back from holiday, going to re-test the module and push to NPM this week
@OllieJennings Friendly ping, are there any updates?
Also very interested for this update! Would be amazing
Came here to complain about bundle size as well. Any progress from devs on this issue?
I created a lightweight version that also supports offline mode mixpanel-lite 5.2k (2.2k gzipped).
I've only included the core features, PR's welcome!
// setup mixpanel
mixpanel.init('your-token-here'); // pass { mute: true } to mute by default
// assign all future events to a user
mixpanel.identify('user@email.com');
// assign user info
mixpanel.people.set({
$email: 'user@email.com' // only special properties need the $
});
// track an event
mixpanel.track('Your Event Name' {
firstName: 'Optional event property 1',
lastName: 'Optional event property 2'
});
// clear current identity
mixpanel.reset();
// stop sending data to mixpanel (calls to track, identify etc are ignored)
mixpanel.mute();
// resume sending data to mixpanel
mixpanel.unmute();
// check if mixpanel is muted
if (mixpanel.muted) {
console.log('Mixpanel is disabled');
}
Also throwing down a friendly ping, I like @john-doherty 's lightweight implementation, any chance at getting something like this into the mixpanel-js repo?
+1
+1
Is there anybody working on this?
+1
+1
Guys - this is really insane!!! So many complaints already and you are ignoring it for 3 years? What have you done? Am a customer for 1 year and haven't seen much else. Really wants to make me churn!
It's really been a while. Can somebody from the team react to this, please? Thank you very much
Are there any plans to look into that?
I've been following this issue since a couple years ago and it's quite clear to me this company doesn't give a dam. Just move to another solution, there are dozens of solutions like mixpanel out there. It's a shame they let random developers create a minimal version of this from their own pocket. Mixpanel is not a free product/solution. We have stopped using and the only big deal about it was the large payload we stopped serving ;)
I just signed our startup with Mixpanel (correction, we haven't switched to the paid plan yet). We implemented Mixpanel tracking, and then afterwards observed how much the JS bundle size increased. It's extremely ironic that the largest factor to increasing conversions and product performance is...... ..... PAGE LOAD TIME.
This is disappointing. We are reviewing the 'lite' package to see if it feels safe to use. @john-doherty thank you for that, we are betting the future of our product on these analytics... so we will need to vet it a bit. I intend to notify Mixpanel about this as well.
mixpanel-lite
does not work with Next.js because it requires document
to exist. The lite solution is a good start, but it does not function in the same server + client environment that this package does.
Although we are only calling Mixpanel on the client-side in our application, it still is bundled server-side where it does this check for document
. It's too bad a team that creates a web product does not prioritize web performance.
Same for me, it's 23% of my app size while I just use basic parts of the SDK... After 4 years, any plans to fix this fast??? We will have to drop Mixpanel otherwise, please do something...!
@dawsbot I'm using next.js, whether or not you use Mixpanel's Library, or the lighter library, you need to load it dynamically client side. My technique was to assign the script's loaded event to a redux/react state, then initialize Mixpanel inside of useEffect
(which has access to the DOM) after the scripts loaded event is set.
@bradgreens No worries, I fully removed mixpanel last month.
The lightest bundle size option out there
Agreed. The response time for this issue is unacceptable. I've moved over to amplitude. (edit: and not just for this reason)
@matthewoates Not gonna lie, it's kind of painful to see Atlassian on Amplitude's homepage. But that said, alternative options are very much in play. We harvested some great metrics, but the developer confidence just isn't available on this project.
Hey folks, I just wanted to let you all know that this library will be much smaller in Q1 2022. With the deprecation of messaging, we will be able to remove some sizable portions of the code base. If the size at that point is still an issue to you, we will work with you to get to a good solution.
I am assigning this issue to myself right now to make sure it is, at long last, resolved. I'm embarrassed it's taken this long and promise you we'll fix it.
Hey! Still on track? Is it out maybe and can share a link here?
Thanks!
@odedsolutions the release removing the in-app notifications code will be publicly available likely this coming week.
is this released?
@odedsolutions the release removing the in-app notifications code will be publicly available likely this coming week.
Hi @tdumitrescu, is there a a new timeline for releasing this? It's been nearly 2 weeks.
given the size of this bundle is there a recommended pattern for lazy loading in Next.js applications?
Last I recall they chipped at the size, but if it’s still an issue just load it like any other bullshit script way after your primary UX loads.
+1 this issue is not resolved, v2.45.0 is still 60kb+. Quite a shame