Nuxt Static vs Laravel blog: overview, pros and cons

Last updated

Antonio Ufano avatar

Antonio Ufano

Back in 2017, I used Laravel to build my personal website and blog. Every year I do some updates, mostly upgrading to the new Laravel release and other dependencies. Last year I changed the editor I used to write the articles of my blog, migrating from a TynyMCE to a markdown editor. You can read more about how I built my Laravel markdown blog in this article but in summary, I wrote my articles in a markdown editor and upon saving then to the database, I convert them to HTML using a public GitHub API.

This system has been working fine but I've never felt 100% comfortable with it. It had a dependency with the GitHub API and sometimes if the article was too long, it gave me some errors. Besides, when I'm writing very long articles, the session on my website expires before I save, so I have to make sure I've copied the article to my clipboard just in case. Most of the time I ended up writing my articles in markdown files locally in VSCode and copy-pasting them to my web once I finished, not the best experience. What I've really wanted is to just write my articles in plain markdown files, completely offline and push them to my repository to publish them. And that's exactly what Nuxt and its content plugin offer.

Nuxt content explained

In summary, the Nuxt content plugin allows you to write your content as markdown, csv, yaml, or JSON in a folder named /content, and serve it from a local API that you can use during your build in an asyncData hook in your Vuejs views. Every folder inside /content will be like a database table/collection and each document inside them, like a row/document.

It's important to notice that the asyncData() hook will only be available in your application views but not in components.

In addition, your markdown files will accept a block of yaml at the beginning of the file in which you can indicate some useful properties, like createdAt date, categories, a summary, etc that you can use later to query them.

For example, the markdown file for this exact article has the following structure:

---
title: Nuxt Static vs Laravel blog
public: true
summary: Some thoughts after migrating my personal webiste and blog from Laravel to a full static site with Nuxt.
slug: nuxt-static-or-laravel-blog
# Date format is MM/DD/YYY
# Only needed if we want to overwrite the file creation/update dates
createdAt: 01/25/2021
updatedAt: 01/25/2021
categories:
  - vuejs
  - laravel
  - javascript
  - opinion
relateds:
  - title: Deploy Strapi applications to production
    summary: I share some tips to deploy Strapi applications to production and guide you step-by-step to deploying a Strapi project to DigitalOcean App Platform
    slug: deploy-strapi-applications-to-production
  - title: Easily send emails in Strapi with any provider
    summary: Strapi's default email plugin is not the best option to use in Production. There are multiple plugins for different email providers but in this article, I'll show you how to use a plugin that works with any provider.
    slug: easily-send-emails-in-strapi-with-any-provider
---

Back in 2017, I used Laravel to build my personal website and blog. Every year I do ...

All my articles are saved as markdown files inside content/articles and I'm able to fetch them with the following code in the asyncData hook of my blog index page:

// retrieves all public articles
export default {
  async asyncData({ $content }) {
    const articles = await $content('articles')
      .where({ public: true })
      .only(['title', 'summary', 'slug', 'createdAt', 'public'])
      .sortBy('createdAt', 'desc')
      .fetch()
  },
}

As you can see, I'm filtering the articles that are public and only retrieving a few properties of each article, the ones I need on my index page. Then in the view that displays the full content of the article, I can retrieve the whole file using the slug, which is passed as a URL query parameter:

  async asyncData({ $content, params }) {
    // fetch page's article by slug
    const article = await $content('articles', params.slug)
      .fetch()

    return { article }
  },

By running npm run generate Nuxt will retrieve your content and build all your views as static HTML pages ready to be deployed.

You can find more details about Nuxt content in this step-by-step guide in the official Nuxt blog and clone the following repository created by Gareth Redfern to see a fully working blog.

Additional features for static blog

My personal website and blog had a few other features other than just serving a whole list of articles so I had to make sure I was going to be able to replicate them using Nuxt. These features were:

  • Pagination in my blog
  • Categories in the articles
  • A contact page
  • A subscribe form to capture emails
  • Recaptcha in all public forms
  • Analytics and AdSense

Pagination and categories were the things that worried me the most. When a dynamic website (like one built with Laravel) paginates, it sends a request to the server, fetches the articles to display from the database, and returns a page. With Nuxt content, you have to calculate the number of pages you'll have in advance and prefetch all of them.

For categories, I just had to include them in the block of YAML at the beginning of the file.

You can find more about how pagination and categories work by checking out the code of the following repository created by Gareth Redfern.

To integrate ReCaptcha, the contact page and the subscribe form, I needed a backend so I ended up creating a few cloud functions. You can even avoid these by integrating something like a pre-built Mailchimp form to collect subscriber emails or even with Netlify forms.

And finally, Google Analytics and AdSense are just two javascript dependencies on the web, so they were pretty easy to implement manually, although I even found a couple of Nuxt modules for them: Nuxt adsense and Nuxt Analytics.

Now that I've covered all of the features of my static site and that it's being online for a couple of weeks, I'll explain some of the benefits and disadvantages.

Benefits of a static blog with Nuxt vs Laravel

I'd say the main benefit of building a static blog with Nuxt vs using something like Laravel or even WordPress is its simplicity. All your site content is part of your codebase, so whenever you want to update an article, you just need to update the file and push it to the repository. That's it.

In addition, not having a database means you don't have to worry about it being attacked, doing backups, etc. The fewer components you have, the more secure your website will be.

Another benefit is performance. As a static site, there is no need to fetch data from a database or API so your pages will be served immediately. This results in practically perfect performance scores in Lighthouse. Here you can see the difference between my Laravelsite (which even had a few optimizations in the server) and my current Nuxt site:

Lighthouse score comparision

And finally, while a Laravel or Wordpress site typically requires you to pay for a hosting provider, you can deploy a static site to a wide variety of places for free. You can deploy it to GitHub pages, Netlify or even an Amazon S3 bucket. I decided to rebuild my website with Nuxt because my hosting costs were around 75$ per year (after the first year offer expired). Now this site runs on Netlify completly free 😉

Disadvantages of a static blog

But not having a database is at the same time a disadvantage. Although I've been able to include pagination and categories in my blog's articles, it means that the result of the build is a collection of folders inside folders inside folders... I know this is not an issue now as I only have like 15 categories and 40 articles but it might be an issue in the future when those numbers grow.

My current build time (running npm run generate) is less than a minute locally and my deployments take less than two minutes so for me it's fine. I don't think I'll write that many articles in the short term to make things really bad but for bogs with a large number of articles, it could be an issue.

On top of that, for some reason some article pages are not generated. I'm not sure what it is yet but I guess it should be an incorrect filename or something like that. You have to be very careful with your YAML block, markdown and filenames as any small typo will break your page.

I think another disadvantage of static sites is getting less knowledge. Building a website that retrieves its content from a database forces you to learn more about web development in general. You have to understand which code runs on the server, how the pages are composed on the fly when a user requests it, how the database works and retrieves the data, which code runs on the browser... It's a more complex system but it's a lot of knowledge that is always nice to have. Nuxt content (and other static site generators) lowers the barrier to building content-driven websites by removing some of the most complex parts.

So my suggestion is that if you are a newbie and you're thinking about how to build your website, a static site is great but I'd also try to understand and learn how dynamic sites and databases work because you'll most probably need that knowledge sooner or later.

I hope you find this article useful and if you have any question about how to build you blog with Nuxt content, feel free to contact me on Twitter or send me a message here.

Happy coding!

If you enjoyed this article consider sharing it on social media or buying me a coffee ✌️

Oh! and don't forget to follow me on Twitter where I share tons of dev tips 🤙

Other articles that might help you