GitLab pages serves files under a public directory. If, like me, you are using GitLab pages to serve a static site (maybe it’s a SPA or just vanilla HTML/CSS/JavaScript) then serving compressed files improves site performance dramatically.
TL;DR
Add the following to your .gitlab-ci.yml file, after the build step (example):
gzip -k -6 -r public
Context
This blog was made using React and is hosted via GitLab Pages. To create the boilerplate React code I used the famous create-react-app method.
Somewhat expectedly, source files are not compressed by default on build. A Google search reveals that you’ll have to configure webpack manually by ejecting the app first and adding some plugins to alter the bundling.
Ejection: create-react-app encapsulates all of the npm modules it uses. This mean you don’t have to worry about how bundling happens and keeps your package.json simple. Ejecting is a one-way operation that bombards your package.json, exposing intricacies of the build.
This sounded greatly unappetising to me.
Obvious solution?
One solution is to add a post-build step. This way we can leave whatever black magic webpack is performing alone and gzip the built files at a later stage.
Alas, an issue.
On my local Windows machine, my post-build gzip command worked wonders but since my CI/CD pipeline ran in a Linux environment, the gzip command differed and so the same build command would not work on the build agent. I had inadvertently coupled my build script to a certain OS.
A better solution
GitLab pages uses a .gitlab-ci.yml to configure deployments. This is where I have a step to run the build command (followed by the erroneous post-build compression step).
GitLab Pages serves under the public directory by default so I added the following line after the build step:
gzip -k -6 -r public
This way, we leave the compression out of the package.json, but instead as part of the deployment configuration. Feels neater to me. But most importantly the coupling of this Linux command is with the .gitlab-ci.yml file and not the package.json. The package.json is a file used on potentially many environments whereas the .gitlab-ci.yml is specifically for GitLab’s pipeline and will only be run on deployment servers.
End result
Now, when a client requests for a page at the URL, /example-url/
, server returns /example-url/index.html.gz
. The browser understands this file and unpacks it before rendering.
Closing thought
My experience is with GitLab Pages but I suppose there are analogies to draw with other CI tools such as Azure DevOps. In most cases there will me another file responsible for configuring deployments (e.g. azure-pipelines.yml) so, by the same logic, you could add your compression step there.