用vuepress搭建一个够自己用的博客(带评论及cdn)

原文博客
最新升级:vuepress2.X搭建博客

闲扯

很久以前,自己拥有一个用hexo搭建的静态博客网站:ox:,记得当时为了把它搞出来,废了不少劲:anger:,然后后来又断断续续更改过一些配置和样式,但是因为感觉各种麻烦,所以就放在github上积累和很多的尘土:cupid:,到现在也懒得在打扫了(其实是好久不用,有点忘了怎么用了:-1::poop:),前段时间在百度统计上看了看那个静态网站的访问人数,发现已经很久很久没人访问过了,:sweat_smile:,然而就在前段时间(没错,就是前面那个时间),我灵光一闪,为啥不重新弄个静态博客呢:heart_eyes:,于是我就决定洗洗睡觉(没错,那是一个夜深人静的晚上),第二天抽空找个简单点的框架,然后搭个静态博客,用来记录自己的所见所闻所想:tada:
第二天一大早吃完中午饭后(睡到中午了:sunglasses:),我就看起了VuePress官网,没错,我选择了VuePress框架,至于为什么呢,有以下几点:

1、 目前开发用vue框架:fire:
2、 就是想用它搞一个:muscle:
3、 反正也简单,实在不行再换呗(搞不起来是不可能的):clap:
4、 没有别的理由了:notes:

它有什么好处、特性、和别的框架对比?看人家官网就得了,说的挺好的

项目搭建

没啥好说的,按照人家官网搭就完事了,人家写的那么清晰、明了。感觉尤大出品的文档都很友好,阅读起来很方便

# 将 VuePress 作为一个本地依赖安装
yarn add -D vuepress # 或者:npm install -D vuepress

# 新建一个 docs 文件夹,你也可以打开编辑器来手动创建
mkdir docs

# 新建一个 markdown 文件
echo '# Hello VuePress!' > docs/README.md

# 启动,让你感受下效果-----but:这种启动方式不爽,还是放package.json里省事,所以感受完了就结束进程吧,
npx vuepress dev docs

项目安装完成后,我们进入package.json里面,添加script启动项

 "scripts": {
    "docs:dev": "vuepress dev docs",
    "docs:build": "vuepress build docs"
  }

上面一顿操作后我们现在要知道三件事情:

1、我们以后所有的文章都将在docs中写

2、开发,也就是写作的时候执行:

yarn docs:dev # 或者:npm run docs:dev // 默认端口http://localhost:8080/

3、打包生成静态html文件,执行

yarn docs:build # 或者:npm run docs:build

默认情况下,生成的静态文件放在.vuepress/dist中,不过可以改的
好了,先来认识下我们以后要大展拳脚的地方 docs目录:

.
├─ docs //以后要在这里面写文章,直接在此文件夹下新建文件夹,然后再建md文档就行,链接会自动生成
│  ├─ README.md // 这个将会是我们以后的首页
│  └─ .vuepress // 这个里面会存放一些配置和组建
│     └─ public  // 静态文件存放地
│     └─ components  // 组建存放地
│     └─ config.js //配置文件,我们以后的所有配置基本都在这里写
└─ package.json

原谅我这部分说的比较糙,其实这部分看官网就好了,人家讲的的确挺详细的,要讲的主要是下面的内容:

首页配置

官网默认主题提供了一个只需要写写配置就能生成的页面,格式是固定的,和VuePress的首页一毛一样,但是这不是我想要的(我也不知道我想要什么样的),所以我在.vuepress/components中新建了一个组建叫home,同时在首页引入:(md文件里可以写vue代码的哦)

// 记得不要复制注释
---
navbar: false       // 不要导航栏
isNoPage: true       // 自定义的属性
sidebar: false        // 不要侧导航
pageClass: home-list  //自定也页面类
---
<home />

.vuepress/components/home.vue和我们平时写vue没啥区别,引用的时候就用这个文件的文件名就可以了,官网有介绍,因为目前还没想好首页改做成什么样的,所以就先这样放着
isNoPage是我自己写的,主要是为了标志当前是否是文章页,以后会用来做判断,在this.$site.frontmatter中存放
pageClass是页面自定义类,编译的时候会把这个类加在外层的div中,可以根据这个来写自己想要的样式

/**这段css可以写在.vuepress/style.styl中,这个是我对首页写的样式**/
home-list{
  .page-edit{
    display: none /**隐藏首页的编辑和最后修改时间标签**/
  }
  #gitalk-container{
    display:none  /**隐藏首页的评论**/
  }
}

列表页的实现

每一张文章页,我都会在头部添加

---
tags: vuepress, 前端
description: 本文介绍应该VuePress搭建一个博客,据官网说:VuePress 由两部分组成:一部分是支持用 Vue 开发主题的极简静态网站生成器,另一个部分是为书写技术文档而优化的默认主题。它的诞生初衷是为了支持 Vue 及其子项目的文档需求。
---
  • tags: 是当前页面的标签,用于在列表页生成标签云
  • description:页面的描述信息,在列表页会显示,官网中有获取more之前的方法,但是会有样式,所以会感觉很难看,所以我就添加的这个description字段,当然,我也并没有放弃官网的方法,因为有时候可能真的懒得写描述信息了,所以加了个判断
<div v-if="item.frontmatter.description" class="art">
  {{item.frontmatter.description}}……<a :href="item.path" class="look">阅读原文</a>
</div>
<div class="art" v-html="item.excerpt" v-else></div>

获取说有文章的列表我是通过一开始设置的isNoPage来做的判断

const arts = this.$site.pages.filter(item => {
  return !item.frontmatter || !item.frontmatter.isNoPage
})

标签的实现

我的标签是一个vue组建,然后在列表页引入改组件;上面说到,我在每个文章前面都会加tags,我会在标签组件中通过遍历this.$site.pages,拿到所有的标签,然后去重,即是我所有页面的标签

<template>
  <div class="tags">
    <h6>标签云</h6>
    <span v-for="item in tags" @click="handleChangeTag(item)">{{item}}</span>
    <span @click="handleChangeTag('all')">所有</span>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tags: []
    }
  },
  created() {
    const tags = this.$site.pages.map(item => {
      return item.frontmatter && item.frontmatter.tags || ""
    })
    const tagsArr = tags.join(",").split(",").filter(i => i !== "")
    this.tags = [...new Set(tagsArr)]
  },
  methods: {
    // 点击标签更改列表
    handleChangeTag(tag) {
      this.$emit('change-tag',tag)
    }
  },
}
</script>

favorite.icon配置

favorite.icon也就是网页左上角那个小图标

image

首先我们需要一个小图标,然后放在.vuepess/public下,然后
打开.vuepress/config.js,添加

head:[
    ['link', { rel: 'shortcut icon', href: '/favorite.icon type: 'image/jpg' }]
]

注意href写的是/favorite.icon,而不是/public/favorite.icon

样式更改

.vuepress下新建两个styl文件用来写样式

override.styl:用来覆盖默认主体样式,比如我想让我的内容占据屏幕的90%,可以:

$contentWidth = 90%

style.styl:写自己一些自定义的样式,可以在这个文件夹里写,比如单独修改导航的颜色

.navbar{
  background:red
}

官网对此的介绍

对复制进行修改

我们对掘金进行大段文字复制的时候会显示版权信息:

用vuepress搭建一个够自己用的博客
作者:给我讲个笑话
链接:https://juejin.im/post/5ce94553e51d455c8838e0d5
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

那么我们如何在博客中实现这个功能呢 ,其实很简单,
首先修改我们的.vuepress/enhanceApp.js文件(enhanceApp.js介绍

import copy from './common/copy'

export default ({
  Vue, // VuePress 正在使用的 Vue 构造函数
  options, // 附加到根实例的一些选项
  router, // 当前应用的路由实例
  siteData // 站点元数据
}) => {
  setTimeout(() => {
    try {
      document && (() => { //对document的判断是防止编译的时候报错
        copy()
      })()
    } catch (e) {
      console.error(e.message)
    }
  },500)
}

然后新建一个copy.js的文件

export default () => {
  function addCopy(e) {
    let copyTxt = ""
    e.preventDefault(); // 取消默认的复制事件
    copyTxt = window.getSelection(0).toString()
    copyTxt = `${copyTxt}\n作者:静水深流\n原文:${window.location.href}\n著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。`
    const clipboardData = e.clipboardData || window.clipboardData
    clipboardData.setData('text', copyTxt);
  }
  document.addEventListener("cut", e => {
    addCopy(e)
  });
  document.addEventListener("copy", e => {
    addCopy(e)
  });
}

这样就可以实现了,有兴趣可以去博客体验一下

添加评论

作为一个有灵魂的博客,怎么可以不能评论呢,我能忍,博客也不能忍:star2:,我的评论系统用的是GITALK,官网说是这是一个基于 Github Issue 和 Preact 开发的评论插件,现在用的多的貌似还有valinegitment,这个貌似可以统计阅读量;希望gitalk也能出个阅读量统计功能,官网提供的方式有两种,一种是在html中引入js文件,另一种是用npm包的形式,我选择的是通过js将评论需要的js和css用js动态插入到页面中,首先修改.vuepress/enhanceApp.js中的代码:

import getGitalk from "./common/getGitalk"
import copy from './common/copy'

export default ({
  Vue, // VuePress 正在使用的 Vue 构造函数
  options, // 附加到根实例的一些选项
  router, // 当前应用的路由实例
  siteData // 站点元数据
}) => {
  setTimeout(() => {
    try {
      document && (() => {
        getGitalk.call(this, siteData)
        copy()
      })()
    } catch (e) {
      console.error(e.message)
    }
  },500)
}

getGitalk.js的实现如下

export default ({pages})=> {
  const path = window.location.pathname
  // 获取当前页面信息
  const dist = pages.filter(item => {
    return item.path === path
  })[0]

  //只有在isNoPage是false的时候才会显示评论
  if (!dist.frontmatter || !dist.frontmatter.isNoPage) {
    const page =document.querySelector('.page')

    const linkGitalk = document.createElement('link');
    linkGitalk.href = 'https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.css';
    linkGitalk.rel = 'stylesheet';
    document.body.appendChild(linkGitalk);

    const scriptGitalk = document.createElement('script');
    scriptGitalk.src = 'https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.js';
    document.body.appendChild(scriptGitalk);

    scriptGitalk.onload= () => {
      let gitalk = document.createElement('div')
      gitalk.id = 'gitalk-container'
      page.appendChild(gitalk)
      var _gitalk = new Gitalk({
        clientID: '11111111111111',
        clientSecret: '2222222222222222',
        repo: 'slbyml.github.io', // 存储评论的仓库名字
        owner: 'slbyml',
        admin: ['slbyml'],  //仓库的管理员,可以有多个
        id: decodeURI(path),      // 每个页面根据url生成对应的issue,保证页面之间的评论都是独立的
      })
      _gitalk.render('gitalk-container')
    }
  }
}

对于gitalk的用法请看官网,但是要讲两个元素clientSecretclientSecret,这两个怎么来的呢,是在这申请的,创建完成后可以看到生成的这两个字段

申请ID

::: tip 注意:
如果想在框架中引入第三方框架,比如element-ui,也可以在这个js中引入注册
:::

部署

部署就简单了,我目前是两个仓库,一个私有的,用来存放源代码,一个就是用来存放生成的静态文件的仓库
更改package.json->script:

"scripts": {
    "docs:dev": "vuepress dev docs",
    "docs:build": "vuepress build docs",
    "deploy": "bash deploy.sh"  // 新加的,用来生成静态文件及上传到github
  }

然后根目录下新建deploy.sh文件:

#!/usr/bin/env sh

# 确保脚本抛出遇到的错误
set -e

# 生成静态文件
npm run docs:build

# 进入生成的文件夹
cd dist

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

# 如果发布到 https://<USERNAME>.github.io/<REPO>
git push -f git@github.com:slbyml/blog.git master

cd -

我的默认生成的静态文件在根目录下的dist,因为我更改了config.js里的配置,保证docs里面的文件是干净的

dest: 'dist'

这样在我执行npm run deploy的时候就会自动生成静态文件,并上传的github上,是不是很方便

静态文件上传cdn

最近感觉网站加载js和css很慢,需要一两秒之巨,作为一个有作为的前端,必须要想办法做优化,最省事的方法就是将静态文件上传的cdn上,我这里采用上传到阿里云;
我一开始是将配置放在了.vuepess/config.jsconfigureWebpack中,上传成功后发现在页面上打包文件app.hash.js根本不执行,调试很久也没找到原因,感觉可能是因为打包文件中开头没有了(window.webpackJsonp=window.webpackJsonp||[]).push([[0],[]]);;具体为啥没有这个,就不得而知了,
现在采用的办法是在deploy.sh中执行上传;以我上传阿里云为例(七牛等其它cdn同理);先安装包webpack-aliyun-oss;然后根目录新建一个upload.js用来放上传代码

const WebpackAliyunOss = require('webpack-aliyun-oss');
new WebpackAliyunOss({
  from: './dist/assets',
  dist: 'dist',
  region: '阿里云上传区域;例:oss-cn-beijing',
  deletOrigin: true,
  accessKeyId: '你的accessKeyId',
  accessKeySecret: '你的accessKeySecret',
  bucket: 'slbblog',
  setOssPath: filePath => {
    // some operations to filePath
    let index = filePath.lastIndexOf("dist");
    let Path = filePath.substring(index + 4, filePath.length);
    return Path.replace(/\\/g, "/");
  },
  setHeaders(filePath) {
    // some operations to filePath
    return {
      'Cache-Control': 'max-age=31536000'
    }
  }
}).apply();

然后将deploy.sh中执行此文件

#!/usr/bin/env sh

# 确保脚本抛出遇到的错误
set -e

# 生成静态文件
npm run docs:build
# 上传文件
node './upload.js'

# 进入生成的文件夹
cd dist

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

# 如果发布到 https://<USERNAME>.github.io/<REPO>
git push -f git@github.com:slbyml/blog.git master
git push -f git@e.coding.net:slbyml-01/slbyml.coding.me.git master 

cd -

最后将页面引用的静态文件路径换位阿里云的.vuepess/config.js

module.exports={
  // 省略别的配置
  configureWebpack: (config, isServer) => {
    if (process.env.NODE_ENV === 'production') {
      // 将地址改为你的阿里云地址
      config.output.publicPath = '//slbblog.oss-cn-beijing.aliyuncs.com/dist/'
    }
  }
}

这样大功告成,测试也没啥问题;以后静态文件就可以愉快的加载cdn文件了,js文件加载时间降到了ms级别;

最后,这些都是我自己做的事情,可能会有更好的实现,所以欢迎讨论!!:clap:
以后想添加的东西:

  • 添加下拉加在更多功能
  • 添加文章阅读量和文章字数
  • 丰富列表页
  • 丰富首页

最后的最后这篇文字也是突发奇想写的,刚开始不知道写啥,所以就边写变想该写啥(负面教学,别学我),没想到写着写着,文思泉涌:clap: ,一片文采华丽的文章就这么诞生了,从没发现自己还有写文章的天赋。
转载原文

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容

  • 基于Vue的一些资料 内容 UI组件 开发框架 实用库 服务端 辅助工具 应用实例 Demo示例 element★...
    尝了又尝阅读 1,140评论 0 1
  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML标准。 注意:讲述HT...
    kismetajun阅读 27,421评论 1 45
  • VuePress从零开始搭建自己的博客 最近将自己的博客从Hexo转移到VuePress中来,使用VuePress...
    codeteenager阅读 2,733评论 0 2
  • Vue2.0+组件库总结 UI组件 element - 饿了么出品的Vue2的web UI工具套件 Vux - 基...
    szch阅读 1,958评论 1 52
  • UI组件 element - 饿了么出品的Vue2的web UI工具套件 Vux - 基于Vue和WeUI的组件库...
    卞卞村长L阅读 1,696评论 0 8