Whenever you are running into performance issues with your single-page applications, you might consider using a static site generator to offload some performance overhead. There are hundreds of static site generators out there, and Gridsome is one of the most popular with over 7000 stars on Github. Gridsome is certainly worth a detailed look, so let’s get started.
In this article, we will be taking a closer look at Gridsome: how it works, how to get started, how to use Gridsome to create websites and apps that are fast by default, and finally, learn how to fetch markdown content with GraphQL.
This tutorial is specifically for developers who want to get started with Gridsome and already use Vue.js. By the end of this tutorial, you will understand how to make use of Gridsome’s many functionalities — along with a few “gotchas” and things to keep in mind along the way.
To get started with Gridsome, you’ll need to make sure you have the following tools installed:
To confirm that you have Node installed, you can run
node --version
in the Terminal
Knowing how GraphQL works is a plus, though their documentation has plenty of examples for quick review.
Gridsome is a free and open-source Vue-powered static site generator (SSG) for building fast, modern websites and apps
As a quick reminder, static site generators automate building individual HTML pages and get those pages ready to be served to users – people who visit/use your websites or apps. SSGs do so by building out fully-fledged, static HTML pages based on raw data (e.g., Markdown) and a set of templates.
Gridsome makes use of GraphQL to get data from different sources, then dynamically generates pages.
There are a few useful features that Gridsome provides out of the box. Gridsome works well on top of JAMStack. Like most static site generators, it supports Markdown and headless CMS. The final product is a folder containing static HTML files that you can deploy anywhere. You can put it in the /public_html
folder on your server or deploy it to a CDN.
Gridsome also provides automatic routing. The Vue components that you create in the /src/pages
folder are automatically mapped to a new page with vue-router
without you having to do anything. For example, if you want to create an “About” page for your blog, all you have to do is create a new file called /src/pages/About.vue
and you automatically have an http://localhost:8080/about page on your website. This is very similar to how Nuxt and Gatsby work; they have a defined folder where components are mapped to pages in the router, so you don’t need to configure them.
Additionally, Gridsome provides code-splitting and asset optimization. In Vue apps, when you create an internal link to another page, you use <router-link>
. With Gridsome, you use <g-link>
instead. It uses the same parameters with which you are probably familiar, but in addition, it provides in-viewport prefetching of pages in the background by prefetching assets and pages referenced as links in the current view. You need to approach this feature cautiously as it might create a performance overhead for users loading pages and assets that they will never actually use, but it can speed up the experience for simple pages.
Gridsome also has a built-in <g-image>
component that outputs optimized compressed images. It also resizes and crops in real time while developing. It works like an <img>
element, but <g-image>
will also generate a compressed, blurry version of the original image as a placeholder. So when a user’s browser finally receives the image from the server, it replaces the placeholder with the actual image.
Considering the fact that there are plenty of other Vue.js SSGs like Nuxt.js, VuePress, and saber, it’s worth exploring when Gridsome makes sense to use, and when it does not. Similar to Gatsby in React, Gridsome is a data-driven framework that uses a GraphQL layer to retrieve content from which it dynamically generates pages. Although it’s not yet as established as Nuxt.js and VuePress, Gridsome has some unique features which make it worth exploring for your next project.
Nuxt.js is definitely a more complete framework, and it can do almost everything that Gridsome can. However, with Gridsome you can query data from the GraphQL data layer into any page, template or component without needing to use a module, as compared to Nuxt.js using Apollo Configuration.
If you’re planning to build a large scale application in which handling authentication is better suited to the server-side, Nuxt.js may be a better option.
If you want to set up a beautiful, blazing-fast documentation site that is SEO-friendly, and want to use Markdown with markdown-it and its extensive ecosystem, VuePress is the way to go.
If you want to connect your site with a headless CMS and build a JAMstack project, Gridsome is more powerful. I think that the GraphQL Data Layer is very handy and straightforward to use, because it allows you to build static content from data sources. In this case, Gridsome is the best choice.
Gridsome fetches data from data sources like CMSs (any headless CMS, Contentful, WordPress, Drupal, Sanity.io, etc.), local files, or external APIs and stores the data in a local database. GraphQL serves as a centralized data management system that gives you the ability to extract and use data within your Vue components.
You can then deploy your entire site or app to a CDN like Netlify, AWS Amplify, or Vercel. A Gridsome site can handle thousands to millions of hits without breaking – and with no expensive server costs.
Once you are sure you have Node and either npm or Yarn set up on your computer, you can now proceed to install Gridsome. As mentioned earlier, knowledge of how to use the Terminal is recommended for working with Grisome.
Step one is to install the Gridsome CLI tool:
yarn global add @gridsome/cli
npm install --global @gridsome/cli
You can now start creating your first Gridsome project! 🎉
gridsome create first-gridsome-site
to create a new projectcd first-gridsome-site
gridsome develop
to start a local development server at http://localhost:8080
You can now launch the development server on your browser:
Here is how a basic Gridsome project would be structured:
.
├── package.json
├── gridsome.config.js
├── gridsome.server.js
├── static/
└── src/
├── main.js
├── index.html
├── App.vue
├── layouts/
│ └── Default.vue
├── pages/
│ ├── Index.vue
│ └── Blog.vue
└── templates/
└── BlogPost.vue
The root directory consists of 5 major files and folders.
package.json
is where all the dependencies for the project will be storedgridsome.config.js
serves as a configuration file for the Gridsome site where you configure pluginsgridsome.server.js
is optional and is used to hook into various parts of the Gridsome server/static directory
will be copied directly to dist
during build. For example, /static/robots.txt
will be located at https://yoursite.com/robots.txt/src directory
is where most of the code lives. In this folder, we have:main.js
, where you import global styles and scripts. This file contains all the application configurations such that it plugs other parts of the app into the Gridsome API.
layouts/
, whose components are used to wrap pages. Layouts should contain components like headers, footers, or sidebars that will be used across the site. All layout components are located in the src/layouts
folder and should be indicated as the global component or imported per page.
If you don’t want to import a layout into every individual page or template, you can make a global layout. To do that, go to src/main.js
and import your layout file. Then make the layout global inside the export function.
For example:
// src/main.js
import Layout from '~/layouts/Default.vue'
export default function (Vue, { head, router, isServer }) {
Vue.component('Layout', Layout)
}
You can now use <Layout>
anywhere in your Gridsome project without importing it to every page:
<template>
<layout>
<!-- code comes here -->
</layout>
</template>
In a situation where a particular layout is not for all pages (for example, if the layout contains the navbar, which you don’t want on the sign in and sign up page), then you would have to import such layouts to only pages you need them.
When you have created a layout you need to import it to your pages and templates. This is done inside the <script>
tag:
<!-- Page -->
<template>
<navLayout>
Add page content here
</navLayout>
</template>
<script>
import navLayout from '~/layouts/navLayout.vue'
export default {
components: {
navLayout
}
}
</script>
Every layout requires a <slot>
component. This is where the content coming from pages and templates will be inserted. Layouts can have multiple slots:
<!-- Layout -->
<template>
<div>
<header />
<slot></slot> <!-- Page content will be inserted here -->
<footer />
</div>
</template>
Every component in the pages/
directory becomes a page on the website. Each page will get its path based on the .vue
file location. For instance, src/pages/Index.vue
will become the homepage/
while src/pages/Blog.vue
will be localhost:8080/blog
or example.com/blog
, which will be rendered as the blog page.
templates/
are used for single-post views to GraphQL collections. To add a template create a .vue
file with the same name as a GraphQL collection to src/templates
.
If you are importing an external data source, like posts from a WordPress blog, into your project, each post will look for a component in this directory for its template. The name of the component file must match the node type in your GraphQL schema.
Gridsome starter sites are prebuilt projects anyone can use to build his or her own websites. Gridsome has 40+ starter sites that cut across tons of platforms like Markdown, Strapi, WordPress, Auth0, and more. For this article, I will be installing the official Gridsome Blog Starter.
The Gridsome Blog Starter is a simple, hackable, and minimalist starter for Gridsome that uses Markdown for content. It also has a dark/light mode feature.
Here is what your site will look like after installing this starter site – https://gridsome-starter-blog.netlify.com/
First, install the Gridsome CLI tool: npm install --global @gridsome/cli
.
If you are not sure if you have it, you can use gridsome -v
to confirm if Gridsome CLI is already installed.
Next, install the starter site:
gridsome create my-blog https://github.com/gridsome/gridsome-starter-blog.git
cd my-blog
to move into the project directorygridsome develop
to start a local dev server at http://localhost:8080
Congratulations, we have now set up a stater site for us to modify to our own taste! 🎉
Visit http://localhost:8080
to access this site:
You can now open vsCode or your preferred code editor to tweak this site to your liking. For example, you can create a new home page, convert this page to a blog, and use this as your portfolio website.
Plugins enable additional functionalities that can be tied to your Gridsome app. Gridsome has a thriving ecosystem of plugins for complex integrations with many things. These are typically JavaScript libraries that you install using npm, and then configure to your project’s needs.
At the time of writing, Gridsome has 194 plugins, which you can access here. To install any Gridsome plugin, you can use npm or Yarn.
Any plugin that starts with
@gridsome/
means it’s an official plugin from the creators of Gridsome. To install a plugin, all you have to do is visit the general plugins page, search for the desired plugin, then follow the installation steps.
The first step to building a blog with Markdown is to create and set up a Gridsome project as explained earlier using gridsome create gridsome-blog
.
In this tutorial, I will be making use of two plugins:
@gridsome/source-filesystem
plugin to transform files into content that can be fetched with GraphQL in your components@gridsome/transformer remark
, a Markdown transformer for Gridsome with RemarkMarkdown is a lightweight markup language that you can use to add formatting elements to plaintext documents. Created by John Gruber in 2004, Markdown is now one of the world’s most popular markup languages. Markdown can be used for nearly everything, like websites, documents, notes, books, presentations, email messages, and technical documentation.
As explained earlier, you can use either Yarn or npm to install plugins. Lets install both at once with npm using the following:
npm i -S @gridsome/source-filesystem @gridsome/transformer-remark
Once your installation is successful, you will need to configure the @gridsome/source-filesystem
plugin within the gridsome.config.js
file. This is so Gridsome looks for the blog
folder and adds all posts to be queried later:
// gridsome.config.js
module.exports = {
siteName: 'Gridsome',
plugins: [
{
use: '@gridsome/source-filesystem',
options: {
typeName: 'BlogPost',
path: './blog/**/*.md',
},
},
],
templates: {
BlogPost: '/blog/:title',
},
};
The above configuration is what we need to set up the source-filesystem
plugin.
typeName
is the GraphQL type and template nameA
.vue
file insrc/templates
must match thetypeName
to have a template for it.
path
is the location of the markdown content we’ll be consuming in the posts/blogtemplates.BlogPost
is the route every post will follow i.e., localhost:8080/blog/new-post
So this doesn’t get too complicated later, let’s create our Markdown files/posts. These will serve as dummy blog posts. First, create the blog
folder which will contain our blog posts:
blog/welcome.md
---
title: 'Welcome to the blog'
date: 2020-04-20
---
## Welcome to the blog
This is the first post in this brand new blog.
Of course we have all the power of Markdown here,
so we can make things **bold** or _italic_.
blog/happy-easter.md
---
title: 'Happy Easter'
date: 2020-04-12
---
## Happy Easter
As it turns out I'm writing this on Easter,
so why not include a picture of a easter egg here.
!\[easter egg\](https://images.unsplash.com/photo-1457301353672-324d6d14f471?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=80)
To avoid confusion, this is what my file & folder structure looks like now:
Whenever you make changes in your gridsome.config.js
file or add new blog posts, you will need to hit (Ctrl + c) to restart the Gridsome development server so it picks up the new configuration and the files you have just created.
There are so many ways to get data into your site in Gridsome, but a very popular and simple means is via GraphQL. Since we have set up the plugin and created dummy posts, let’s check out the GraphQL playground.
Data can be queried from the GraphQL data layer into any page, template or component. Queries are added with a <page-query>
block in pages & templates or <static-query>
block in components.
Run gridsome develop
and navigate to http://localhost:8080/___explore:
# Write your query or mutation here
query {
posts: allBlogPost {
edges {
node {
id
title
date (format: "MMMM D, YYYY")
path
}
}
}
}
When you click the big Play button, we get the result below showing that the two blog posts we created as Markdown files are now available through the GraphQL endpoint:
{
"data": {
"posts": {
"edges": [
{
"node": {
"id": "46ea6f212d1378a5dcc360216e17dbc4",
"title": "Welcome to the blog",
"date": "April 20, 2020",
"path": "/blog/welcome-to-the-blog/"
}
},
{
"node": {
"id": "54c8892e9cf791f134c7ace95dcbcf5e",
"title": "Happy Easter",
"date": "April 12, 2020",
"path": "/blog/happy-easter/"
}
}
]
}
}
}
The next step is to query and display the data in either our components or pages. Earlier on we created a file Blog.vue
in our pages folder. Now that we have some content, let’s add it onto that page.
Let’s create a component BlogPostList
in src/components/
to make our project easier to maintain and test. In the BlogPostList.vue
file, use the code below:
// src/components/BlogPostList.vue
<template>
<div class="post-list">
<article class="post" v-for="post in posts" :key="post.node.id">
<h4>{{post.node.title}}</h4>
<p>Published on {{post.node.date}}</p>
<g-link :to="post.node.path">Read article</g-link>
</article>
</div>
</template>
<script>
export default {
props: ['posts']
}
</script>
<style>
.post-list {
margin-top: 12px;
}
.post {
padding: 12px 0;
}
</style>
This file is just receiving data as props from the Blog.vue
file into which we are about to fetch our blog posts.
We will use <page-query>
to get the list of blog posts from the GraphQL endpoint, as it’s a page:
// src/pages/Blog.vue
<template>
<Layout>
<h1>Blog</h1>
<p>This is the blog page.</p>
<BlogPostList :posts="$page.posts.edges"/>
</Layout>
</template>
<script>
import BlogPostList from '~/components/BlogPostList.vue';
export default {
metaInfo: {
title: 'Blog'
},
components: {
BlogPostList
}
}
</script>
<page-query>
query {
posts: allBlogPost {
edges {
node {
id
title
date (format: "MMMM D, YYYY")
path
}
}
}
}
</page-query>
Now when you access the blog page via http://localhost:8081/blog/
we should see the list of blog posts:
Now it’s time to create a post page. At this point, if you try to click the read article link below each post it will refer you to a 404 error page. This is because we have not yet created a page for each individual blog post.
The 404 page can easily be customized.
As a reminder, the typeName
is the GraphQL type and template name and a .vue
file in src/templates
must match the typeName
to have a template for it.
To create single pages for nodes in a collection (in this case the collection is BlogPost
), let’s create a new file, src/templates/BlogPost.vue
, where we define how the blog posts should look.
We’ll need to add a page query again to get the post itself out of the GraphQL endpoint, this time we’ll also need the field content
as it contains the body of the post in HTML:
// src/templates/BlogPost.vue
<template>
<Layout>
<article>
<header>
<h2>{{$page.post.title}}</h2>
<p>Published on {{$page.post.date}}</p>
<p><i>{{$page.post.timeToRead}}min to read</i></p>
</header>
<main class="content" v-html="$page.post.content"></main>
</article>
</Layout>
</template>
<style>
article > header {
text-align: center;
}
.content {
margin-top: 48px;
}
</style>
<page-query>
query Post ($path: String!) {
post: blogPost (path: $path) {
id
title
date (format: "MMMM D, YYYY")
timeToRead
content
}
}
</page-query>
With these we have been able to create a blog that fetches Markdown content and files as posts. Feel free to add additional content and features to your website here.
You can find my source code here
In this tutorial, I will be using the gridsome/source-faker
plugin to get data for the site. This data will be queried using GraphQL.
As explained earlier, you can either make use of yarn or npm to run this installation:
yarn add @gridsome/source-faker
or
npm install @gridsome/source-faker
Once you are done with the installation, the next step is to register the plugin in gridsome.config.js
:
export default {
plugins: [
{
use: '@gridsome/source-faker',
options: {
numNodes: 100
}
}
]
}
To make this site attractive, I will be using TailwindCSS. There are many options you can use to install TailwindCSS in Gridsome but I will be using their CDN.
In the main.js
file, we will be adding the head metadata and then include the external CSS/CDN link:
import DefaultLayout from '~/layouts/Default.vue'
export default function (Vue, { router, head, isClient }) {
// Set default layout as a global component
Vue.component('Layout', DefaultLayout)
head.link.push({
rel: 'stylesheet',
href: 'https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css'
})
}
After successfully setting up the plugin and TailwindCSS, the next step is to create a new page and then link it in our default layout:
After creating the new page, go to layouts/Default.vue
to include this new link in the navbar, knowing that Default.vue
appears on all pages as it’s used to wrap page components:
<template>
<div class="layout">
<header class="header">
<strong>
<g-link to="/">{{ $static.metadata.siteName }}</g-link>
</strong>
<nav class="nav">
<g-link class="nav__link" to="/">Home</g-link>
<g-link class="nav__link" to="/profile/">Profile</g-link>
<g-link class="nav__link" to="/about/">About</g-link>
</nav>
</header>
<slot />
</div>
</template>
To ensure that the new page makes use of defualt.vue
, we will need to wrap our code with the name given to it in main.js
, which is in layout
as explained earlier.
We’ve covered this topic earlier in this article, so you can follow along there for this part of the tutorial. You can find my source code here, and the live site here.
When working with Gridsome, the best way to deploy your site is to make use of a Git-service like GitHub, then connect a deploy service (Netlify, AWS Amplify, Vercel, Github Pages, Surge.sh etc.) that builds your site from a selected repository. Some of these services (Vercel and Surge.sh, for example) let you deploy your static Gridsome site from the Terminal.
Gridsome comes with a set of useful commands, both for development and production purposes:
Command | Description |
---|---|
create | Scaffolding tool that will enable you to create a Gridsome app in seconds using gridsome create my-app |
develop | Start a local development server at http://localhost:8080/ with hot-reloading using gridsome develop |
build | This command generates a static site inside a dist directory of your project using gridsome build |
explore | To start the GraphQL Playground and explore your schema or data, go to http://localhost:8080/___explore |
info | Outputs information about the local environment using gridsome info |
Two major things are needed to use Netlify to deploy you projects or websites:
If you have a GitHub and a Netlify account, then you can push your code to GitHub via Git.
Once you have pushed to GitHub, visit your Netlify dashboard via netlify.com and login:
Once you have logged in, you can now click the New site from Git button, then select GitHub as the Git provider where your site’s source code is hosted for continuous deployment:
You can now search for the repository so you can begin to deploy your website as seen in the image above.
Add the build command (gridsome build
) for Gridsome. It might take some time to deploy, but once its done you will be able to access your site via the link Netlify generates for you.
The Netlify Drop can also be used by making use of the generated dist
folder after running the gridsome build
command.
FTP stands for File Transfer Protocol, which is a set of rules that computers follow for the transferring of files from one system to another over the internet. To host your Gridsome site on a traditional hosting via FTP, you need to manually build your project from the Terminal by running gridsome build
in your project folder so as to generate a dist
folder where your generated site is located.
The generated folder can now be uploaded to any FTP.
As static site generators gain popularity, you must be able to understand building with SSGs like Gridsome to deliver content to your users by comfortably building static websites.
This article is just an introduction to Gridsome. You can check the official Gridsome documentation to learn more here.
To read more about Gridsome, here are some links you can check out:
If you have any questions, you can leave them in the comments section and I’ll be happy to answer every single one! Thanks for reading!
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowSimplify component interaction and dynamic theming in Vue 3 with defineExpose and for better control and flexibility.
Explore how to integrate TypeScript into a Node.js and Express application, leveraging ts-node, nodemon, and TypeScript path aliases.
es-toolkit is a lightweight, efficient JavaScript utility library, ideal as a modern Lodash alternative for smaller bundles.
The use cases for the ResizeObserver API may not be immediately obvious, so let’s take a look at a few practical examples.