-
-
Notifications
You must be signed in to change notification settings - Fork 10.7k
refactor(dev): replace lodash
#14180
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
Conversation
|
1aa7b4f
to
4198a75
Compare
@brophdawg11 Snapshots are "failing", but imo the output is exactly the same (even more predictable if you ask me). So question here mainly is: do we want to update snapshots or do we want to remove these keys? |
tl;dr; Can we just use the individual I think the discussion above is a perfect example of why we use tools like Out of curiosity, I ran some tests on this branch and the commit it's branched off of and in my (very unscientific) tests of Another argument for these types of changes is less for a user to install into their > du -h node_modules/lodash/
4.9M node_modules/lodash/
> du -hs node_modules/es-toolkit/
11M node_modules/es-toolkit/ It does look like
In cases where there is a 1:1 platform option ( Referring back to the the comment on the e18e proposal, in the future lets discuss the pros of these types of changes in a discussion prior to opening PRs so we can decide which we want to move forward with to avoid unnecessary overhead/toil/reviews/perf-testing/etc. I had to spend a chunk of time yesterday evaluating #14111 which came with no data, and another chunk time today evaluating this PR - all of which I would have rather spent on more pressing areas of RR, like working towards stabilizing middleware 😉 . When we do accept a proposal in the future, let's communicate that the PR should come with the raw data demonstrating that we've achieved what we set out to (faster perf, smaller footprint, etc) so that we don't have to run all those numbers ourselves from scratch. |
You'll have to forgive me for just playing code golf with my suggestions - however, the Even then, I can appreciate that a potential 10% speedup isn't necessarily justification to move off lodash. However....
I would argue that lodash is rarely the right implementation. It's wildly over-engineered for most use cases (including this one), and for the remaining it's just encouraged poor architecture because it's so flexible. I'm not sure I'd say es-toolkit is the right implementation either as their
all the individual packages have actually been deprecated, recommending native alternatives (although the alternatives don't work for All that being said, none of that rambling is a good enough reason to change. The motivation for me, as an end(ish) user though is not size over the wire or on disk, or performance - I just like making my lockfile as small as possible, without prejudice. Every additional dependency is a false positive ReDoS, supply chain compromise, or malformed license that'll get me in trouble with legal waiting to happen. Footnotes
|
huh, good catch - I didn't know that - that's a bummer but understandable for stuff like
It's got 70 million weekly downloads, it's certainly not the wrong choice.
This is totally understandable as a personal preference, but it's just not a pressing need for us at the moment. As stated in #13721 (comment) though we're not anti-these changes, but we just want to see the real-world impacts outlined so we don't have to try to figure them out ourselves. For this PR, given we can't use the individual methods:
|
Or an awful lot of wrong choices :P I agree on not bringing in es-toolkit. The builtin |
4198a75
to
299545c
Compare
299545c
to
36a42a0
Compare
36a42a0
to
d162b6c
Compare
It looks like something about cloning is breaking a lot of e2e tests |
The tests, at least on my machine, appear to run fine individually. I also appear to be getting similar failures on |
await preset.reactRouterConfig({ reactRouterUserConfig }), | ||
// @ts-expect-error |
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 error is this suppressing? 👀
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.
excludedConfigPresetKeys
will always be ["presets"]
, which technically can't happen according to the types.
So in order to remove presets
property from preset.reactRouterConfig
's return and the fact that omit
is now type-safe, there's no other way than suppressing this error, otherwise TS will yell at us.
@brophdawg11 Looking at the code, I would say we could just map to preset.reactRouterConfig
's return value as according to the type of preset
, we'll always have a name
& reactRouterConfig
(which doesn't have a presets
property, so omit
can be removed as well purely type-wise)
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.
because a ConfigPreset
doesn't have a presets
key, right?
yeah thats awkward. you can cast as never
, or, safer, you could cast the source as ConfigPreset & {presets?: unknown}
personal preference i guess, though
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.
because a
ConfigPreset
doesn't have apresets
key, right?
Indeed.
you can cast
as never
Yeah I don't like casting, hence the expect-error
, but I guess @brophdawg11 can just tell me the preference of the team and I'll update to whatever is preferred
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'll defer to @pcattori for type preference questions
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 expect-error is nice because we'll get a type error if/when we fix types for ConfigPreset
, at which point we can clean this up. Whereas with a cast, that cast will likely live in the codebase forever.
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.
@pcattori That's indeed (one of) the reason(s) why I don't like casting.
the tests fail because configs can contain functions. particularly this test fixture:
we're currently cloning the options to avoid mutating them - this probably means we are holding 2 copies of the object in memory each time, which isn't the best. i wonder if we can achieve what we want through types rather than cloning the object (i.e. if this object gets passed to user code (i.e. a user/plugin/preset/etc can mutate it), that won't fly. but if it never leaves the bounds of react-router itself, we could probably do it. if it turns out we do need to deep clone, we could use klona |
@@ -389,7 +387,7 @@ async function resolveConfig({ | |||
} | |||
|
|||
// Prevent mutations to the user config | |||
reactRouterUserConfig = deepFreeze(cloneDeep(reactRouterUserConfig)); | |||
reactRouterUserConfig = deepFreeze(structuredClone(reactRouterUserConfig)); |
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 are only two uses of deepFreeze - here, and on a newly created object.
Given that deep freeze is already recursing the object, it seems like folding the cloning into that would potentially simplify things a bit (as well as saving a few cycles).
For the time being I'm going to close this so we an continue to discuss the proper solution in #13721 (comment). Once we've landed on a valid solution there we can evaluate it and re-open a PR. |
Alternative to #14111
I'm sure people from the wider @e18e ecosystem cleanup (like @43081j, @Fuzzyma & @outslept) will be very happy to see these kind of changes as well