VuePress 博客优化之 last updated 最后更新时间如何设置

发表于 2年以前  | 总阅读数:1151 次

前言

在 《一篇带你用 VuePress + Github Pages 搭建博客》[1]中,我们使用 VuePress 搭建了一个博客,但是浏览最终搭建的站点:TypeScript4 中文文档[2],我们会发现,在每篇文章的底部,并没有像 VuePress 官方文档那样,出现最后更新的时间:

这篇我们来探究下如何实现最后更新时间。

官方自带

查阅 VuePress 的官方文档[3],我们可以知道,VuePress 自带显示最后更新时间的插件,在默认主题下,无需安装本插件,因为 VuePress 的 core 中已经包含此插件。

你可以在 config.js 文件中直接使用:

// .vuepress/config.js
module.exports = {
  themeConfig: {
    lastUpdated: '上次更新', // string | boolean
  }
}

注意,themeConfig.lastUpdated 默认是关闭的,在给定一个字符串后,它会作为前缀显示(默认值是:Last Updated)。

在这个示例代码中,我们设置 lastUpdated 的值为 "上次更新",最终的效果应该跟上面的 VuePress 官网的截图是一致的。

在这里,也给了一个使用须知:

由于 lastUpdated 是基于 git 的, 所以你只能在一个基于 git 的项目中启用它。此外,由于使用的时间戳来自 git commit,因此它将仅在给定页的第一次提交之后显示,并且仅在该页面后续提交更改时更新。

那我们按照文档配置一下试试,结果发现并没有出现所谓的最后更新时间,因为没有内容显示,显得这里的空白也很大:

查看插件源码

那这是为什么呢?回顾下我们代码编译和提交的过程,其实我们是在本地写好源码,然后执行构建命令,将构建后的结果 git init,然后强制提交到远程仓库。这从我们的 deploy.sh 脚本文件可以看出:

npm run docs:build

cd docs/.vuepress/dist

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

git push -f git@github.com:mqyqingfeng/learn-typescript.git master:gh-pages

那应该没有什么问题呀,我们就是作为 git 仓库提交的,也提交了一个 commit,为什么会显示不出来呢?

而且说起来,last updated 最后更新时间是怎么生成的呢?他怎么就根据 git 的提交记录自动生成时间了呢?

为了解决这个问题,也为了满足我们的好奇心,我们不妨去看下这个 npm 包 @vuepress/plugin-last-updated 的源码[4],结果发现它的源码意外的简单:

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
}

通过源码,我们可以发现,之所以能生成时间,其实是通过利用 git log 命令获取时间,然后写入 $page 全局属性中。

$page

那 $page 是什么呢,我们查看官方文档 - 全局计算属性[5]章节:

在 VuePress 中,内置了一些核心的计算属性[6],以供默认主题或自定义主题使用。

对于每个页面,都会有一个 $page 计算属性,官方还给了一个 $page 的示例:

{
  "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"
    },
    ...
  ]
}

我们由此可以想到,VuePress 其实针对每个页面都生成了一个 $page 计算属性,然后在多个地方展示计算属性的值,那突破口就来了,如果我们像源码那样,直接向 $page 写入一个 lastUpdated 属性呢?

Markdown 中使用 Vue

我们每个页面都是根据 markdown 文件生成的,我们怎么在一个 markdown 文件中向 $page 写入一个 lastUpdated 属性呢,还好在 VuePress 中,markdown 是可以直接使用 Vue 语法的,这里使用 vuepress-theme-reco 主题的示例代码作为讲解:

// 在 markdown 文案中直接写

<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>

在页面的展示效果如下:

那么我们直接在 Markdown 中直接写入如下的 Vue 代码:

<script>
export default {
    mounted () {
      this.$page.lastUpdated = "2022/1/6 下午6:09:09";
    }
  }
</script>

我们本地运行代码,然后查看页面,就会发现真的成功写入了最后更新时间:

Vue 组件

但是这样每篇都插入一段 Vue 代码,很麻烦呀,我可以勉强接受手动更新一下时间,但我不能接受每次那么多篇都要手动改一下呀,即便用批量替换也有点麻烦,就没有更优化的方式吗?

那我们可以将这段 Vue 代码抽离成一个 Vue 组件,将具体的时间封装在组件中,然后每个 md 文件引入这个组件即可,而 VuePress 也是可以支持引入组件的。查看下官方文档[7]:

所有在 .vuepress/components 中找到的 *.vue 文件将会自动地被注册为全局的异步组件,如:

.
└─ .vuepress
   └─ components
      ├─ demo-1.vue
      ├─ OtherComponent.vue
      └─ Foo
         └─ Bar.vue

你可以直接使用这些组件在任意的 Markdown 文件中(组件名是通过文件名取到的):

<demo-1/>
<OtherComponent/>
<Foo-Bar/>

那我们就在 .vuepress 文件夹下新建一个 components 文件夹,然后创建一个 LastUpdated.vue 文件,代码为:

<template>
</template>

<script>
export default {
  props: ['slot-key'],
  mounted () {
      this.$page.lastUpdated = "2022/1/6 下午2:00:00";
  }
};
</script>

然后我们在具体要使用这个时间的 md 文件里写入:

<LastUpdated />

自然也是成功的写入了时间:

这样我们每次修改 LastUpdated 组件里的时间,所有引入该组件的地方时间都会改变。

Markdown

这个问题看似是通过曲线救国的方式解决了,就是每次都需要手动更新一次,而且所有引用的地方都会更新,如果要实现某个地方局部更新,还要自己写入时间,其实还是有点麻烦的。

让我们再回顾下官方文档里的介绍:

由于 lastUpdated 是基于 git 的, 所以你只能在一个基于 git 的项目中启用它。此外,由于使用的时间戳来自 git commit,因此它将仅在给定页的第一次提交之后显示,并且仅在该页面后续提交更改时更新。

还有官方文档里的这句[8]:

lastUpdated 是这个文件最后一次 git 提交的 UNIX 时间戳

那这句里的 「这个文件」到底是指哪个文件呢?回想下我们的提交方式,我们每次只提交了编译后的文件,编译的文件为 HTML 文件,虽然它是以 git 仓库的形式提交的,但在它编译完后就应该已经是静态的了,不可能是在运行 HTML 文件的时候再通过 git 仓库获取最后提交时间的吧,所以这个文件不应该是指编译后的文件,那排除掉编译后的文件,其实我们就可以想到,这里的文件指的其实应该是你编写的 markdown 文件。在你执行编译命令的时候,从 git log 中获取时间,写入编译后的代码中。

这也可以解释为什么我们按照官方文档配置后,没有显示时间,因为我们的源码确实不是 git 仓库,我们只是把编译后的代码生成了一个代码仓库提交上去,那自然是获取不到时间。

所以我们进入源码的根目录,然后执行 git init,要注意,如果要生成最后更新时间,需要:

  1. 仓库 git init
  2. 文件至少 commit 一次

但当我们 git add 的时候,可能会报错,会提示你已经添加了另外一个 git 仓库在你当前的仓库:

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

这是因为我们编译生成的 dist 目录也是一个 git 仓库,但其实解决方式很简单,我们直接用一个 .gitignore 文件 将 dist 目录忽略掉不就好了,这是 .gitignore 文件写入的内容:

node_modules
dist

我们 commit 后再运行代码,就会看到每篇文章都会出现最后更新时间:

Last updated

如果你想更改时间前面的 Last Updated: 这段字符,你可以在 config.js 写入:

module.exports = {
    themeConfig: {
        lastUpdated: '上次更新'
    }
}

展示的效果就会变为:

更改格式

如果你想要更改时间展示的格式,参照 @vuepress/plugin-last-updated 的官方文档[9],你可以这样写:

const moment = require('moment');

module.exports = {
  plugins: [
    [
      '@vuepress/last-updated',
      {
        transformer: (timestamp, lang) => {
          // 不要忘了安装 moment
          const moment = require('moment')
          moment.locale(lang)
          return moment(timestamp).fromNow()
        }
      }
    ]
  ]
}

展示的效果为:

至此,虽然绕了一圈,但还是简单的解决了这个问题。

参考资料

[1]《一篇带你用 VuePress + Github Pages 搭建博客》: https://github.com/mqyqingfeng/Blog/issues/235

[2]TypeScript4 中文文档: http://ts.yayujs.com/

[3]官方文档: https://vuepress.vuejs.org/zh/plugin/official/plugin-last-updated.html#%E4%BD%BF%E7%94%A8

[4]源码: https://github.com/vuejs/vuepress/blob/master/packages/%40vuepress/plugin-last-updated/index.js

[5]官方文档 - 全局计算属性: https://vuepress.vuejs.org/zh/guide/global-computed.html#site

[6]计算属性: https://cn.vuejs.org/v2/guide/computed.html#%E8%AE%A1%E7%AE%97%E5%B1%9E%E6%80%A7

[7]官方文档: https://vuepress.vuejs.org/zh/guide/using-vue.html#escaping

[8]这句: https://vuepress.vuejs.org/zh/theme/writing-a-theme.html#%E7%BD%91%E7%AB%99%E5%92%8C%E9%A1%B5%E9%9D%A2%E7%9A%84%E5%85%83%E6%95%B0%E6%8D%AE

[9]@vuepress/plugin-last-updated 的官方文档: https://vuepress.vuejs.org/zh/plugin/official/plugin-last-updated.html

本文由哈喽比特于2年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/lEldZzKAHaiPyaURK_2CdQ

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 目录