-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Lodash: Remove completely from @wordpress/viewport
package
#44572
Conversation
Size Change: +2.36 kB (0%) Total Size: 1.27 MB
ℹ️ View Unchanged
|
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.
LGTM, another package down 🙂
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 migrated code is correct but almost always Object.entries
is called too often and could be called just once by moving it out of a loop.
return select( store ).isViewportMatch( query ); | ||
} ); | ||
return Object.fromEntries( | ||
Object.entries( queries ).map( ( [ key, query ] ) => { |
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.
A little optimization idea: in both versions of withViewportMatch
, we could extract the Object.entries
call so that it's executed only once when creating the HOC, not on each render or state update.
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.
Done as part of 7f17ee9.
packages/viewport/src/listener.js
Outdated
breakpoints, | ||
( result, width, name ) => { | ||
const queries = Object.entries( breakpoints ).reduce( | ||
( result, [ name, width ] ) => { | ||
Object.entries( operators ).forEach( |
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.
Here operators
is a constant, so Object.entries( operators )
could be moved out of the loop.
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.
Done as part of 7f17ee9.
packages/viewport/src/listener.js
Outdated
const queries = reduce( | ||
breakpoints, | ||
( result, width, name ) => { | ||
const queries = Object.entries( breakpoints ).reduce( |
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 queries
object is used only inside the setIsMatching
callback, where it's de-objectified with Object.entries
. What if it was an [ [ string, MediaQueryList ] ]
from the beginning? This could be achieved with .flatMap
instead of .reduce
:
queries = Object.entries( breakpoints ).flatMap( ( [ name, width ] ) => {
return operators.map( ( [ operator, condition ] ) => {
const list = window.matchMedia( ... );
list.addListener( ... );
return [ `${ operator } ${ name }`, list ];
} );
} );
By the way TypeScript flags list.addListener
as deprecated and MDN recommends list.addEventListener( 'change', fn )
instead.
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.
breakpoints, | ||
( result, width, name ) => { | ||
const matches = Object.entries( breakpoints ).reduce( | ||
( result, [ name, width ] ) => { | ||
Object.entries( operators ).forEach( |
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.
Here both operators
and breakpoints
are also static and Object.entries
could be lifted 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.
Done as part of 7f17ee9.
3c12dc9
to
7f17ee9
Compare
@jsnajdr thanks for the suggestions, mind taking another look? |
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.
Just one more bug to fix and we're finished 😉
}, | ||
{} | ||
); | ||
const matches = breakpointEntries.flatMap( ( [ name, width ] ) => { |
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 a missing Object.fromEntries
here. The setIsMatching
action expects an object.
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.
Good find. Would have been useful to have a test to catch this.
Addressed in 92e074e
} ); | ||
return Object.fromEntries( | ||
queryEntries.map( ( [ key, query ] ) => { | ||
return [ key, select( store ).isViewportMatch( query ) ]; |
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.
Maybe the select( store )
call could be extracted out of the loop, too, if you think it makes sense.
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 think I'm leaning towards keeping it as-is. Do you see any potential big performance improvements from that 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.
Not really, it's just a double map lookup, equivalent to registry[ store ][ method ]
. On the other hand, Object.entries
is in a different ballpark, it would allocate and deallocate memory on each loop iteration.
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?
This PR removes all of the Lodash from the
@wordpress/viewport
package, including thelodash
dependency altogether. There are just a few usages and they're straightforward to replace.Why?
Lodash is known to unnecessarily inflate the bundle size of packages, and in most cases, it can be replaced with native language functionality. See these for more information and rationale:
@wordpress/api-fetch
package haslodash
as a dependency #39495How?
We have to deal essentially with 2 methods (
mapValues
, andreduce
), and migration away from them is pretty straightforward, especially because the functionality is covered by unit tests.Testing Instructions