Photo by Fabian Grohs on Unsplash
This is part one of a series on building a file-based blog from scratch with Gridsome. Find the full series here.
Gridsome is a modern static site generator based on Vue. It has functionality that allows easy development of fast websites, and loading data from various sources.
Gridsome is inspired by Gatsby, a similar framework based on React.
To be more precise, Gridsome builds static progressive web apps. The major benefit of frameworks like Gridsome are the speed benefit for your website visitors, and the ease of development. Only the essential pre-rendered HTML, CSS and JS are loaded at first. When the entire website is rendered, Gridsome sites hydrate into a fully functional Vue.js app in the background. You also get “code splitting, asset optimization, progressive images, and link prefetching” out of the box.
There are plenty of options to load data for your website from. You can load, e.g., JSON or Markdown files from the local filesystem. With this, you can already build a Git-based blog (like this one!). Other data sources include most of the (headless) CMS out there, like Forestry, Contentful, Drupal, Sanity.io, and (yes) even Wordpress. Gridsome can also load data easily from databases, AirTable, and any other API.
Hosting options are plentiful, because all you need to do is to serve the static files generated by Gridsome. You host these files wherever you can serve static files. It’s possible to just put them behind nginx on a VPS. But static sites really shine when hosted on a global CDN, because of the decreased latency, increased download speeds, and the massive scalability. Static sites on CDN are also “set-and-forget”. You won’t need to update servers, or fix security bugs.
Popular options to host static sites are CDN-based solutions like Netlify (which I use), Vercel (formerly Zeit now), Surge.sh, AWS Amplify, or Google Firebase. You can also use the static file hoster of your choice and add a CDN like Cloudfront. Most have a free plan, so try them and find out what works best for you.
Dynamic sites like Wordpress update automatically when you change your data. This is because each time a user requests your website, Wordpress looks into the database and retrieves the latest version of that site. (That’s simplified, because Wordpress sites can use caching at various layers.)
Static sites on the other hand need to be rebuilt when the content changes. Every time you add a blog post, fix a typo, or add an image you need to
Wordpress works for many people and is still a valid default option for your run-off-the-mill websites. You can even build many complex projects with Wordpress. The eco-system of themes and plugins is amazing. (And yes, you can even export your Wordpress as a static site.)
But for many use cases, static sites are a great option.
Static sites give your website visitor the fastest experience, because there is no dynamic rendering of the website on the server-side.
JAMstack sites are a subtype of static sites.
They consist of client-side JavaScript, reusable APIs, and pre-built Markup.
For me, JAMstack is:
Gridsome is a modern way to build static websites. As explained above, you get an optimized, pre-rendered static site that hydrates into a fully Vue.js-powered SPA. This means you get the full power of Vue.js, with the download and render speed of a static site.
Gridsome sites get nearly perfect Google Lighthouse Scores out-of-the-box. This is the score for my blog:
I only spent minimal time optimizing the accessibility, mainly by adding Aria labels and getting the color contrasts right.
These results tell you how Google perceives your site. A higher ranking on these measures (Performance, Accessibility, Best Practices, and SEO) can improve your ranking in Google search results.
One other thing I love about Gridsome is that you can load data from many sources with ease.
You load data from any data source into a collection.
A collection can be Posts
, Products
, Members
, or any other dataset you want to display on your site.
The data in these collections is stored as a flat list of nodes, with any number of nested properties you want.
You then use GraphQL to load your data in your application.
Let’s get started with a basic Gridsome project. We’ll use the Gridsome CLI. Install it with the following command:
➜ npm install --global @gridsome/cli
Then we’ll create our project and start it:
➜ gridsome create awesome-blog
➜ cd awesome-blog
➜ gridsome develop
This is what we’re greeted with:
Now let us look at the folder structure:
On the top level, we have some standard files and folders: package.json
, README.md
, .gitignore
, yarn.lock
, and the node_modules
folder.
We can also find two Gridsome config files: gridsome.config.js
and gridsome.server.js
.
gridsome.config.js
file contains Gridsome specific configuration like the site name, and any plugins you want to enable.
Plugins like a site map, data-loader or RSS plugins, or CSS loaders.gridsome.server.js
file to hook into the life cycle of Gridsome and load data or mutate collections.Finally, there are two top-level folders: src
and static
.
static
folder is for all files you want to be copied as-is into the dist
folder (the result of gridsome build
).In the src
folder, you can find several more files and folders:
main.js
: contains the initial Vue componentfavicon.png
: your faviconcomponents
: a place for your Vue components that you’ll use on your sitelayouts
: are Vue components that wrap other Vue components and templates. Layouts should contain the headers, footers, and sidebars that you use on your site.pages
: are separate pages like your home page (Index.vue
) or your about page (About.vue
). These pages will be rendered under your-site/page
, like mannes.tech/about
. They will be rendered inside the specified layout component.templates
: these components are the blueprints for all dynamically created pages, like blog posts.When you run gridsome develop
, you can see changes to your site instantly.
Go ahead and change that Lorem Ipsum text!
Gridsome exposes a GraphQL API for you to explore the data.
You can find the URL to the GraphQL explorer (Playground) in the output of the gridsome develop
command (most likely http://localhost:8080/___explore
).
At the moment there is not much data, but you can explore the GraphQL schema (click on the DOCS
tab on the right).
Explore all pages with this command:
query {
allPage {
path
context
}
}
The result will look like this:
{
“data”: {
“allPage”: [
{
“path”: “/404/“,
“context”: {}
},
{
“path”: “/“,
“context”: {}
},
{
“path”: “/about/“,
“context”: {}
}
]
}
}
This tells you that you get the index page, an about page and a 404 page out of the box.
As a final step, let’s create a new page and link to it from the Index page. We’ll add a “pages” page that links to all the pages (because our pages are something we can query).
First, create a new file in the src/pages
folder called Pages.vue
Basic Vue components consist of three parts: <template>
, <script>
, and <style>
.
The template
contains your HTML template for that component (with Vue specific syntax).
The script
part defines the JavaScript for that component (this is also where you import other components).
And the style
contains your CSS/SASS/LESS rules, which are scoped to that component.
Gridsome enhances this with the <page-query>
.
With a page query you can interact with the GraphQL API and load data from it.
This data is then available inside of your component’s script
and template
.
The final Pages.vue
file looks like this:
<template>
<Layout>
<h1>Pages</h1>
<ul>
<li v-for="page in $page.pages" :key="page.path">
<g-link :to="page.path">{{ page.path }}</g-link>
</li>
</ul>
</Layout>
</template>
<page-query>
query Pages {
pages: allPage {
path
}
}
</page-query>
<script>
export default {
metaInfo: {
title: ‘Pages’
}
}
</script>
You can now add a link to it in your src/pages/Index.vue
template:
<g-link to="/pages">Pages</g-link>
(Add it somewhere within the template > Layout
HTML section)
That’s it for this introductory post on JAMstack with Gridsome. Find out how to create a markdown-based blog in the next part of this series.