David is a developer & technical writer. When he is not writing code/content, he is reading on how to design and develop good software products.
Published on
Nuxt is a free and open-source JavaScript library built on top of Vue.js. Among other powerful features, it enables developers to build server-side rendered(SSR) applications. In today's modern software development, DevOps practices such as Continuous Integration(CI) and Continuous Deployment(CD) are essential for automating the software delivery process. These modern processes can help developers building SSR applications with Nuxt.js automate their application deployments seamlessly.
This tutorial will demonstrate how to build, test, and deploy your Nuxt.js Application to GitHub Pages using CircleCI. GitHub Pages is a free static site hosting platform for hosting static web pages via Git repositories. There are several other hosting platforms such as Netlify and Vercel, however, in this tutorial, we will use GitHub Pages for our demo. CircleCI is a continuous integration and continuous delivery platform for implementing DevOps practices. There are other CI/CD(Continous Integration/Delivery&Deployment) platforms such as Jenkins and Travis CI.
To follow along with this tutorial, you will need the following:
CI/CD pipeline is a DevOps mechanism for automating the process of software delivery. It involves the continuous automation, integration, and testing phase to delivery and deployment throughout the lifecycle of a software product. CI/CD pipeline helps automate the process of software delivery and enables you to perform build and test automatically. It also helps to improve flexibility with the ability to ship new functionalities faster. By utilizing the CICD pipeline, you can reduce manual errors and provide feedback to software developers, allowing for faster product iteration.
Continuous Integration, Continuous Delivery, and Continuous Deployment are common terms in modern software development practice and the DevOps ecosystem. Often, these terms are used interchangeably and as synonyms. Despite each being part of the software delivery process, each approach differs in its implementation and what they mean to a development team.
CICD pipelines consist of four important stages. Any developer developing a new version of any software should follow the following stages. In the event of a failure at any stage, developers receive feedback notifications.
We need to set up a Nuxt.js application and connect it to GitHub to get started. Run the following command to create a new Nuxt.js app:
After the command, proceed and press Yes. It will prompt an interactive project creation process and ask some questions. Some of these Nuxt CLI implementation questions might change in the future, however, these are the three important questions and answers for this tutorial:
After answering all these questions, create-nuxt-app will begin scaffolding the new Nuxt.js application. As soon as the scaffolding is complete, you will need to connect your app to a GitHub repository. Go to your GitHub account and create a new repository. Let the name of your repo be the same as your project, in my case, i.e., nuxt-cicd. After that, connect the project to the GitHub repo you just created. Navigate into the root folder of your Nuxt.js project and run the following command to make an initial commit.
Then connect your project to the repo by running the following command:
Remember to replace the repository GitHub URL above with yours. With this, your project will be connected to your GitHub repo.
While setting up our Nuxt project, we chose Jest as our testing framework. The create-nuxt-app has set up what we needed for testing our application (including the packages required and the default test configuration) along with a jest.config.js file. The test folder is located at the root of the application. Inside the test folder, you will see a default NuxtLogo.spec.js test file with a test for the Nuxt Logo component that simply checks if the component is a Vue instance. Additionally, we will add another test to check if the Nuxt logo components render properly. Replace the NuxtLogos.spec.js file with the following code below:
After that, save the file and run the tests with the following command:
If your test runs successfully, your display screen should be similar to this below:
Next, we need to run the nuxt generate command to create a dist folder at the root of our Nuxt project. This folder will contain a production version of the application to be deployed to a static hosting platform like GitHub Pages. The generated version contains only static files, making it suitable for static hosting
One thing to note about applications deployed to GitHub Pages is that their base URLs are the name of your application's repository. For instance, your URL for the nuxt-cicd application project on GitHub Pages would be https://[YOUR_GITHUB_USERNAME].github.io/nuxt-cicd.
We need to inform our Nuxt application to generate the distribution version and the proper router base when deploying to GitHub Pages. This will cause all of our routes to fail if we don't do it.
The first step is writing a nuxt generate script that specifically targets the deployment to GitHub Pages. Add the following extra script in the script section in your package.json file.
In the script above, the generate: gh-pages script sets the DEPLOY_ENV environment variable (which we will reference later in the tutorial) to GH_PAGES (we will use this identity for GitHub Pages) and also add the fail-on-page-error flag that confirms that the build fails if there is a page error.
Then, we need to set our router base inside the nuxt.config.js configuration file. To do that, add the following code just before the module.exports line:
We created a routerBase object based on the variable DEPLOY_ENV value in the code above. The routerBase value is set to a router base object targeting GitHub pages if we deploy our application to GitHub pages. Otherwise, the default value should be an empty object. By doing so, we'll ensure that the router base is properly configured for our project. Dont forget to change the base value of: nuxt-cicd if you're using a different slug for your repo.
To complete our configuration, we need to add the following line within the exported object in the nuxt.config.js file:
As part of setting up the deployment script to deploy to GitHub pages, we need a script that achieves the following:
The first thing we need to do is to create a CircleCI configuration. To do that, create a folder named .circleci in the root folder of your project. Then add a file named config.yml inside the folder.
Because the node_modules folder isn't pushed to the project repository, we must install the necessary packages for our CircleCI build. Enter the following configuration below inside the config.yml file:
As shown in the configuration above, we created a build job that utilizes the Node Docker image available in CircleCI registry. The cimg/node 12.16.0 is a Docker image created by CircleCI to support continuous integration. The tag 12.16.0 implies the version of Node.js will be Node.js v12.16.0; however, your node version might be different.
After that, we check out our code and update npm. Then, we install our dependencies by running the npm install command and creating a cache of our node_modules folder using the save_cache step. Also, we add a restore_cache step to restore our cached assets for use after saving a cache in a previous run.
Next, we need to add a step to run our tests in our configuration. To do that, add another run step :
The step will run the npm run test command that we previously ran locally to run our tests using Jest.
We will add another step to build our project, as shown below, by running the nuxt generate command.
This step above invokes the `generate: gh-pages` script that was designed for deployment to GitHub pages.
The step will run the npm run test command that we previously ran locally to run our tests using Jest.
We need to add the last script for deploying to GitHub pages. Before that, we would need to separate our deploy branch away from the main branch. This separate branch will be maintained exclusively for deployments to GitHub pages. This could be a time-consuming procedure but, fortunately, there is a Node.js package called gh-pages that can help us accomplish that. With this package, we will be able to push our files to a special gh-pages branch on our repository and have them deployed to GitHub Pages.
To do that, add the following deploy steps to your config.yml file:
We install the gh-pages package in the configuration above and set our git configurations for GitHub in our container. Remember to change the values of both user.email and user.name to your own GitHub account details.
In the second step, we use the local installation of our gh-pages package to publish everything in our generated dist folder from the previous build step to our gh-pages branch.
You will notice that we added a few arguments to the gh-pages command. We also assigned a special commit message (prefixed with --message) which contains [skip ci]. This command will instruct CircleCI not to initiate a new build when pushing these contents to the gh-pages branch. Lastly, we assigned --dotfiles to the gh-pages command so that it will ignore all dotfiles.
Here is the complete configuration file:
Then commit your changes and push them to the main branch.
As a first step, we need to connect our project with CircleCI. Go to your CircleCI dashboard (remember we highlighted creating an account at the beginning of this article), and add the project in the Add Project section. Click the Set Up project next to your project. The display should be similar to this below:
Click the Set Up Project to start building the project. Then CircleCI will run the configuration to build, test, and deploy your application. You will notice the build fails. Dont panic; this was expected. To see why the build fails, click on the process tag and inspect every step of the build process. You will discover that the deployment failed at the stage where gh-pages would push our files to the deploy branch. This error occurred because our connection to GitHub, which needed to push our files, was not authenticated.
To establish an authenticated connection with GitHub, we need a deployment key in the form of a private/public SSH key pair that is served in our GitHub account and granted write access.
Run the following command to create an SSH key pair on our local machine :
Remember to replace the YOUR_GITHUB_EMAIL with the email address you used for your GitHub account. Then choose a destination name like deploy_key and press Enter to accept the default password of none. Afterward, this should automatically generate a public/private key pair for you at the chosen destination named deploy_key (private key) and deploy_key.pub (public key).
After that, you have to save the private key within CircleCI. Navigate to your CircleCI Pipelines page and click on the button with the cog icon to access the Settings Page.
On the side menu of the Project Setting Page, scroll down and click SSH Keys:
It will prompt a modal box to Add an SSH Key:
The form has two input fields. Enter "github.com" as the hostname, and paste the contents of your "private key()" into the private key field (this was the private key we generated earlier). Then click ADD SSH Key to add the key. Perhaps if you have any issues adding your private key to CircleCI, you can contact or check CircelCI support.
Upon adding the key, you'll see the fingerprint of your newly added key. As fingerprints are safer than exposing private keys directly, CircleCI uses fingerprints to identify private keys in its scripts.
After that, you need to ensure that the “pass secrets to builds from forked pull requests” options on our Advanced Setting Page are set to Off. You can locate the Advanced Setting link on the side menu of our project setting page.
To complete our security checks, please ensure that you delete the private key file from the project root folder.
Next, we need to submit our public key to our GitHub account. You can do this by going to the Settings tab of your GitHub project repository. On the side menu, click Deploy Keys. Then click Add deploy key on the Deploy Keys page, and the form below will appear:
Input a relatable name in the title field, e.g., “CircleCI Deployment Key”. In the Key field, paste the content in your public key file “deploy_key.pub” and check the Allow write access checkbox. Then click Add key.
Your key will be displayed in the list of deployed keys. To finish up, we need to add the fingerprint of our private key from CircleCI to our configuration file. Our deploy steps will look like this below:
Make sure you replace the fingerprint used here with your own.
Here is the complete configuration file config.yml:
Finally, commit your changes and push to the main branch once more to trigger the deployment. As soon as you push, it will initiate a new build process, which will be successful this time. Then click the deployment tab and check the test section. You will discover that all our tests are running successfully:
If you want to verify that our application is deployed, visit your GitHub page URL "https://[your_github_username.github.io/nuxt-cicd]", and view the deployed nuxt application. You will see the homepage of the nuxt application.
You can find the complete repo for this tutorial here on GitHub.
Utilizing the CICD pipeline can help reduce manual errors and provide feedback to developers, allowing for faster product iteration. Developers building server-side rendered applications with Nuxt.js should leverage these modern processes to deploy their applications. We demonstrated how to leverage CICD to successfully deploy a Nuxt.js application to GitHub Pages. CircleCI offers a comprehensive list of configuration options, so we could tailor our configuration to suit our specific needs and deploy it to other hosting providers.
Get visual proof, steps to reproduce and technical logs with one click
Continue reading
Try Bird on your next bug - you’ll love it
“Game changer”
Julie, Head of QA
Try Bird later, from your desktop