# VuePress Tutorial 15 - Blog Plugin
# What We're Doing
It's now time to install and begin the process of configuring @vuepress/plugin-blog (opens new window). We're going to start by describing the main features provided by the plugin. Then we'll go over the installation and usage. After going over the installation and usage, we'll describe the concepts and implementation of document classification, permalinks, and directory classification.
If you're interested you can check out the blog plugin code here (opens new window). You can also check out the @vuepress/theme-blog (opens new window) if you're interested in learning more about it. We won't be discussing the blog theme in detail since we're using the default theme (opens new window).
Make sure you start the local development server which should be running at http://localhost:8080/ (opens new window) to see the changes we'll be making to the site. If the changes aren't appearing after you save them, then try restarting your local development server.
You can view all of the code in this tutorial by going to the tutorial-15
branch of the code-monkeys-blog-tutorials (opens new window) repository.
# Features
The blog plugin provides the following main features:
- Classification (opens new window) which means you can quickly classify posts by using their characteristics.
- Pagination (opens new window) which allows you to break up the display of your posts into multiple pages. This provides easier navigation and a better user experience.
- Client API (opens new window) which allows you to access global variables that contain data about pagination, frontmatter, and the various services the plugin provides.
We'll be discussing pagination and the Client API in more detail in future tutorials.
# Installation
We're now ready to discuss the installation of the plugin.
# Using the Tutorials Repo
If you're following along with the tutorials, then when you switch to the tutorial-15
branch you can run the following command to install the package instead of running the installation command:
This will ensure you have the same version used in the blog since the command uses the version specified in the yarn.lock
file during the installation.
# Using the Installation Command
To install the blog plugin in your own project you can run the following command:
Installing the Same Blog Plugin Version
If you want to ensure you're installing the same version being used in the tutorials and blog, then run yarn upgrade @vuepress/plugin-blog@1.9.4
.
# Updated package.json File
After installing the plugin, the package.json
file should look something like this:
# Automatically Installed Plugins
When installing the blog plugin you may have noticed the following plugins also get installed:
- @vssue/vuepress-plugin-vssue (opens new window)
- vuepress-plugin-disqus (opens new window)
- vuepress-plugin-feed (opens new window)
- vuepress-plugin-mailchimp (opens new window)
- vuepress-plugin-sitemap (opens new window)
These plugins provide features that are common to blogs, so they're included in the installation of the blog plugin. Including these plugins in the installation of the blog plugin saves you the time of searching for plugins that provide these common features as well as from having to separately install each plugin.
The plugins will only be used though if you enable them in the config.js
file.
They can also be installed as standalone plugins, so you don't need to use the blog plugin to use them for your site.
We'll be discussing these plugins in more detail in future tutorials.
# Usage
To use the blog plugin we need to add the following to the config.js
file which should now look something like this:
# Document Classification
The blog plugin provides a document classifier which is a set of functions that handles the classifications of pages with the same characteristics.
These characteristics for pages in a blog may consist of:
- Pages in the same directory, e.g., a
_posts
directory. - Pages containing the same frontmatter key, e.g.,
tag: js
which signifies those pages contain content related tojs
, i.e.,JavaScript
.
Another common requirement is the ability to group all pages as well as pages with specific tags for pagination.
Before discussing directory classification, we're going to first define what a permalink is as well as discuss how they're built and configured. This will give us a better understanding of how the blog plugin uses permalinks to build customizable links for blog posts which is preferable to using the default way of creating links.
# Permalinks
A permalink is a URL that is intended to remain unchanged for a long time. This leads to links that are less susceptible to link rot (opens new window) which is when a link ceases to point to its originally targeted web page due to the page being relocated to a new address or becoming permanently unavailable.
VuePress v1 (opens new window) provided support for creating customizable links by introducing the ability to build permalinks.
# Template Variables
We're able to build permalinks by using the following template variables:
Variable | Description |
---|---|
:year | Published year of post (4-digit) |
:month | Published month of post (2-digit) |
:i_month | Published month of post (without leading zeros) |
:day | Published day of post (2-digit) |
:i_day | Published day of post (without leading zeros) |
:slug | Slugified file path (without extension) |
:regular | Permalink generated by VuePress by default. |
# Default Configuration
The default configuration for permalinks is /:regular
.
The :regular
template variable will first check if the Markdown files in the documents directory which in our case is the docs
directory are index files, i.e., README.md
or index.md
.
- If they're index files, they get converted to URLs without extensions that are based on the file hierarchy.
- If they're not index files, they get converted to URLs with
html
extensions that are based on the file hierarchy.
Let's look at some examples to make this clearer where the file paths are relative to the documents directory which again in our case is the docs
directory:
Relative Path | Page Routing |
---|---|
/README.md | / |
/foo/README.md | /foo/ |
/foo.md | /foo.html |
/foo/bar.md | /foo/bar.html |
Using Vue Files
Files with a vue
extension follow the same conventions described for Markdown files above, e.g., /README.vue
gets converted to /
.
You can take a look at fileToPath.ts (opens new window) to see the code that handles converting files to paths.
# Global Configuration
To globally change the default configuration for permalinks for your site you can add the permalink
property to the config.js
file.
We can build a permalink to use in the config.js
file by using the template variables.
For example we can use the template variables to build the following permalink: /:year/:month/:day/:slug
.
We can then set this as the value for the permalink
property in the config.js
file:
Using the Default Configuration
We'll be leaving the permalink
property with the default value of /:regular
, and we'll use the configuration provided by the blog plugin to customize the permalinks for each blog post.
# Local Configuration
It's also possible to set a permalink locally for a single page which overrides any globally set configuration.
This is done be setting the permalink
property in the frontmatter of the Markdown file:
This will set the permalink
property to be /using-a-local-permalink
instead of following the global configuration.
Now that we have an understanding of document classification and permalinks, let's move onto the directory classifier which handles classifying pages placed in the same directory.
# Directory Classification
First we need to create a directory that will contain all of the pages we want to classify. To do this we'll create a _posts
directory inside of the docs
directory. The docs
directory for your site should now look something like this:
.
├── docs
│ ├── .vuepress
│ ├── _posts
│ ├── icons
│ └── README.md
Next, we'll create the following example pages in the _posts
directory:
2020-07-03-example-page-1.md
2021-11-16-example-page-2.md
2022-05-08-example-page-3.md
The _posts
directory for your site should now look like this:
.
├── _posts
│ ├── 2020-07-03-example-page-1.md
│ ├── 2021-11-16-example-page-2.md
│ └── 2022-05-08-example-page-3.md
By default VuePress (opens new window) will create the following page URLs since it uses the /:regular
template variable described above when building the links:
/_posts/2020-07-03-example-page-1.html
/_posts/2021-11-16-example-page-2.html
/_posts/2022-05-08-example-page-3.html
You should now be able to navigate to these pages in the browser:
- http://localhost:8080/_posts/2020-07-03-example-page-1.html (opens new window)
- http://localhost:8080/_posts/2021-11-16-example-page-2.html (opens new window)
- http://localhost:8080/_posts/2022-05-08-example-page-3.html (opens new window)
The default behavior is fine for creating the main pages on the site, but having the ability to build customizable links for blog posts is preferable.
After using the configuration provided by the blog plugin to build customized permalinks, the page URLs will look like this:
/2020/07/03/example-page-1/
/2021/11/16/example-page-2/
/2022/05/08/example-page-3/
To build these customizable links we're going to start setting up the directory classifier configuration in the config.js
file.
# directories
First, we'll add the directories
property which is used to create the directory classifier.
The expected type is a DirectoryClassifier[]
, and the default value is []
.
Here's the updated config.js
file:
# id
Next, we'll add the id
property which sets a unique id for the current classifier. We'll use a value of posts
.
The expected type is a string
, and the default value is undefined
.
Here's the updated config.js
file:
# dirname
Now, we'll add the dirname
property which is used to identify the directory we want to classify. This is the _posts
directory we created earlier.
The expected type is a string
, and the default value is undefined
.
Here's the updated config.js
file:
After setting the dirname
property, the page URLs get set to the customized permalinks mentioned above:
- http://localhost:8080/2020/07/03/example-page-1/ (opens new window)
- http://localhost:8080/2021/11/16/example-page-2/ (opens new window)
- http://localhost:8080/2022/05/08/example-page-3/ (opens new window)
The customized permalinks are actually built using properties we haven't discussed yet. The blog plugin sets default values that don't need to be explicitly set in the config.js
file. We'll be discussing these other properties and their default values below.
The previously provided links still work because they get converted to the customized permalinks when navigating to those pages.
Unknown Custom Element
When navigating to the links if you inspect the browser then go to the Console
, you'll see the following error: Unknown custom element: <Post>
.
This error is occurring because the plugin is looking for a Post
layout component in the layouts
directory which we haven't created yet.
Before creating a Post
layout component to fix this error, we're going to first add the path
property.
# path
The path
property specifies the entry page, also known as the list page for the current classifier. This page will be used to display your posts as a paginated list.
The expected type is a string
, and the default value is /${id}/
where ${id}
is the value of the id
property we previously set.
This means you don't need to explicitly set the path
property if you're going to be using the same value as the id
property. We'll be using a value of /posts/
for the path
property, so we don't need to explicitly set the property. However, we're going to explicitly set the property because it allows us to have a quick reference to the property and its value.
Here's the updated config.js
file:
You can navigate to the entry page by using the following link:
Notice this link has the value of the path
property in it, i.e., /posts/
. This is the same link we set in the navbar dropdown menu for All Posts, so you can click on that link to navigate to the entry page which will eventually be a paginated list of all of the posts.
Currently, when navigating to that link the Layout
component provided by the default theme (opens new window) is displayed. The blog plugin will fallback to using the Layout
component if it's unable to find an IndexPost
layout component in the layouts
directory.
This means we can create an IndexPost
layout component that specifically handles the layout of the paginated list of all of the posts instead of using the Layout
component.
# Creating the IndexPost Layout
To create the IndexPost
layout component we're going to add an IndexPost.vue
file inside of the layouts
directory. The layouts
directory for your site should now look something like this:
.
├── layouts
│ ├── GlobalLayout.vue
│ └── IndexPost.vue
We're going to begin the development of the IndexPost
layout component by adding template
, script
, and style
tags:
We'll continue developing the IndexPost
layout component in a future tutorial.
# layout
We're now ready to add the layout
property which is used to specify which layout to use for the entry page.
The expected type is a string
, and the default value is 'IndexPost' || 'Layout'
.
From the default value we can see why the entry page originally defaulted to using the Layout
component before we created the IndexPost
layout component. Since the blog plugin looks for the IndexPost
layout component by default, we don't need to explicitly set the property. However, we're going to explicitly set it because this gives us a quick reference to the property and its value.
It's also possible to use a custom value for the layout
property, e.g., you could use a value of MyIndexPost
which you would have to explicitly set in the config.js
file. Then you would have to create a MyIndexPost.vue
file inside of the layouts
directory.
Here's the updated config.js
file:
We're now going to fix the Unknown Custom Element
error we got after adding the dirname
property. To fix this error we need to create the previously mentioned Post
layout component.
# Creating the Post Layout
The Post
layout component is used to handle the layout for individual post pages.
To create the Post
layout component we're going to add a Post.vue
file inside of the layouts
directory. The layouts
directory for your site should now look something like this:
.
├── layouts
│ ├── GlobalLayout.vue
│ ├── IndexPost.vue
│ └── Post.vue
We're going to begin the development of the Post
layout component by adding template
, script
, and style
tags:
We'll continue developing the Post
layout component in a future tutorial.
# itemLayout
We're now ready to add the itemLayout
property which is used to specify which layout to use for individual post pages.
The expected type is a string
, and the default value is 'Post'
.
From the default value we can see why the blog plugin looks for a Post
layout component. Since the blog plugin looks for the Post
layout component by default, we don't need to explicitly set the property. However, we're going to explicitly set it because this once again gives us a quick reference to the property and its value.
It's also possible to use a custom value for the itemLayout
property, e.g., you could use a value of MyPost
which you would have to explicitly set in the config.js
file. Then you would have to create a MyPost.vue
file inside of the layouts
directory.
Here's the updated config.js
file:
# itemPermalink
We're now ready to add the itemPermalink
property which is used to build customized permalinks for each blog post.
The expected type is a string
, and the default value is '/:year/:month/:day/:slug'
.
From the default value we can see how the blog plugin built the customized permalinks after only setting the dirname
property. Since the blog plugin uses the value we currently want, we don't need to explicitly set the property. However, just like the other properties we're going to explicitly set it because this gives us a quick reference to the property and its value.
Here's the updated config.js
file:
# Summary of URLs and Layouts
Here's a table that summarizes the relationship between the page URLs the blog plugin builds using customized permalinks and the layout components.
URLs | Layouts |
---|---|
/posts/ | IndexPost (falls back to Layout ) |
/2020/07/03/example-page-1/ | Post |
/2021/11/16/example-page-2/ | Post |
/2022/05/08/example-page-3/ | Post |
# Next Steps
In the next tutorial we'll be discussing the configuration for the pagination
property as well as how to access the pagination data in the layout components by using the Client API.