-
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
Build: Reference Lodash as an external module #5933
Conversation
I'm all for merging this to avoid a Lodash incarnation of the above issue in the future and as Core doesn't currently enqueue Lodash as it is only installed as part of npm Doing this now should be an easy win versus the latter alternative. |
Hah, I started writing exactly this a few minutes ago, before I thought to check if someone else had already done it. It looks like there are a few plugins that enqueue their own copy of lodash. We can probably reach out to those few plugin authors individually. |
I am also in favor, as our current approach is to bundle lodash in our custom blocks as well. To have lodash as an external library would reduce bundle size in the custom block world as well. |
b587ac5
to
75ba81f
Compare
Managed to get tests to pass again by faking a |
75ba81f
to
4a84919
Compare
Rebased again to include explicit references to Babel dependencies otherwise available only via implicit transitive dependency. I also noticed in some unrelated effort toward a Babel 7 upgrade that we'll need other changes to the Babel configuration, so it may be a good idea to group these upstream changes. I was asked in last week's Core JS meeting to justify the inclusion of Lodash, when core already includes Underscore, a similar library. Rather than reiterate common points, I'll simply defer to a well-abbreviated comparison discussion, with a summary of superiority in: features, documentation, testedness, maintenance, performance, consistency, adherence to the language specification (naming like I'll acknowledge that one of the original points for its inclusion was its modularity and being able to selectively import features (#289), which is very much ironic given the presence of this pull request to use the entire library instead. I'd not want to dismiss this possibility altogether, as its an area of continuous improvement (see Webpack 4's I'll let the pull request sit until a recap discussion in tomorrow's JS meeting, but I'd like to have this merged ahead of the next release unless there's objection. |
@aduth Thanks for the explanation. When I asked you to "justify the inclusion of Lodash" I wasn't really asking about underscore vs. lodash - although I appreciate your reasoning there. I was more asking whether its merits are sufficient to warrant not using the already bundled in WordPress underscore. Isn't underscore already being loaded on the post edit page for It sounds like you think they are... Great! If we are switching to Lodash, do you think that means we should switch that across core to avoid loading duplicate, redundant libraries? |
Discussed in this week's core JS chat: https://wordpress.slack.com/archives/C5UNMSU4R/p1523367666000160 Consensus is to move forward with this merge, and work toward migrating existing core usage of Underscore. Related Trac ticket: https://core.trac.wordpress.org/ticket/43733 |
4a84919
to
90d6e0b
Compare
This pull request seeks to reference Lodash as an external module (window global), rather than include in the build of each bundle.
Why?
a copy ofa good chunk of Lodash in each bundle, upwards of a dozen or more copies in fact. There was some hope that the introduction of Webpack 4 and its handling ofsideEffects
would enable us to at least properly "tree shake" to include only relevant Lodash modules. Preliminary testing, however, shows thatlodash-es
+sideEffects
actually increases end bundle size. Through some debugging, it appears that with Lodash's internal dependency structure, all of Lodash is included anyways in most cases, with additional overhead of linking modules (even concatenated). I think this warrants further exploration, though this has been time-consuming as-is, so may need to be deprioritized in favor of other pursuits.Why not?
_.noConflict
, though requires referencing Lodash on the global by its full namelodash
(not the_
shorthand).Results There is a total savings of 272.47kb of the total production (minified) bundle size, approximately 15.3% across all of Gutenberg's JavaScript bundles. Lodash's minified bundle is 71.4kb, making for a net savings of 201kb (11.2%). I believe this can be improved further with proper aliasing of
lodash-es
(see notes below).components/build/index.js
hooks/build/index.js
plugins/build/index.js
core-data/build/index
.jsviewport/build/index.js
data/build/index.js
utils/build/index.js
i18n/build/index.js
element/build/index.js
editor/build/index.js
date/build/index.js
edit-post/build/index
.jsblocks/build/index.js
Before: 1783.1 KiB
After: 1510.63 KiB
Lodash: 71.4 KiB
Net savings: 201 KiB (11.2%)
Implementation notes:
Babel Preset: We need to drop
babel-plugin-lodash
for this to work. It's not currently possible to extend our Babel preset configuration to omit this (even programmatically; I'm guessing it partially applies some behaviors upon being loaded?). I have inlined the Babel configuration into the Webpack configuration. This is obviously a temporary solution, and we should either drop this from the packaged Babel plugin, or otherwise allow to be configurable.lodash-es
: Redux includes a couple references tolodash-es/isPlainObject
. It would be ideal if these were consolidated to the external we have defined, aslodash.isPlainObject
. I expected the proposed configuration would work and, in fact, the built bundle (before minification) includes inline comments about Redux' usage being for an "external" module, though it still includes the module inline. I have not found a related issue, though I wonder if this may be a bug within Webpack. In any case, this does not add much weight, but is duplicated nonetheless, and there is opportunity for further savings.Testing instructions:
Verify there is no regressions in the build (including plugin-packed), and that the application loads and operates as expected.