Skip to content
This repository has been archived by the owner on Feb 8, 2018. It is now read-only.

Cleanup assets serving #1969

Merged
merged 9 commits into from Apr 12, 2014
Merged

Cleanup assets serving #1969

merged 9 commits into from Apr 12, 2014

Conversation

zwn
Copy link
Contributor

@zwn zwn commented Feb 1, 2014

First commit in this PR fixes https://app.getsentry.com/gittip/gittip/group/13299458/ where we have so far 7.4k of exceptions. The trouble there has been that we were trying to set last modified time even on responses other than 200 (404 for example).

Second commit unifies our http caching strategy (#1555). Before we had two kinds of assets - long term and short term (versioned). For the long term, where we would want the maximum caching, we were not setting expire time. That means that the browser cannot know if the cached version is current or not without a hit to the server. We try to respond with 304 (not modified) but it is still a hit. Moreover we respond 304 not often enough because the decision to do so is based on mtime of the file. With each deploy possibly a new git checkout is made which results in mtime of 'now'. To conclude, the files we would want to be cached the most, were not.

Now all assets have far future expire time that allows the most caching. Our versioned assets (served from assets/%version/*) are invalidated with each deploy automatically. The other assets need to have their own version embedded in url (which is the case with jquery already).

Third commit makes a run to move all assets to CDN. What is not done yet a references from css files where I was not sure how to do the url expansion for website.asset_url.

Fourth folds separate css files into our main gittip.scss file to reduce the number of http requests to make the site speedier.

I'd appreciate a full review and thorough TTW test before merge & release. Thanks.

cc: @seanlinsley @clone1018 @duckinator

@zwn
Copy link
Contributor Author

zwn commented Feb 1, 2014

I have found some more files (more than I thought there were) that reference /assets/ directly so the move to CDN is not complete yet. But we are closer than before 😄. I do not want to stall this on the totality of the move to CDN.

@zwn
Copy link
Contributor Author

zwn commented Feb 1, 2014

cc @galuszkak @Changaco @sim6 - just trying to remember who could be interested in this PR. Anyone feel free to ping anyone else.

@zwn
Copy link
Contributor Author

zwn commented Feb 1, 2014

I was aiming to get a better score at
https://developers.google.com/speed/pagespeed/insights/?url=www.gittip.com&tab=desktop
http://www.webpagetest.org/result/140131_C7_STD/1/details/
We should be better in both after we deploy this.

@galuszkak
Copy link
Contributor

Looking onto this.

@galuszkak
Copy link
Contributor

Ok I have only one proposal. Wouldn't be better to write template tag/extension to jinja to create assets url (which will do "{base_url}{asset_url}".format(base_url=website.asset_url, asset_url=url) )? it will look something like that:

"{% url '/icons/twitter.16.png' %}"

Than this:

"{{ website.asset_url }}/icons/twitter.16.png"

this will remove also typo problems if we do something accidentally in variable. What do you think @zwn ?
I think this will be more clear and consistent than remember whole variable name.

@zwn
Copy link
Contributor Author

zwn commented Feb 1, 2014

I probably wouldn't mind having something like that. However the added value for me does not outweigh the time I'd spent learning how to do it. Typo problems will be caught by tests anyway and I use auto completion of my editor. So as I said before, maybe nice to have but for me definitely not worth the effort (since I have almost no idea how jinja does its magic).

@zwn
Copy link
Contributor Author

zwn commented Feb 1, 2014

@seanlinsley
Copy link
Contributor

This has been sitting for 8 days. I'm going to review this and try and get it merged today.

@chadwhitacre
Copy link
Contributor

!m @seanlinsley


response.headers['Expires'] = 'Sun, 17 Jan 2038 19:14:07 GMT'
last_modified = get_last_modified(request.fs)
response.headers['Last-Modified'] = format_date_time(last_modified)
Copy link
Contributor

Choose a reason for hiding this comment

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

This approach worries me because it sets the Expires header to the far future for all assets, not just the ones in the %version directory. That means that if any of those files change content but not name, we're very likely to break the website for some users.

Is there a reason we're not versioning all of our assets? If it means that when we deploy everyone has a 100% cache miss on their first page load, that doesn't sound so bad.

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 tried to address this in the description of this PR (second and mainly third paragraph). Can you reread it and come back to me if still does not make sense? Thanks.

Copy link
Contributor

Choose a reason for hiding this comment

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

Our versioned assets (served from assets/%version/*) are invalidated with each deploy automatically. The other assets need to have their own version embedded in url (which is the case with jquery already).

That works for jQuery, but there are many other files there that don't have a version number in the file name.

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 is stopping us from adding one when we update them? Or do you feel that putting all of them under the %version header is better?

Copy link
Contributor

Choose a reason for hiding this comment

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

You're suggesting that, for example, if Open Street Map makes a new logo, we'd add it as www/assets/openstreetmap-2.png? A year from now, I doubt we're going to remember to do that.

I think I'd prefer for everything to be under %version. It means a 100% cache miss on the first page after a new deploy, but every page after that has a 100% cache hit (for assets at least).

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

@zwn I'd say go for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I will. Is there anything else standing in the way of merging this?

Copy link
Contributor

Choose a reason for hiding this comment

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

No, we should be good to go.

Looking at the timestamps, it's now been 6 days since we last talked. Is this still on your radar? If not, I'd be happy to do the last bit of work.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Still on the radar (I would eventually get to it). But feel free to jump in, I'll try to help with the big 'elsewhere' and 'coinbase' PRs.

@chadwhitacre
Copy link
Contributor

@zwn Update on this? You are busy, or burned out on Gittip, or something. Haven't seen you for a week or two. :-) Everything okay?

@chadwhitacre
Copy link
Contributor

We did a little bit of assets rearranging in #2142 ff.

@clone1018
Copy link
Contributor

I'll be taking over this PR in @zwn's absence.

@zwn
Copy link
Contributor Author

zwn commented Mar 15, 2014

@clone1018 Go ahead. Yeah, I've been busy with other stuff. Hope to be back soon.

@@ -24,7 +24,7 @@
/* @group Single Chosen */
.chzn-container-single .chzn-single {
background-color: #ffffff;
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0 );
filter: unquote("progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0 )");
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the purpose of the unquote here?

Copy link
Contributor

Choose a reason for hiding this comment

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

Presumably to support importation into the SCSS file?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, unquote is commonly used to bypass the SCSS parser for IE-specific hacks.

@seanlinsley seanlinsley assigned seanlinsley and unassigned clone1018 Apr 5, 2014
@seanlinsley
Copy link
Contributor

@clone1018 as frustrating as the recent downtime was for me, I can't let this PR sit stale any longer. I'm going to try and get this finished up today.

@seanlinsley
Copy link
Contributor

Rebased on master (2a26dc9 -> 24ad470)

@@ -99,6 +98,9 @@ def __init__(self, db, api_key, api_secret, callback_url, api_url=None, auth_url
elif api_format:
raise ValueError('unknown API format: '+str(api_format))

# TODO: make this use website.asset_url!
self.icon = '/assets/icons/%s.16.png' % self.name

Copy link
Contributor

Choose a reason for hiding this comment

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

@whit537 thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

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

Got this sorted with @pjz's help in IRC

@seanlinsley
Copy link
Contributor

Besides the failing tests and gittip/elsewhere/__init__.py, this is complete 🍺

@whit537 IRT #1767, the first widget relies on an old version of jQuery that hasn't been provided for a long time :-/

zwn and others added 6 commits April 6, 2014 11:41
Note that while rebasing this commit, I (@seanlinsley) added
a good deal of extra changes since we were still using
the static "/assets/foo" URL in a lot of other places.
This doesn't version the old widgets because people may still be using
them. (ref: #1767) Except... the first widget refers to an old version
of jQuery that we haven't provided in a long time :-/

This commit also fixes reset.css and chosen.css to correctly load.
and start using that name for `asset_version_url`
@seanlinsley
Copy link
Contributor

Reabsed on master after #2242 (7bebe6b -> 8e3defc)

@seanlinsley
Copy link
Contributor

So, the tests are failing because they don't have access to website. How do I fix that?

@chadwhitacre
Copy link
Contributor

@seanlinsley The hacky way to fix that is to change get_avatar_url to take a second parameter, and pass website in every place we call get_avatar_url. A cleaner solution would require more refactoring than I think we want to get into here.

@seanlinsley
Copy link
Contributor

What sort of refactoring would make it so that's not required?

@chadwhitacre
Copy link
Contributor

@seanlinsley This is an old PR. I don't think we should block on any refactoring here.

@seanlinsley
Copy link
Contributor

You didn't answer my question :-P. I'm genuinely curious what you had in mind.

that way it has access to the website object by default
clone1018 added a commit that referenced this pull request Apr 12, 2014
@clone1018 clone1018 merged commit 9f6e573 into master Apr 12, 2014
@clone1018 clone1018 deleted the fix-cache branch April 12, 2014 22:12
@seanlinsley seanlinsley mentioned this pull request Apr 13, 2014
@chadwhitacre
Copy link
Contributor

Very happy this is out, thank you! 💃

!m @zwn @seanlinsley @clone1018

@seanlinsley seanlinsley mentioned this pull request Apr 27, 2014
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants