Skip to content
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

Framework: Move localStorage polyfill to separate bundle #7232

Closed
wants to merge 5 commits into from

Conversation

aduth
Copy link
Contributor

@aduth aduth commented Aug 2, 2016

As discovered in #7038 and #6558 before it, our local storage polyfill loading behavior is very fragile, and I suspect we're doomed to repeat it in its current state. As such, this pull request seeks to separate the polyfill into a separate bundle to be included in the page prior to the main application bundle.

Testing instructions:

Verify that your primary browser and Safari Private Mode load Calypso without any errors in the console.

Open questions:

/cc @gwwar (fixed previous breakage) @blowery (tinkerer of Webpack)

Test live: https://calypso.live/?branch=add/polyfill-bundle

@aduth aduth added Framework [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. labels Aug 2, 2016
@@ -5,43 +5,41 @@ import { assert } from 'chai';

describe( 'localStorage', function() {
describe( 'when window.localStorage does not exist', function() {
const window = {};
delete global.localStorage;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like we should stub, or restore this value when the suite is done.

@gwwar
Copy link
Contributor

gwwar commented Aug 2, 2016

@gwwar
Copy link
Contributor

gwwar commented Aug 2, 2016

cc @mkaz for the desktop question

@aduth
Copy link
Contributor Author

aduth commented Aug 3, 2016

This line is causing the failed tests:

Indeed, though interestingly different failures when updating this line. We might instead need to change lib/local-storage back into exporting a function, though this would require additional logic in the server rendered markup to invoke. I'll plan to poke at this more tomorrow.

@aduth aduth force-pushed the add/polyfill-bundle branch from 2e90c58 to d402cf5 Compare August 3, 2016 16:16
@aduth
Copy link
Contributor Author

aduth commented Aug 3, 2016

Rebased and introduced a separate lib/polyfill module to better allow lib/local-storage to be used outside the context of the browser (e.g. test env setup) and more easily tested in isolation. Having a separate lib/polyfill module better aligns with "polyfill" as a bundle, rather than specifically to the localStorage polyfill (in case, for example, we want to include more polyfills, which hopefully is not the case 😄 ).

@gwwar
Copy link
Contributor

gwwar commented Aug 17, 2016

Whoops lost track of this one. I can test again after a rebase

@aduth aduth force-pushed the add/polyfill-bundle branch from d402cf5 to 9036fff Compare August 18, 2016 01:10
@aduth
Copy link
Contributor Author

aduth commented Aug 18, 2016

Thanks @gwwar , pushed a rebase to resolve merge conflicts.

I noticed that the conflicts were caused by the introduction of the ES6 function wrappers in #6117, which feels kinda similar in purpose. Do you think it would make sense to pull that into the "polyfill" bundle here? To be fair, those are more development mode utilities than polyfills. I dunno, maybe best to leave for a separate pull request in any case.

@gwwar
Copy link
Contributor

gwwar commented Aug 18, 2016

Do you think it would make sense to pull that into the "polyfill" bundle here?

Let's leave that for another PR

@gwwar
Copy link
Contributor

gwwar commented Aug 18, 2016

With a completely empty lib/local-storage/index.js file the polyfill chunk is still 385 kB in size in a development environment. Do we expect this amount of size overhead from webpack in the first chunk? cc @blowery

@gwwar
Copy link
Contributor

gwwar commented Aug 18, 2016

👍 I confirmed that browsing with private Safari browser does not lead to errors in Calypso on this branch.

The polyfill chunk size seems unreasonably large though, so we may want to investigate if an alternative webpack configuration can give us a lighter result.

@blowery
Copy link
Contributor

blowery commented Sep 2, 2016

@gwwar hmmm.. if it's an entry chunk, it'll include the loader bits from webpack, but 385 seems... crazy. What all is in there?

@aduth
Copy link
Contributor Author

aduth commented Sep 26, 2016

When building as production, it appears to be much smaller - Around 30kb without any minification or gzip (~5.5kb after). Inspecting generated bundle, most of this size is CoreJS polyfills for ES6 e.g. Object.assign.

@gwwar
Copy link
Contributor

gwwar commented Sep 26, 2016

30kb sounds much more reasonable. I'd be comfortable with merging this.

@gwwar
Copy link
Contributor

gwwar commented Oct 24, 2016

Checking in on this one, was there anything else that needed additional testing?

@aduth
Copy link
Contributor Author

aduth commented Oct 27, 2016

Checking in on this one, was there anything else that needed additional testing?

No, just haven't had a chance to circle back around to this. Will need to rebase and retest to account for changes in #8161.

@aduth
Copy link
Contributor Author

aduth commented Oct 31, 2016

Rebased to account for #8161. @blowery : Do you think this should be included in the vendor bundle? Currently it's separate.

Also, I'm not sure why it was needed previously, but I did not include the CommonsChunkPlugin updates as in the previous version (9036fff) and it still appears to work well. In fact, the development bundle size is much more reasonable, so that could explain why it was so large before.

import localStoragePolyfill from 'lib/local-storage';

export default ( () => {
if ( 'undefined' === typeof window ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this a little confusing. This is an IIFE that's exporting nothing. Could it just be an IIFE in the body of the module and explicitly export null or undefined instead? like

( () => { /*do the thing */ } )();

export default null;

or maybe even don't export anything?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hrm, just realized I may not understand how modules evaluate as well as I thought. Does code in the body of the module run before the module is required? Or just once on the first require?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right that we don't need or want the export default. The only other reason to keep it an IIFE is to allow the early return, since there can't be top-level returns in a module. Otherwise we could just put all the browser-specific polyfills inside the if block.

Or just once on the first require?

This is the intended behavior.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed IIFE export in ec93319.

@blowery
Copy link
Contributor

blowery commented Oct 31, 2016

re

Also, I'm not sure why it was needed previously, but I did not include the CommonsChunkPlugin updates as in the previous version (9036fff) and it still appears to work well. In fact, the development bundle size is much more reasonable, so that could explain why it was so large before.

Could you walk through that a bit more? I'm curious why the dev bundle would change in size at all.

@aduth
Copy link
Contributor Author

aduth commented Oct 31, 2016

@blowery To be honest, I don't recall why I felt the need to include it in CommonsChunkPlugin in the first place. Probably because I was referencing the approach for vendor. When rebasing, I "forgot" to include it again, yet it ran without issues and the size of the bundle was appropriate in development, so... ¯_(ツ)_/¯

@lancewillett
Copy link
Contributor

@aduth Want to keep this one active?

We plan close it soon as it is an older pull with no recent activity.

@aduth
Copy link
Contributor Author

aduth commented Jan 3, 2017

@lancewillett Yes, I'd still like to merge this in. It's reviewable in its current state as far as I can recall.

@gwwar
Copy link
Contributor

gwwar commented Jan 4, 2017

I'd be fine with 🚢'ing this after a rebase and another spot check.

@aduth
Copy link
Contributor Author

aduth commented Mar 9, 2017

Meh, static file has a number of downsides. Haven't decided whether they outweigh the need to create a separate config for such a small file though.

@blowery
Copy link
Contributor

blowery commented Mar 9, 2017

Yeah. I'd consider just inlining it honestly.

@aduth
Copy link
Contributor Author

aduth commented Mar 9, 2017

That's a good thought. In which case it acts more as an extension to what we have already for BrowseHappy?

@blowery
Copy link
Contributor

blowery commented Mar 9, 2017

That sounds cool.

@aduth
Copy link
Contributor Author

aduth commented Mar 17, 2017

My reluctance at this point stems from wariness to add more unminified JavaScript to the base index.jade file. The BrowseHappy stuff is already pretty non-ideal.

i'd probably bump this out to a separate webpack build entirely. This will be affected by things like the vendor dll / vendor chunk, commons plugins, etc.

Can you explain what you mean by this being affected @blowery ?

@blowery
Copy link
Contributor

blowery commented Mar 17, 2017

Just that it'll have to load after the manifest if its part of our normal webpack build. That's probably ok?

@gziolo
Copy link
Member

gziolo commented Mar 29, 2017

My question is why we don't migrate existing code to use localForage instead of localStorage?

@aduth
Copy link
Contributor Author

aduth commented Mar 29, 2017

My question is why we don't migrate existing code to use localForage instead of localStorage?

We should, but it's non-trivial since the leap from synchronous to asynchronous is not always well-defined. Since it's not obvious, also noting that most usage won't be uncovered from a search of localStorage but instead the store dependency we use to interface.

@gziolo
Copy link
Member

gziolo commented Mar 30, 2017

@gziolo
Copy link
Member

gziolo commented Mar 30, 2017

I did even more research and it looks like we would need sync wrapper for localforage that would work as drop-in replacement for store :D

I think your PR makes much more sense in this context.

@matticbot
Copy link
Contributor

@aduth This PR needs a rebase

@blowery
Copy link
Contributor

blowery commented Apr 13, 2017

yeah, there's a few places using it:

$ ag "require\( 'store'" -c && ag "from 'store'" -c
boot/index.js:1
layout/community-translator/launcher.jsx:1
layout/nux-welcome/index.js:1
lib/application-passwords-data/index.js:1
lib/desktop/index.js:1
lib/local-list/index.js:1
lib/plugins/store.js:1
lib/plugins/wporg-data/list-store.js:1
lib/posts/actions.js:1
lib/preferences/actions.js:1
lib/products-list/index.js:1
lib/signup/progress-store.js:1
lib/signup/flow-controller.js:1
lib/trophies-data/index.js:1
lib/user/user.js:1
my-sites/welcome/README.md:1
auth/controller.js:1
blocks/app-promo/index.jsx:1
layout/community-translator/invitation-utils.js:1
layout/masterbar/notifications.jsx:1
lib/abtest/index.js:1
lib/countries-list/index.js:1
lib/oauth-token/index.js:1
lib/olark/index.js:1
lib/sites-list/list.js:1
lib/user/support-user-interop.js:1
lib/wp/handlers/guest-sandbox-ticket.js:1
my-sites/invites/controller.js:1
my-sites/invites/invite-accept-logged-out/index.jsx:1
my-sites/pages/helpers.js:1
reader/sidebar/index.jsx:1

@gziolo
Copy link
Member

gziolo commented May 5, 2017

@aduth I rebased it with master.

@fabianapsimoes Can you test this branch with the scenario described in #6555 (comment)?

@klimeryk
Copy link
Contributor

With #13748 merged, this can probably be closed - unless we want to pursue this as the ultimate fix? Although, IMHO, #13748 seems solid enough (though, I'm probably biased ;)).

@aduth
Copy link
Contributor Author

aduth commented May 11, 2017

@klimeryk Sounds alright to me! We can always revisit if needed.

@aduth aduth closed this May 11, 2017
@aduth aduth deleted the add/polyfill-bundle branch May 11, 2017 23:48
@matticbot matticbot removed the [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. label May 11, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Framework [Size] L Large sized issue
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants