preface

In “Building a Blog with VuePress + Github Pages”, we built a blog with VuePress, but looked at the final site: The TypeScript4 Chinese documentation does not have the last update date at the bottom of each article as in the official VuePress documentation:

In this article we will explore how to achieve the last update time.

The official cabin

Check the official VuePress documentation and you can see that VuePress comes with a plug-in that displays the last update time. Under the default theme, there is no need to install this plug-in because VuePress core already contains this plug-in.

You can use it directly in the config.js file:

// .vuepress/config.js
module.exports = {
  themeConfig: {
    lastUpdated: 'Last update'.// string | boolean}}Copy the code

Note that themeConfig. LastUpdated is off by default and is displayed as a prefix after a string is given (default: Last Updated).

In this sample code, we set the value of lastUpdated to “last update” and the final result should be the same as the screenshot from the VuePress website above.

Here, also give a use notice:

Because lastUpdated is Git-based, you can only enable it in a Git-based project. Also, because the timestamp used is from the Git commit, it will only be displayed after the first commit of a given page, and will only be updated when subsequent commit changes are made to that page.

Let’s try the configuration according to the document. The result is that there is no so-called last update time, because there is no content displayed, so there is also a large blank here:

View the plugin source code

So why is that? To review our code compilation and submission process, we actually wrote the source code locally, then executed the build command, git init the build result, and then forced the commit to the remote repository. This can be seen from our deploy.sh script file:

npm run docs:build

cd docs/.vuepress/dist

git init
git add -A
git commit -m 'deploy'

git push -f [email protected]:mqyqingfeng/learn-typescript.git master:gh-pages
Copy the code

We committed a commit as a Git repository, and we committed a commit as a git repository.

What is the last updated date? Git commit records automatically generated from git commit records.

To solve this problem, and to satisfy our curiosity, we took a look at the source code for the NPM package @vuepress/plugin-last-updated, which turned out to be surprisingly simple:

const path = require('path')
const spawn = require('cross-spawn')

/ * * *@type {import('@vuepress/types').Plugin}* /
module.exports = (options = {}, context) = > ({
  extendPageData ($page) {
    const { transformer, dateOptions } = options
    const timestamp = getGitLastUpdatedTimeStamp($page._filePath)
    const $lang = $page._computed.$lang
    if (timestamp) {
      const lastUpdated = typeof transformer === 'function'
        ? transformer(timestamp, $lang)
        : defaultTransformer(timestamp, $lang, dateOptions)
      $page.lastUpdated = lastUpdated
      $page.lastUpdatedTimestamp = timestamp
    }
  }
})

function defaultTransformer (timestamp, lang, dateOptions) {
  return new Date(timestamp).toLocaleString(lang, dateOptions)
}

function getGitLastUpdatedTimeStamp (filePath) {
  let lastUpdated
  try {
    lastUpdated = parseInt(spawn.sync(
      'git'['log'.'1'.'--format=%at', path.basename(filePath)],
      { cwd: path.dirname(filePath) }
    ).stdout.toString('utf-8')) * 1000
  } catch (e) { /* do not handle for now */ }
  return lastUpdated
}
Copy the code

Git log command to obtain the time, and then write the $page global attribute.

$page

$page = $page; $page = $page;

In VuePress, some core computational properties are built in for use by default themes or custom themes.

For each page, there is a $page attribute, and an example of $page is provided:

{
  "title": "Global Computed"."frontmatter": {
    "sidebar": "auto"
  },
  "regularPath": "/zh/miscellaneous/global-computed.html"."key": "v-bc9a3e3f9692d"."path": "/zh/miscellaneous/global-computed.html"."headers": [{"level": 2."title": "$site"."slug": "site"
    },
    {
      "level": 2."title": "$page"."slug": "page"},... ] }Copy the code

VuePress generates a $page calculated attribute for each page, and then displays the value of the calculated attribute in multiple places. What if we wrote a lastUpdated attribute to $page as in the source code?

Vue is used in Markdown

Each page is generated from a Markdown file. How can we write a lastUpdated attribute to $page in a Markdown file? However, in VuePress, markdown can use Vue syntax directly. Here is an example code for the vuepress-theme-reco theme:

<p class="demo" :class="$style.example">< p> <style module>. Example {color: #41b883; } </style> <script> export default { props: ['slot-key'], Mounted () {document.querySelector('.${this.$style.example} ').textContent = ' ' } } </script>Copy the code

The display effect on the page is as follows:

So let’s write the following Vue code directly in Markdown:

<script> export default {mounted () {this.$page. } } </script>Copy the code

We run the code locally and look at the page to see that the last update time was actually written successfully:

Vue components

However, it is troublesome to insert a section of Vue code into each article. I can reluctantly accept manual updating of the time, but I cannot accept manual updating of so many articles every time. Even if batch replacement is a little troublesome, isn’t there a better way to optimize?

We can separate the Vue code into a Vue component, encapsulate the specific time in the component, and then import it from each MD file. VuePress also supports importing components. Check out the official documentation:

All *. Vue files found in.vuepress/ Components are automatically registered as global asynchronous components, such as:

. └ ─. Vuepress └ ─ components ├ ─ demo - 1. Vue ├ ─ OtherComponent. Vue └ ─ Foo └ ─ Bar. The vueCopy the code

You can use these components directly in any Markdown file (component names are retrieved by filename) :

<demo-1/>
<OtherComponent/>
<Foo-Bar/>
Copy the code

Create a components folder in the.vuepress folder and create a LastUpdated. Vue file:

<template> </template> <script> export default { props: ['slot-key'], Mounted () {this.$page. }}; </script>Copy the code

Then we write in the MD file where we want to use this time:

<LastUpdated />
Copy the code

Nature also succeeded in writing time:

So every time we change the time in the LastUpdated component, all the places where the component was introduced will change the time.

Markdown

This problem seems to be solved by the way of curve saving the country, that is, every time you need to manually update, and all references will be updated, if you want to implement a local update, also need to write their own time, in fact, it is a bit troublesome.

Let’s review the official document again:

Because lastUpdated is Git-based, you can only enable it in a Git-based project. Also, because the timestamp used is from the Git commit, it will only be displayed after the first commit of a given page, and will only be updated when subsequent commit changes are made to that page.

And this from the official document:

LastUpdated is the last Git submitted UNIX timestamp for this file

Which document does “this file” refer to? The compiled file is HTML. Although it is submitted in the form of git repository, it should be static after it is compiled. It is not possible to obtain the last submission time through git repository while running THE HTML file. So this file should not refer to the compiled file, so if you exclude the compiled file, it should be the markdown file that you wrote. When you run a build command, get the time from the Git log and write it into the compiled code.

This also explains why the time is not displayed when we configure the source code according to the official documentation, because our source code is not a Git repository, we just submitted the compiled code to a repository, so we can’t get the time.

Git init (); git init (); git init ();

  1. Warehouse git init
  2. Commit the file at least once

Git add: git add: git add: git add: git add: git add

You’ve added another git repository inside your current repository.

This is because the dist directory we compiled is also a Git repository, but the solution is simple: we can ignore the dist directory with a.gitignore file. This is what the.gitignore file says:

node_modules
dist
Copy the code

If we run the code after the commit, we should see the last update time for each article:

Last updated

If you want to change the Last Updated: character before the time, you can say in config.js:

module.exports = {
    themeConfig: {
        lastUpdated: 'Last update'}}Copy the code

The display will look like this:

Change the format

If you want to change the format of the time display, refer to the official documentation of @vuepress/plugin-last-updated. You can write:

const moment = require('moment');

module.exports = {
  plugins: [['@vuepress/last-updated',
      {
        transformer: (timestamp, lang) = > {
          // Don't forget to install moment
          const moment = require('moment')
          moment.locale(lang)
          return moment(timestamp).fromNow()
        }
      }
    ]
  ]
}
Copy the code

The display effect is:

So far, although we have gone around, we have simply solved this problem.

series

Blog Building is the only practical tutorial series I’ve written so far, explaining how to use VuePress to build a blog and deploy it on GitHub, Gitee, personal servers, etc.

  1. Build a blog with VuePress + GitHub Pages
  2. This article will teach you how to synchronize GitHub and Gitee code
  3. Can’t use GitHub Actions yet? Look at this article
  4. How does Gitee automatically deploy Pages? GitHub Actions again!
  5. A Linux command with an adequate front end
  6. A simple enough Nginx Location configuration explained
  7. How to deploy your blog to your own server

Wechat: “MQyqingfeng”, add me Into Hu Yu’s only readership group.

If there is any mistake or not precise place, please be sure to give correction, thank you very much. If you like or are inspired by it, welcome star and encourage the author.