Nuxt.js: A Universal Vue.js Application Framework

Universal (or Isomorphic) JavaScript is a term that has become very common in the JavaScript community. It is used to describe JavaScript code that can execute both on the client and the server.

Many modern JavaScript frameworks, like Vue.js, are aimed at building Single Page Applications (SPAs). This is done to improve the user experience and make the app seem faster since users can see updates to pages instantaneously. While this has a lot of advantages, it also has a couple of disadvantages, such as long “time to content” when initially loading the app as the browser retrieves the JavaScript bundle, and some search engine web crawlers or social network robots will not see the entire loaded app when they crawl your web pages.

Server-side Rendering of JavaScript is about preloading JavaScript applications on a web server and sending rendered HTML as the response to a browser request for a page.

Building Server-side rendered JavaScript apps can be a bit tedious, as a lot of configuration needs to be done before you even start coding. This is the problem Nuxt.js aims to solve for Vue.js applications.

What is Nuxt.js

Simply put, Nuxt.js is a framework that helps you build Server Rendered Vue.js applications easily. It abstracts most of the complex configuration involved in managing things like asynchronous data, middleware, and routing. It is similar to Angular Universal for Angular, and Next.js for React.

According to the Nuxt.js docs “its main scope is UI rendering while abstracting away the client/server distribution.”

Static Generation

Another great feature of Nuxt.js is its ability to generate static websites with the generate command. It is pretty cool and provides features similar to popular static generation tools like Jekyll.

Under the Hood of Nuxt.js

In addition to Vue.js 2.0, Nuxt.js includes the following: Vue-Router, Vue-Meta and Vuex (only included when using the store option). This is great, as it takes away the burden of manually including and configuring different libraries needed for developing a Server Rendered Vue.js application. Nuxt.js does all this out of the box, while still maintaining a total size of 28kb min+gzip (31kb with vuex).

How it works

This is what happens when a user visits a Nuxt.js app or navigates to one of its pages via <nuxt-link>:

When the user initially visits the app, if the nuxtServerInit action is defined in the store, Nuxt.js will call it and update the store.

Next, it executes any existing middleware for the page being visited. Nuxt checks the nuxt.config.js file first for global middleware, then checks the matching layout file (for the requested page), and finally checks the page and its children for middleware — middleware are prioritized in that order.

Then, Nuxt.js calls the asyncData() and fetch() methods to load data before rendering the page. The asyncData() method is used for fetching data and rendering it on the server-side, while the fetch() method is used to fill the store before rendering the page.

At the final step, the page (containing all the proper data) is rendered.

These actions are portrayed properly in this schema, gotten from the Nuxt docs:

Creating A Serverless Static Site With Nuxt.js

Let’s get our hands dirty with some code and create a simple static generated blog with Nuxt.js. We will assume our posts are fetched from an API and will mock the response with a static JSON file.

To follow along properly, a working knowledge of Vue.js is needed. You can check out Jack Franklin’s great getting started guide for Vue.js 2.0 if you’re a newbie to the framework. I will also be using ES6 Syntax, and you can get a refresher on that here: https://www.sitepoint.com/tag/es6/.

Our final app will look like this:

The entire code for this article can be seen here on GitHub, and you can check out the demo here.

Application Setup and Configuration

The easiest way to get started with Nuxt.js is to use the template created by the Nuxt team. We can install it to our project (ssr-blog) quickly with vue-cli:

vue init nuxt/starter ssr-blog

Note: If you don’t have vue-cli installed, you have to run npm install -g vue-cli first, to install it.

Next, we install the project’s dependencies:

cd ssr-blog
npm install

Now we can launch the app:

npm run dev

If all goes well, you should be able to visit http://localhost:3000 to see the Nuxt.js template starter page. You can even view the page’s source, to see that all content generated on the page was rendered on the server and sent as HTML to the browser.

Next, we can do some simple configuration in the nuxt.config.js file. We will add a few options:

In the above config file, we simply specify the title template to be used for the application via the titleTemplate option. Setting the title option in the individual pages or layouts will inject the title value into the %s placeholder in titleTemplate before being rendered.

We also pulled in my current CSS framework of choice, Bulma, to take advantage of some preset styling. This was done via the link option.

Note: Nuxt.js uses vue-meta to update the headers and HTML attributes of our apps. So you can take a look at it for a better understanding of how the headers are being set.

Now we can take the next couple of step by adding our blog’s pages and functionalities.

Working with Page Layouts

First, we will define a custom base layout for all our pages. We can extend the main Nuxt.js layout by updating the layouts/default.vue file:

In our custom base layout, we simply add the site’s navigation header. We use the <nuxt-link> component to generate links to the routes we want to have on our blog. You can check out the docs on <nuxt-link> to see how it works.

The <nuxt> component is really important when creating a layout, as it displays the page component.

It is also possible to do a couple of more things — like define custom document templates and error layouts, but we don’t need those for our simple blog. I urge you to check out the Nuxt.js documentation on views to see all the possibilities.

Simple Pages and Routes

Pages in Nuxt.js are created as Single File Components in the pages directory. Nuxt.js automatically transforms every .vue file in this directory into an application route.

Building the Blog Homepage

We can add our blog homepage by updating the index.vue file generated by the Nuxt.js template in the pages directory:

Now, we can visit http://localhost:3000/about to see the about page, without having to restart the app, which is awesome.

Showing Blog Posts on the Homepage

Our current homepage is pretty bare as it is, so we can make it better by showing the recent blog posts from the blog. We will do this by creating a <posts> component and displaying it in the index.vue page.

But first, we have to get our saved JSON blog posts and place them in a file in the app root folder. The file can be downloaded from here, or you can just copy the JSON below and save in the root folder as posts.json:

We import the posts data from the saved JSON file and assign it to the posts value in our component. We then loop through all the posts in the component template with the v-for directive and display the post attributes we want.

Note: The ~ symbol is an alias for the / directory. You can check out the docs here to see the different aliases Nuxt.js provides, and what directories they are linked to.

Nuxt.js adds some custom methods to our page components to help make the development process easier. See how we use some of them on the single post page:

Validate the route parameter with the validate method. Our validate method checks if the route parameter passed is a number. If it returns false, Nuxt.js will automatically load the 404 error page. You can read more on it here.

The asyncData method is used to fetch data and render it on the server-side before sending a response to the browser. It can return data via different methods. In our case, we use a callback function to return the post that has the same id attribute the route id parameter. You can see the various ways of using this function here.

As we have seen before, we use the head method to set the page’s headers. In this case, we are changing the page title to the title of the post, and adding the post summary as a meta description for the page.

Great, now we can visit our blog again to see all routes and pages working properly, and also view the page source to see the HTML being generated. We have a functional Server Side Rendered JavaScript application.

Generating Static Files

Next, we can generate the static HTML files for our pages.

We will need to make a minor tweak though, as by default Nuxt.js ignores dynamic routes. To generate the static files for dynamic routes, we need to specify them explicitly in the ./nuxt.config.js file.

We will use a callback function to return the list of our dynamic routes:

You can check here for the full documentation on using the generate property.

To generate all the routes, we can now run this command:

npm run generate

Nuxt saves all generated static files to the dist folder.

Deployment on Firebase Hosting

As a final step, we can take advantage of hosting by Firebase to make our static website live in a couple of seconds.

Install Firebase CLI, if you don’t already have it:

npm install -g firebase-tools

Next, initialize the site and specify the dist folder as the public directory, when prompted:

firebase init

Now we can deploy the app:

firebase deploy

This will make the website live at <YOUR-FIREBASE-APP>.firebaseapp.com. The demo app for this article can be seen at https://nuxt-ssr-blog.firebaseapp.com/.

Conclusion

In this article, we have learned about how we can take advantage of Nuxt.js to build Server-side rendered JavaScript applications with Vue.js. We also learned how to use its generate command to generate static files for our pages, and deploy them quickly via a service like Firebase Hosting.