Skip to content

Micro-optimize bundle size of PasswordToggleElement#7673

Merged
aduth merged 5 commits intomainfrom
aduth-js-optimize-password-toggle
Jan 24, 2023
Merged

Micro-optimize bundle size of PasswordToggleElement#7673
aduth merged 5 commits intomainfrom
aduth-js-optimize-password-toggle

Conversation

@aduth
Copy link
Contributor

@aduth aduth commented Jan 20, 2023

🛠 Summary of changes

Minor refactoring of a few files to simplify and optimize the size of JavaScript bundles, particularly the PasswordToggleElement implementation and its dependencies, toward a goal of reducing overall JavaScript size in critical paths (notably, the Sign In page).

For more detail, refer to individual commits for specific changes and rationale.

Performance Results

Reduces gzipped size of Password Toggle bundle from 933b to 558b (-40.2%).

We're starting to hit a point of diminishing returns, since even though 40.2% reduction sounds impressive, we're talking an absolute difference of about 0.4kb 😅

aduth added 5 commits January 20, 2023 16:03
micro-optimization: transpilation of args defaulting is slightly verbose. also results in marginal reduction of size of payload over the wire (see spec changes)
micro-optimization: shave a few characters "window"
micro-optimization: avoid error variable and "try' statement; minified output is also better able to collapse the preceding "if" statement
- more aligned with standards vs. object of elements
- less indirection, more direct access
- avoid decorator premature optimization
- micro-optim: avoid "elements" pass-through

changelog: Internal, Performance, Reduce size of JavaScript bundles
* @return Promise resolving once event has been logged.
*/
export async function trackEvent(event: string, payload: object = {}): Promise<void> {
export async function trackEvent(event: string, payload?: object): Promise<void> {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

For context, argument defaulting transpilation is a bit verbose. I expect this would correct itself once browser support for optional arguments is good enough to avoid the syntax downgrading.

Transpiled result:

async function(e) {
  let n = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {};
  // ...
}

Copy link
Contributor

Choose a reason for hiding this comment

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

My first thought was, why are we transpiling this? but wow default parameters only have 93% availability on canicuse, that is surprising

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is surprising!

There are ways we could optimize this a bit by telling Babel certain "assumptions", but I'm not overly stressed about it broadly speaking. Hopefully with having dropped IE support and targeting browser support percentage, it won't be too long before we can use the native syntax.

Copy link
Contributor

@zachmargolis zachmargolis left a comment

Choose a reason for hiding this comment

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

LGTM

* @return Promise resolving once event has been logged.
*/
export async function trackEvent(event: string, payload: object = {}): Promise<void> {
export async function trackEvent(event: string, payload?: object): Promise<void> {
Copy link
Contributor

Choose a reason for hiding this comment

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

My first thought was, why are we transpiling this? but wow default parameters only have 93% availability on canicuse, that is surprising


def valid_payload?
!log_params[:payload].nil?
params[:payload].nil? || !log_params[:payload].nil?
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should keep the server strict about these

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The payload is optional for both the Ruby and JavaScript versions of this API. Any reason it shouldn't also be optional for the JSON API?

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess that's right, but all events have extra attributes. I take my comment back

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'm not super happy with how the validation turned out here, since how Rails permit handling with a hash makes it so all invalid parameters (including a nil value) would be normalized to an empty hash, so it requires this juggling of both params and #permit'd log_params to allow omission while still rejecting anything other than a hash.

await fetch(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ event, payload }),
Copy link
Contributor

Choose a reason for hiding this comment

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

what if we used || to do what the default value did? it's still an overall character reduction right?

Suggested change
body: JSON.stringify({ event, payload }),
body: JSON.stringify({ event, payload: payload || {} }),

Copy link
Contributor Author

Choose a reason for hiding this comment

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

what if we used || to do what the default value did? it's still an overall character reduction right?

Yeah this would technically work and be reasonably effective at reducing overall size. To my other comment though, I guess I don't see the issue with omitting the payload if we have nothing to send.

@aduth aduth merged commit dc39657 into main Jan 24, 2023
@aduth aduth deleted the aduth-js-optimize-password-toggle branch January 24, 2023 13:36
@mdiarra3 mdiarra3 mentioned this pull request Jan 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants