How to Tame Your JavaScript and CSS to Improve Performance

Web development has become increasingly complex over the past decade. Rather than serving up static HTML, CSS, and images, JavaScript applications run on the browser and execute asynchronous API requests to retrieve information. JavaScript and CSS assets have become critical to performance with the rise of single-page applications and other modern web application architectures.

Let's take a look at how to optimize your JavaScript and CSS assets to reduce load times and improve the user experience.

Page Weights vs. Expectations

The size of JavaScript and CSS assets has increased dramatically over the past few years. According to HTTPArchive, the size of an average web page's JavaScript and CSS assets have more than tripled over the past decade. The median desktop webpage is 2,032kb and the median mobile web page is 1,864kb.

Growth in Page Weights Over Time

Growth in Page Weights Over Time – Source: HTTPArchive

At the same time, user expectations for page load times have never been higher. Nearly half of visitors expect a web page to load in two seconds or less, according to Skilled, while a two-second delay can lead to a 4.3% loss in revenue per visitor, a 3.75% reduction in clicks, and a 1.8% drop off in queries.

Page speed also affects search engine optimization (SEO). In 2018, Google announced that speed would become a factor in Google Search and Ads. The search engine giant recommends that developers pay close attention to user-centric performance measures and use tools like PageSpeed Insights.

2018 Load Times Breakdown

2018 Load Times Breakdown – Source: MachMetrics

Average load times vary based on companies, industries, and geographies, among other things. So while you should optimize for the lowest possible load times, it's helpful to understand where you fit with the competition when setting benchmarks.

How to Improve Performance

There are many ways to optimize JavaScript and CSS assets to reduce load times. They don't apply to every situation, but they can help in the most common scenarios.

Let's take a look at the five most effective strategies:

Proper Placement

Most browsers render web pages from the top down, which means that anything in the `<head>` must load before they’re visible. For example, JavaScript assets are both fetched and executed before moving onward.

CSS files should be loaded in the `<head>` since they influence the look and feel of the web page. Otherwise, visitors would see a flash of unstyled HTML before the final page is rendered, which looks bad overall.

JavaScript files should be loaded right before the final `</body>` tag since they’re usually not required until the visitor starts interacting with the web page. The only exception may be analytics that you want to fire immediately.

Asynchronous JavaScript

You can include an `async` attribute in JavaScript `<script>` tags to load the files asynchronously. The browser will begin downloading the script in the background while it continues to execute and build the rest of the web page.

Of course, there are some cases when you want to wait until the page loads to execute a JavaScript or wait for a dependency to load before a particular script. You can use the `defer` attribute in these cases to wait for the page to load.

It's worth noting that `async` behaviors mean that it's no longer necessary to combine files. Unlike HTTP/1.1, HTTP/2 uses multiplexing to send and receive HTTP requests and responses asynchronously using a single TCP connection.

Reduce External Requests

Many JavaScript and CSS assets contain external resources. For example, you may use services like Google Analytics or OptinMonster, which require their own JavaScript references, or CSS files that import Google Fonts.

In many cases, you can host third-party resources locally to avoid these issues. Download Google Fonts or Boostrap's theme rather than using an external content delivery network (CDN). You can even host your own Google Analytics.

You can also increase the speed of external requests using DNS caches, prefetching, and other strategies. For example, DNS prefetching enables browsers to perform DNS lookups in the background with `<link rel="dns=prefetch" href="">`.

Minify & Compress Assets

Minification gets rid of unnecessary characters from a JavaScript or CSS file, which reduces the file size and loading times. While you should never *write* compact CSS or JavaScript, you can use tools to compress it in production.

If you're using a build tool, include minification as part of your build process.

Here's an example in Gulp:

...
const gulp = require('gulp');
const minifyCSS = require('minify-css');
gulp.task('minify-css', () => {
            return gulp.src('styles/*.css')
            .pipe(gulp.dest('dist'));
}
...

Compression is less of a sure thing than minification since there's a trade-off: Compression reduces download times, but the browser must uncompress the file before rendering it. You can maximize performance by compressing all or none.

Use a CDN & Caching

CDNs can reduce load times by hosting JavaScript and CSS resources in close proximity to each visitor. For example, someone in Europe would be served assets from a server located in the E.U. rather than the U.S.

While CDNs provide global caching, you can also take advantage of browser caching. Most default caching expires in just five minutes, but you can configure them to cache for one month or one year to minimize loading times.

The easiest way to do this is with the `Cache-Control` HTTP header or the `Expires` header. You can create a cache that sits between your web application and visitors to create a local cache that you have more control over.

Take JavaScript by the Reins

With JavaScript and CSS assets optimized for max performance, you ensure load times aren't degrading your conversion rates, SEO benefits, and overall user experience.

To take it a step further, load test your web application on a regular basis to ensure you're not introducing any regressions. The best load testing frameworks leverage browser-based testing for accurate results.

LoadNinja's browser-based load testing suite makes it easy to build data-driven tests with a record-and-replay functionality that can run across tens of thousands of cloud-based browsers. Developers can quickly debug any performance bottlenecks with actionable metrics for both web UI and API layers.

Do yourself a favor and start your free trial or schedule a demo today.