skip to Main Content

So I’ve been checking out Chrome’s new Audits panel with Lighthouse, and slowly been improving my site’s metrics. It currently sits at 95 (performance), 97 (accessibility) and 75 (best practices).

I started going through the recommendations, and clicked the “learn more” links on several sections. As a result, I’m now reading through the Google Developers website. However the two articles that are specifically of importance for my question, are Render-Blocking Resources and Render-Blocking CSS.

From the Render-Blocking Resources article, here is the most important excerpt (the CSS article as a whole essentially carries on with this in more detail):

  • For critical scripts, consider inlining them in your HTML. For non-critical scripts, consider marking them with the async or defer attributes. See Adding Interactivity with JavaScript to learn more.
  • For stylesheets, consider splitting up your styles into different files, organized by media query, and then adding a media attribute to each stylesheet link. When loading a page, the browser only blocks the first paint to retrieve the stylesheets that match the user’s device. See Render-Blocking CSS to learn more.
  • For non-critical HTML imports, mark them with the async attribute. As a general rule, async should be used with HTML imports as much as possible.

Now, in order for my site to achieve its current scores, here is what is currently in place. (I should note that I do plan on taking advantage of them all, if possible. This is simply as the site currently stands.)

Current Implementations

  • The site is 100% designed to be mobile-first, and is compatible with device resolutions ranging from 240 pixels up to 3840 pixels in width. I am using adaptive design, with a few breakpoints.
  • I’m using HTTPS.
  • I’m using icon sprites.
  • I’m using non-minified CSS and JavaScript, split into several files, because the site theme is still under development. The CSS files contain media queries.
  • <a> elements are using target="_blank" and rel="noopener" is absent.
  • <script> elements are not using async or defer attributes.
  • I’m not using HTTP/2, or service workers.
  • I have enabled GZIP compression via cPanel (“Optimize Website”), targeting all content. (I am prepared to limit this to just HTML, PHP, CSS, JavaScript, plain text and XML, if the average load times are faster [I plan on running a benchmark to test both scenarios by loading the site 10 times for each — I haven’t had a chance to test this yet].)

The Problems

The main CSS file is fairly large (currently 75 kiB). On-top of that, there is the jQuery file that is already minified (95 kiB), plus several smaller CSS files which are specific to certain areas of the site. Users are also expected to view multiple pages within a single visit due to the nature of my site (a microprocessor information repository).

In order to comply with the outlined guidelines above, I’m contemplating splitting up the CSS files to not only be dependent on the section of the site as they currently are, but also by media query, linking to them with <link> elements using the media attribute, versus queries within the CSS files themselves.

For JavaScript, I’m thinking about grouping all async scripts together in one file, and all defer scripts together in another. I’m assuming there are no problems with grouping the jQuery API code with other self-written functions?

Okay. There are my plans, but in taking a step back for a moment and thinking about how this would be implemented, a couple of questions were brought to my attention, and I was hoping you guys could help me decide. This kind of thought process is very new to me (also partly because I’ve never had a site of this size before), so any input would be great.


The Questions

  1. Since all CSS files are downloaded, irrespective of whether they are used, I’m not sure whether one large main CSS file is the best way to go, or whether to have more HTTP requests and split it up by media type/query and section of the site. Regardless of the method, CSS will be minified.

    <link rel="stylesheet" href="reset-min.css"> <!-- ~ 1.5 kiB; all media types -->
    <link rel="stylesheet" href="layout-min.css"> <!-- ~ 50 kiB; internal @media -->
    <link rel="stylesheet" href="color-min.css"> <!-- ~ 25 kiB; internal @media -->
    
    <!--
        3 HTTP requests; 76.5 kiB
        Main CSS file split into "layout" and "color" for easy editing in the future.
    -->
    
    vs.
    
    <link rel="stylesheet" href="reset-min.css"> <!-- ~ 1.5 kiB; all media types -->
    <link rel="stylesheet" href="global-screen.css" media="screen"> <!-- ~ 7 kiB; site-wide elements -->
    <link rel="stylesheet" href="color-screen.css" media="screen"> <!-- ~ 10 kiB -->
    <link rel="stylesheet" href="database-screen.css" media="screen"> <!-- 20 kiB; not on all pages -->
    <link rel="stylesheet" href="global-print.css" media="print"> <!-- ~ 6 kiB; site-wide elements -->
    <link rel="stylesheet" href="color-print.css" media="print"> <!-- ~ 7 kiB -->
    <link rel="stylesheet" href="database-print.css" media="print"> <!-- ~ 7 kiB; not on all pages -->
    
    <!--
        7 HTTP requests; 58.5 kiB
        CSS files split into "global/database" and "color" for easy editing in the future.
    -->
    
  2. The first question also applies to JavaScript files. I have the main JS file for my functions, plus the jQuery API file. However, since the functions will be split up by async or defer attributes, this will result in more HTTP requests, but of smaller size. JS will also be minified.

    <script src="jquery-min.css"> <!-- ~ 95 kiB; local -->
    <script src="scripts-min.css"> <!-- ~ 21.3 kiB -->
    
    <!--
        2 HTTP requests; 116.3 kiB
    -->
    
    vs.
    
    <script src="scripts-async-min.css" async> <!-- ~ 108.1 kiB; includes jQuery API -->
    <script src="scripts-defer-min.css" defer> <!-- ~ 4.3 kiB -->
    
    <!--
        2 HTTP requests; 112.4 kiB
    -->
    
  3. My last question is really concerning the main culprits of reduced webpage loading — the jQuery API file, and web fonts. Since they take up HTTP requests anyway, would you recommend outsourcing directly from the jQuery CDN and Google, versus hosting the files locally? I bring this up as I’m assuming the CDNs would be faster to serve. However, I would be taking advantage of service workers where possible to reduce the need to download files.


Thank You!

Thank you for reading through this long post. I understand that I have probably gone into too much detail, but I didn’t want to leave anything out that may be important.

3

Answers


  1. Here are my views on the questions you raised:

    1) Browser can open multiple parallel connections to a single server while loading the files. However, the catch lies in the limits on the number of these connections. Loading a single file of 76.5 KiB will usually be slower than loading 3 files of 25 KiBs. This won’t hold true always since the Server handshake time ‘might’ be greater than the time taken to actually fetch the resource, especially in your case were the file size is 70Kibs and average Internet Speeds are ever-increasing. I guess the best solution will be highly dependent on the geographical areas you are targeting.
    Heres a discussion on parallel connections limit : Max parallel http connections in a browser?

    2) Same predicate applies to the js files as well. However, jQuery is almost global these days. There’s a very very high chance that user has visited a website that required before coming to your website. Hence, using a popular CDN would mean that THE jQuery FILE WILL NOT BE DOWNLOADED AT ALL AND LOADED FROM THE BROWSER CACHE. There goes one of your biggest culprit. Even if the file does not exists in the browser cache, using a CDN should be the preferred practice, as CDNs by definition, are Geographically Distributed Systems and a good chance exists that the CDN can provide a lower latency if the visitor is not geographically in the same region as your server.

    The javascript code that is not immediately required to be executed should be loaded async or deffered. What you do of these two further depends upon the browsers you are targeting. Older browser won’t see any advantage with deferred loading.
    Refer: Script Tag – async & defer

    3) The same rational applies to fonts as well.If you are using a popular font, chances are it already exists in the cache.
    Using service workers to manage jquery and fonts seems like an overkill to me. You might want to use them for your other assets though.

    Also, I would like to add that you should try make the webpages load progressively. Put only the required code inside the head section. JS code which is executed upon user interaction should be loaded after the DOM content, i.e., just above the closing body tag.

    I would also suggest to defer loading the css which is being used to style the content rather than fixing the layout. This includes all the colours, fonts and other fancy stuff.

    If your purpose is to get a good score on the Chrome Audit, things I mentioned might not stand correct. But for serving actual users, this is what I would personally do.

    Login or Signup to reply.
  2. Question 1:
    You can keep separate css files with you for easy editing. Use vswebessentials to bundle and minify for the production version. When you are hosting it on server, put up a far future expires date or use cache manifest. Then, you would need to rename the bundled file when you make the changes. Site will work lot faster.

    A 75kb css is not large in today’s date when downloaded over single connection, if you give a far future expiry date and your client makes no other request for that for any other date for the domain.
    Hopefully, you are not going to change css daily. You can break it down too as per media query specification.

    Question 2
    Loading jquery from cdn is a good idea but you need to make sure that it is available before your js is going to execute. Do not use service workers for simpler stuff. If you want to check, audit http://www.google.co.in, your audit numbers may be better than google. So, do not complicate development with audit numbers. Concentrate on UX. That’s what google is doing.

    Question 3
    You can and should use CDN for jquery and fonts. Use cache manifest and far future expiry, if you can instead of following the audit tab for numbers and service workers.

    Login or Signup to reply.
  3. I wanted a high rating for my website for my progressive web app (Angular, AWS serverless) for free. the ratings I got are in the image below. This is what I would advise against your questions…

    1) Put the CSS file required for above the fold content in the HTML page itself, for the rest of the css files, let them load asynchronously. be careful about unused css, I spent time cleaning and removing unused classes.

    2) Do you really use a lot of jquery? for best results, you might want to write vanilla javascript instead of using jquery in the above-the-fold content especially. in my website https://beta.akberiqbal.com i wrote plain javascript for the above-the-fold items (navigation etc). and below the fold, I had my three Angular5 JS files. the bundle.css file was small, so I made it part of the HTML also.

    3) if you have a service worker app, a local fetch should be faster than a CDN.

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search