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

Minify combined class names #248

Merged
merged 8 commits into from
Jul 19, 2017

Conversation

gilbox
Copy link
Contributor

@gilbox gilbox commented Jun 13, 2017

Hashes the combined class name to create a minified combined class name.

@lencioni
@xymostech
@jlfwong

src/exports.js Outdated
@@ -21,7 +21,6 @@ const StyleSheet = {
create(sheetDefinition /* : SheetDefinition */) {
return mapObj(sheetDefinition, ([key, val]) => {
return [key, {
// TODO(gil): Further minify the -O_o--combined hashes
_name: process.env.NODE_ENV === 'production' ?
`_${hashObject(val)}` : `${key}_${hashObject(val)}`,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since this is going to be joined and hashed again, we can probably remove the leading underscore here now, right?

@gilbox
Copy link
Contributor Author

gilbox commented Jun 13, 2017

ping @lencioni addressed your comment and added other improvements

@gilbox
Copy link
Contributor Author

gilbox commented Jun 16, 2017

ping @xymostech

Copy link
Contributor

@xymostech xymostech left a comment

Choose a reason for hiding this comment

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

Like @jlfwong mentioned in this comment: #246 (comment) we maybe want to be generating longer hashes now that we're combining class names, since we're increasing the risk of collisions. Unfortunately, it looks like the library we're using for hashing doesn't support generating longer hashes... Hmm. Does anyone have insight into how we might do that in a good way?

src/util.js Outdated
@@ -132,7 +132,7 @@ export const stringifyAndImportantifyValue = (
// ordering of objects. Ben Alpert says that Facebook depends on this, so we
// can probably depend on this too.
export const hashObject = (object /* : ObjectMap */) /* : string */ => stringHash(JSON.stringify(object)).toString(36);

export const hashString = (string /* : string */) /* string */ => stringHash(string).toString(36);
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you maybe add a quick docstring here, and maybe use this function inside of hashObject so it's clear that they're supposed to be using the same hash algorithm?

@csilvers
Copy link
Member

If you need more than 32 bits of hash, you're kinda stuck, since js doesn't provide 64-bit integer types.

You could go back to using a google hash: https://github.com/lovell/farmhash e.g. It has fingerprint64() which gives you a 64-bit hash (as a string), and is platform independent. I don't know how fast it is, though.

Your only other solution would be to generate two separate 32-bit hashes and concatenate them. The most straightforward way to do this, if you're always hashing the same kind of object, is to add a 'salt' field to the object, and hash it once with salt=1 and a second time with salt=2 (or whatever).

Of course, this will double your hashing time. farmhash is probably faster. :-)

@csilvers
Copy link
Member

(Blah, maybe not possible -- it looks like farmhash is node-specific, and just a wrapper around some C code.)

src/inject.js Outdated
if (process.env.NODE_ENV === 'production') {
className = processedStyleDefinitions.classNameBits.length === 1 ?
`_${processedStyleDefinitions.classNameBits[0]}` :
`_${hashString(processedStyleDefinitions.classNameBits.join())}`;
Copy link
Collaborator

Choose a reason for hiding this comment

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

What if we append processedStyleDefinitions.classNameBits.length? That would help reduce the likelihood of collisions.

@gilbox
Copy link
Contributor Author

gilbox commented Jul 11, 2017

ping @xymostech @lencioni
I implemented something similar to @lencioni's suggestion but instead of using the length of processedStyleDefinitions.classNameBits.length I used the combined length of the stringified style definition objects since they probably exhibit more variation. However, that length is modded by 36 so that there is only one additional byte added. (see af553e3)

Copy link
Collaborator

@lencioni lencioni left a comment

Choose a reason for hiding this comment

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

This seems good to me, but it looks like CI is red.

@xymostech what do you think?

@@ -243,6 +243,12 @@ const processStyleDefinitions = (
}
};

// Sum up the lengths of the stringified style definitions (which was saved as _len property)
// and use modulus to return a single byte hash value.
Copy link
Collaborator

Choose a reason for hiding this comment

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

This comment would be 💯 if it explained why we are adding the length to the hash.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

let className;
if (process.env.NODE_ENV === 'production') {
className = processedStyleDefinitions.classNameBits.length === 1 ?
`_${processedStyleDefinitions.classNameBits[0]}` :
Copy link
Contributor

Choose a reason for hiding this comment

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

should we maybe be adding the length of the style definitions when there's only one class name, too? If only to make the hashes the same size/consistent?

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 sure what the advantage of that would be. Also, before this PR the hashes were different lengths--for example, from our homepage:

image_ay4wjb-o_O-background_1h6n1zu-o_O-fadeIn_3jddj2-o_O-backgroundSize_cover_176vplr

--so I imagine they still won't be the same size.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oh, the other thing is that we'd be hashing a hash unnecessarily. is the additional expense justified?

Copy link
Contributor

Choose a reason for hiding this comment

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

We wouldn't be hashing anything new, just adding the extra length char on, right? You're right though, this probably isn't important. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oh, you're right double-hashing shouldn't be a thing

@xymostech
Copy link
Contributor

I think the travis failing was a fluke, I restarted it

@xymostech
Copy link
Contributor

Okay, I'm gonna merge this! Sorry for the delay! Maybe once this lands, @lencioni or I could try updating aphrodite on our sites and see if anything breaks and how much smaller the styles get.

@xymostech xymostech merged commit 7f9f602 into Khan:master Jul 19, 2017
@lencioni
Copy link
Collaborator

That sounds good. I actually work with @gilbox so I'll let him do the honors on our site and report back here with anything interesting. 💃

@xymostech
Copy link
Contributor

Oh ha, I didn't realize! Sounds wonderful :)

@gilbox
Copy link
Contributor Author

gilbox commented Jul 31, 2017

@xymostech could we get a release please 🙏

@xymostech
Copy link
Contributor

@gilbox Did you test things out on your site? I can make a release but I'd love for someone to do some real testing to make sure this doesn't horribly break things...

@gilbox
Copy link
Contributor Author

gilbox commented Aug 1, 2017

ah ok I didn't realize that's what you meant. I'll give it a whirl

gilbox pushed a commit to gilbox/aphrodite that referenced this pull request Aug 2, 2017
@gilbox
Copy link
Contributor Author

gilbox commented Aug 23, 2017

I tested with #263, should be good to publish a new version

@gilbox
Copy link
Contributor Author

gilbox commented Aug 25, 2017

ping @xymostech for the new version

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants