-
Notifications
You must be signed in to change notification settings - Fork 140
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
fix: Implement isDeepEqual
manually
#1686
Conversation
We were using a builtin Node function, but that was silly because Node functions aren't available in the browser. Most builder could probably work that out, but Vite doesn't, so let's implement that ourselves and avoid requiring a bundler to sort this out. Closes #1685
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
Size Change: 0 B Total Size: 3.28 MB ℹ️ View Unchanged
|
{ | ||
files: ['react/**/*.ts'], | ||
rules: { | ||
'posthog-js/no-direct-null-check': 'off', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why turn this off instead of using isNull
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Side note, but @pauldambra what's the background on us using isNull
etc rather than ===
? Browser compatibility? Bytes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the bundle reduced by 1% when we switched to isNull
and isUndefined
compared to the straight comparison
ofc likely that the react stuff is being bundled and run through a minifier by someone else but consistency is probably better than varying
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we use the checks a lot and...
the minified code has (something like) fe(x)
at each call site
whereas the direct check is (something like) x === void 0
when minified
so once you call isUndefined
more times than the character count of adding the declaration to the bundle you add roughly half as many characters by moving to a function
it's the same reason we have some global things as variables in the utils
folder because then they'll minify and we have xY
in the bundle not navigator
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the context! So if someone was experimenting with a new minifier, this is something they could change to see if it made a difference.
(I'd expect a good minifier to make this kind of change automatically but I probably am hoping for too much)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, in my mind I did that to avoid crossing the boundary from posthog-js/react
to posthog-js
. I now see that doesn't make sense because this is a single package for those who're installing it, so I'm happy to change :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah.. fair.. yep, something to bear in my mind if/when we start splitting this up
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So if someone was experimenting with a new minifier, this is something they could change to see if it made a difference.
that'd be a very good minifier... it's more of a compiler at that point 🤯
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there's two sources of (avoidable) size in the repo IMO
- unnecessary repetition of primitives - like this example
- heavy use of classes and no minification of class fields/properties
@@ -0,0 +1,19 @@ | |||
export function isDeepEqual(obj1: any, obj2: any): boolean { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the provenance of this? Is it directly copied from the node library? If you wrote or modified it, it needs tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've attempted to write this function a few times and always been wrong, so would be interested in the answer to this!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we've had to handle recursive json in other places in the SDK too... which is why i wondered about json stringify comparison performance
const keys1 = Object.keys(obj1) | ||
const keys2 = Object.keys(obj2) | ||
|
||
if (keys1.length !== keys2.length) return false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (keys1.length !== keys2.length) return false | |
if (keys1.length !== keys2.length) { | |
return false | |
} |
We generally prefer this style in the codebase. (I'm surprised prettier didn't change this!)
if (!keys2.includes(key)) return false | ||
if (!isDeepEqual(obj1[key], obj2[key])) return false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (!keys2.includes(key)) return false | |
if (!isDeepEqual(obj1[key], obj2[key])) return false | |
if (!keys2.includes(key) || !isDeepEqual(obj1[key], obj2[key])) { | |
return false | |
} |
{ | ||
files: ['react/**/*.ts'], | ||
rules: { | ||
'posthog-js/no-direct-null-check': 'off', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Side note, but @pauldambra what's the background on us using isNull
etc rather than ===
? Browser compatibility? Bytes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, we need to be very careful with that deep equal function
@@ -0,0 +1,19 @@ | |||
export function isDeepEqual(obj1: any, obj2: any): boolean { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've attempted to write this function a few times and always been wrong, so would be interested in the answer to this!
How about this:
Avoids |
We'll have a follow-up PR moving this new helper function to the |
We were using a built-in Node function, but that was silly because Node functions aren't available in the browser. Most bundlers could probably work that out, but Vite doesn't, so let's implement that ourselves and avoid requiring a bundler to sort this out.
Closes #1685