GSA / code-gov-web

DEPRECATED 🛑- Federal Source Code policy implementation.
Other
407 stars 108 forks source link

Site is slow to load. #129

Closed slightlyoff closed 5 years ago

slightlyoff commented 8 years ago

Hi,

A Chrome engineer here. I noted a twitter discussion about this project and decided to trace the loading of the site on a moderate connection (emulated 3G) on moderate hardware (a ~$200 Moto G4).

The resulting chrome:inspect trace shows that an inordinate amount of script is running, delaying first load considerably: https://chromedevtools.github.io/timeline-viewer/?loadTimelineFromURL=https://dl.dropboxusercontent.com/u/6792555/code.gov/code_gov_3G_moto_g4_first_load_TimelineRawData-20161104T161147

The site appears to load ~270K of JS (~1.1MB unzipped) which blocks rendering for several seconds in the trace above. This seems, perhaps, excessive.

jakearchibald commented 8 years ago

To add some detail: what you're seeing there is 18 seconds until meaningful content is displayed on real hardware. 6.5s of which is execution time which can't be solved by caching.

The majority of the content here could be served as HTML, which (along with preloading the font) would bring the same test down to around 5 seconds. Inlining of primary CSS would knock further seconds off that.

dracos commented 8 years ago

Here is a forked static site version I just knocked up: https://dracos.github.io/code-gov-web/ By scraping the site with selenium: https://github.com/dracos/code-gov-web/blob/gh-pages/scrape It removes the JS, outlines the inline CSS, and turns all the hash links into normal links. I also shrunk the front page press images. Visual comparison of loading here: https://www.webpagetest.org/video/compare.php?tests=161104_G2_HZ6,161104_JA_HZ7 Hope that's of interest.

jakearchibald commented 8 years ago

@dracos hah, wow, yes that shows the potential benefits nicely

lukad03 commented 8 years ago

@slightlyoff Code.gov is built in Angular - what you're seeing is the bootstrapping process of the app. There are alternative solutions in Angular to prerender the pages and bootstrap the app while the User is already on the page (i.e. Angular Universal, but we're quite limited by our infrastructure (as it relates to authorizing deployment of our app to something like Cloud.gov) so that may be out of our grasp for some time.

There is likely room for performance optimization somewhere between removing all JS and what we have currently, so we'll look into that as well.

In it's current state, static HTML files would work just fine. We're using a temporary solution that has our API output the repos to a repos.json file in the project directory, so each time that job is run we could also run this one.

Once the API is live though, we'd have to ensure that the static files are in-sync with the contents of the API. This could get quite messy. Will discuss with the team.

jakearchibald commented 8 years ago

@lukad03 which parts of the code.gov homepage depend on API data?

dracos commented 8 years ago

Computers are good at keeping things in sync :) You may be interested in seeing how one of our projects uses webhooks extensively to keep its associated website up to date at http://docs.everypolitician.org/bot.html e.g. https://medium.com/@everypolitician/i-keep-the-index-up-to-date-a147b4c0dac2 , https://medium.com/@everypolitician/i-webhooks-pass-it-on-703e35e9ee93#.laeyfocqj or https://medium.com/@everypolitician/how-i-build-the-everypolitician-website-6fd581867d10#.lt5f28cs4

If your API has webhooks, then you could potentially do something similar, or a simple script that ran regularly and automatically regenerate if the data in the API changes. I can run that for you if you like, all it would presumably do would be to generate a Pull Request on github if anything had changed, so no issue in touching any government infrastructure… ;)

The many benefits to the user of a full static site, in terms of performance, simplicity, better URLs, and progressive enhancement, plus it still fits in your limited infrastructure, to me far outweigh any developmental issues – to me, it's a similar issue to the issue of massive web page bloat. If you're suggesting that your aim is to make the site fetch directly from an API client-side in order to generate its search results, then I would please encourage you to reconsider. Thanks for your time.

NekR commented 8 years ago

@lukad03

@slightlyoff Code.gov is built in Angular - what you're seeing is the bootstrapping process of the app.

No offense but this isn't really an excuse for users, they don't care what you use. But if we are talking from dev perspective (which is wrong anyway), why do you use knows-to-be-very-slow Angular here? This app seems pretty new to me and could use any of more faster frameworks on none at all.

jakearchibald commented 8 years ago

@mikeptweet that seems slower than @dracos' build. What is your's doing and what are the benefits?

lukad03 commented 8 years ago

@NekR no offense taken!

Angular isn't the fastest framework out there, but it's comprehensive, consistent (in implementation via Typescript), and is ready to support the future of Code.gov. There is plenty of content out there about choosing the best JS frameworks and why to use each (I don't think this is the forum for that), but this is one of many factors to take into account when building a product that's useful to your Users.

In this case, how does the current load time effect the product‘s ability to deliver value to Users? Now that we've launched, our next steps are to evaluate this issue and others and figure out how we can better enable Users to derive value from use of this product. Depending on the severity of the effect, we'll release updates that address the problem to the best of our abilities. Unless this is drastically impacting the value of the Product, I hope to stick with the current framework and encourage anyone to make pull requests that help address this issue.

NekR commented 8 years ago

I indeed didn't mean to start "my framework is best". There is no best one. You just mentioned yours and said it's slow because framework does some of its things. No one here says "go rewrite this app". Just trying to point out that performance must be in mind and that it's really important.

I many times heard "What if our users don't need performance?", "What if we don't develop performance critical apps?". How so? Maybe those apps are for other computers though, then fine :-)

Anyway, I never saw people liking waiting while an app (native/web/whatever) is booting or loading.

In this case, how does the current load time effect the product‘s ability to deliver value to Users?

I don't have stats, but I'm pretty sure @slightlyoff or @jakearchibald have some links. Basically performance matters and users don't like waiting. Do you like waiting?

Okay, to sum things up: It's great that this issue will be evaluated, it's just weird to me to hear "This framework making things slow" and then "But we like it, it makes our live easier because of ...".

lukad03 commented 8 years ago

@NekR I don't think you were starting a framework is best discussion, so no worries.

We didn't choose Angular because we prioritize making our lives easier over the quality of our user experience, and I hope I didn't lead you to that conclusion. Lots of factors went into our decision making, and we think there are opportunities to improve the load performance of the current stack. If we exhaust all options, we'll revaluate the stack top to bottom.

I'm merely suggesting that app performance is one of many metrics we're monitoring, and that we're prioritizing performance improvement alongside other metrics - quality content, quality ux post-page load, etc. At the end of the day, the thing that's most important to our team is delivering a quality product to our users.

uncompiled commented 8 years ago

In this case, how does the current load time effect the product‘s ability to deliver value to Users?

I'm curious to explore federal government open source projects, but as a user, the current load time manifests itself as a fiscally tangible portion of my non-unlimited data plan.

Now that we've launched, our next steps are to evaluate this issue and others and figure out how we can better enable Users to derive value from use of this product.

The README suggests that this website is primarily an "inventory of the government's custom code to promote reuse between agencies", but will also "provide tools to help government and the public collaborate on open source projects". While the current iteration of the website could work using a static site generator, what type of tools will be built on top of Angular?

Please note that I have no intention of being adversarial regarding the use of Angular. I'm genuinely curious about the scope of this project. I think this is a great idea that brings visibility to government adoption of open source software -- I just want it to load faster.

lukad03 commented 8 years ago

@uncompiled Great question!

Currently code.gov is pulling in repo data from a precompiled repos.json file. The intent however is to use the code-gov-api in realtime - pulling in repo data commits/issues/etc. that are being made to show developers the latest that's happening in govt. open source. For a variety of reasons (none technical), we're not able to leverage the API until we've received the appropriate approvals to do so. When we find a path forward on the API, our full intent is to leverage the best of Angular to fetch this data in realtime (via search, listing latest activity, etc.). There's also an opportunity to explore how Agencies might use Code.gov which could involve posting data to the API as well.

jakearchibald commented 8 years ago

But surely something can be rendered before the API responds. Something better than a spinner.

lukad03 commented 8 years ago

@jakearchibald We're looking at performance gains for bootstrapping Angular first to see how far that will get us. Angular Universal is able to precompile and bootstrap the app while Users view and interact with the precompiled pages. Since we don't have access to a server for the time being though, we'll have to explore other ways to pre-render and simultaneously bootstrap the app if the performance gains we're working on don't significantly improve the load time.

samccone commented 8 years ago

Hi,

Sam here 🐐 .

@jeffbcross swung by my desk and asked if I had a moment to take a look at the site performance. Since Jeff told me @robwormald is looking into fixing the angular issues with the template compilation, we decided to take a look at the other bottlenecks on the site ignoring the angular issues.


There are a few simple wins here that can get you to first paint even faster. When paired with Rob's fixes I think you will be in good shape.

Here are the findings.

image00

If we look at your critical path, we see that we are spending around 1.6seconds before we ship the first frame. The question is why? And what can we do to get a frame shipped faster.

image01

The HEAD is a very special place to the browser. By putting some resources in the head the browser prioritizes these resources as render blocking 🚫 (until they are done downloading) Now for most of the scripts you have marked these as async or defer which avoids this problem, however you still have two external stylesheets which are going to block the initial paint until they complete. You also have an inline script tag for google tag manager that is going to block the parser until the script execution is complete.

To fix these problems the following approaches can be taken.

  1. Move the stylesheets out of the head and inline your critical css using a tool like https://github.com/addyosmani/critical during your build process.
  2. Move the inline script tag to the bottom of your page or.. Make it an external script tag marked with defer or async.

Digging in further we see that the browser ships the first frame right after the flag.svg downloads

image02

For some reason the flag download is taking quite a long time. Instead of using an external svg consider inlining the svg in the page to avoid this delay. If you can not do that also consider using link rel preload
https://www.w3.org/TR/preload/ to tell the browser that the priority of this resource should be increased.

Onto the font download + flash of no fonts. Looking at the network waterfall in devtools we see that your font download is kicked off pretty late (started after the stylesheet is parsed). It is possible to kick this off much sooner using Font Loader api that is shipping browsers today. https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSet/load

image03

You can also use link rel preload in this case also to bump the priority of the font download to start much sooner.

I think with some of these fixes applied you will be in great shape.

jeffbcross commented 8 years ago

Thx @samccone. I'm gonna experiment/measure some of the other recommendations and send some PRs.

dracos commented 8 years ago

It's great that there are ways to improve the initial page painting, and other improvements, I hope they're successful.

Just as an additional anecdata point: I have had a power cut all day today so far due to a blown junction point. I thought I'd take a look at the site again on my mobile, which in my house has a connection that moves between H+ and H (3.5G), occasionally dropping down as far as E (2G). The first time I tried to load the site, I got the loading flag and nothing more; I assume a connection switch interrupted something (presumably the JS) loading and not completing. The second time, I didn't even get the loading flag, it just stuck loading. The third time, again loading flag and nothing more. The fourth time, the site did eventually load. Hope that's of interest.

jcastle-zz commented 6 years ago

Code.gov is regularly being optimized for speed. Closing this now.

dracos commented 6 years ago

Thanks for reminding me of this. I just looked at the current code.gov on webpagetest with a Cable connection and it took 7 seconds before it displayed anything besides a wavy flag,: https://www.webpagetest.org/video/view.php?id=180202_DF_fa05798b3a9d754071c657ef9fbd861d.3.0 https://www.webpagetest.org/video/compare.php?tests=180202_DF_fa05798b3a9d754071c657ef9fbd861d-r:3-c:0

Downloading over half a meg of JavaScript before rendering anything isn't to me a good first impression, but I'm not sure what other things have changed since this ticket was opened. As @jakearchibald said: "But surely something can be rendered before the API responds. Something better than a spinner." I suggest there potentially might still be some room for improvement there :)

DanielJDufour commented 6 years ago

I'm reopening this. Exploring AOT, defering stylesheets and other suggestions mentioned above.

DanielJDufour commented 5 years ago

Thank you everyone for your advice and suggestions. We re-wrote the front-end of code.gov, which you can find at https://github.com/GSA/code-gov-front-end. The performance is much improved, but still far from perfect. I've created some specific issues to improve performance like shrinking the images:

Please add your suggestions as issues at https://github.com/GSA/code-gov-front-end/issues. Thank you and have a great day.

I'm also closing this issue as this repo is about to be archived.