At Eightygram we think that too much knowledge is lost when experts discuss things in private. We build a platform for conversations that are public yet protected and hope to create a unique experience on the web. We’re at the very beginning but you can help us by signing up or sharing our mission. Thanks and much love!

Many react developers use a boilerplate to get their projects started. The most popular boilerplate set-up is create-react-app. Create-react-app removes the hassle of writing your own Webpack config. However, using the predefined Webpack config removes the option of compressing your files with Webpack. This is not necessarily bad since there are plenty of other ways to introduce compressing to your app. You just have to remember to do it …

You can easily find out if you are compressing your files already by running a quick Lighthouse audit. In this article, I walk you through how I tripled my Lighthouse performance score for a personal app by gzipping server responses using Nginx.

Lighthouse: A Neat Little Trick

Lighthouse is a small auditing tool baked into Chrome. Lighthouse tests for performance, best practices, basic SEO and accessibility. It is also a tool to help you rank better on Google Search. You can find Lighthouse in the Chrome inspect panel (you may have to press the small arrow to get to it):

After some fairly straightforward improvements for SEO, best practices and Accessibility I was stuck on a performance score of 32 for my create-react-app:

I tried several approaches to better my site's performance:

Code Splitting with dynamic imports() and React. Suspense (my score went up to 33)

with dynamic imports() and React. Suspense (my score went up to 33) Optimizing rendering by analyzing my render tree and increasing the use of PureComponent (my score remained at 33)

Naturally, this was not satisfying. What was surprising to me was, that I had almost the same Lighthouse performance score in production (33) as I was seeing during development(29) and Lighthouse was prominently suggesting enabling text compressing when running the audit in production.

Here is the takeaway: Webpack will not automatically compress responses to the client.

When googling the issue, I found that Webpack is more than capable of compressing the responses to the client (your user) but that you can’t use this functionality with the create-react-app boilerplate without ejecting. You are expected to implement compressing on the server-side. In comes Nginx.

Short disclaimer: After enabling gzip my score tripled (so stay tuned):

Nginx: A Very Popular Reverse Proxy to React

There are some fantastic articles about the functionality and workings of Nginx. For this article, I will assume that you are familiar the basic workings of Nginx.

As it turns out, enabling gzip is pretty straightforward with Nginx. But there are some pitfalls that are best avoided.

Here is a Nginx server block that enables gzip for you:

Lets go through the settings:

Basic Settings:

gzip on: This is a default config for many Nginx servers. It will enable gzip but ONLY for the MIME type text/html

This is a default config for many Nginx servers. It will enable gzip but ONLY for the MIME type text/html gzip_disable “msie6”: Disable gzip for browsers that do not support it — this will disable gzip for IE4–6

Disable gzip for browsers that do not support it — this will disable gzip for IE4–6 gzip_vary on: Let the browser decide whether it will accept gzip. If it does not accept gzip sent the uncompressed file. The decision is made via the Accept Encoding header. A typical request made with a modern browser would include the header: “ accept-encoding gzip, deflate, br” (check it in your own requests)

Let the browser decide whether it will accept gzip. If it does not accept gzip sent the uncompressed file. The decision is made via the Accept Encoding header. A typical request made with a modern browser would include the header: “ gzip, deflate, br” (check it in your own requests) gzip_proxied any : enables compression for all proxied requests. Alternatively, you can limit compression to responses that include the no-cache or no-store header.

: enables compression for all proxied requests. Alternatively, you can limit compression to responses that include the no-cache or no-store header. gzip_comp_level: This setting will set the compression level for gzip (this is a zipping feature and not specific to nginx). The default level is 6 and this should be applied for most use cases. But be aware, Nginx default value for this value is 1. Cranking it up will increase the work for your server — be vary if you are running a large app!

This setting will set the compression level for gzip (this is a zipping feature and not specific to nginx). The default level is 6 and this should be applied for most use cases. But be aware, Nginx default value for this value is 1. gzip_buffers: Sets the number and size of buffers used to compress a response. By default, the buffer size is equal to one memory page. This is either 4K or 8K, depending on a platform. You can edit this value or roll with the Nginx default which is: gzip_buffers 32 4k|16 8k This should work pretty well!

Sets the number and size of buffers used to compress a response. By default, the buffer size is equal to one memory page. This is either 4K or 8K, depending on a platform. You can edit this value or roll with the Nginx default which is: gzip_buffers 32 4k|16 8k This should work pretty well! gzip_http_version: Sets the minimum HTTP version of a request required to compress a response — you can optionally omit this setting since 1.1 is the default.

Sets the minimum HTTP version of a request required to compress a response — you can optionally omit this setting since 1.1 is the default. gzip_min_length 0: It is possible to only gzip files that have a certain size (you can insert a byte size here). Many people will tell you to set this to about 1000 or even 10000 but I found making sure that your bundles have good sizes in the first place and only including good gzip_types (see below) more useful.

The Pitfall:

gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype: This tells Nginx which file formats it should gzip. Usually, the benefit is highest for files that include a lot of text such as HTML, CSS or JavaScript files. The benefit is lowest for file formats that are already compressed such as .jpg or .png. You can also gzip .svg files, but I found it way (!) better for performance if you optimize your .svg files before sending them (SVGO is a great tool for that). Please note: Using gzip is a demanding task for the server. Do not simply gzip all files blindly as this will have a bad impact on your site's performance. You need to play with these settings to find the optimal setup for your app!

A quick tip for this setting: Nginx uses MIME types to determine which files it should compress. You can check the MIME type of your files in the network tab of all modern browsers, use exactly the listed MIME type. Here is an example:

Security

Please note that gziped files sent via HTTPS can be subject to BREACH attacks. The risk has been largely mitigated by modern browsers. Nonetheless, if you are running an app with strict security requirements be sure to look into the security aspects of sending compressed files via HTTP and HTTPS.

Conclusion 🎉🎉🎉

Setting up gzip with nginx and create-react-app is pretty straightforward and can be done in about 5 min. Before getting into more advanced optimization techniques like code splitting (which can become cumbersome once you have a React + Redux app) this should definitely be one of your first optimizations. I hope that you have success in increasing the performance of your app!

I’m trying to build a twitter audience. If it works, i’ll publish more helpful coding tricks. Follow me https://twitter.com/FlorianMartens9 😜

Thank you for reading! Stay healthy and keep hacking.