从零开始搭建和mybatis-plus官网一样主题的网站(cos+宝塔+vercel)

2022-09-13 09:41:24 浏览数 (2)

一、前言

网站主题最初是在开发数据api的时候看到的,当时在学习Mybatis-Plus,最初也不知道这是个主题,就觉得Mybatis-Plus官网UI真的不错,直到后面发现另外一个类似的网站,我意识到这是个模板,于是有了自己也搭建一个的想法,不过拖延症相当严重,最初是在宝塔上修改的,效率极低,一度放弃部署,直到最近换成本地开发才好了很多,也就是最近网站搭建初步完成,接下来就是往里面增加文章等等,这里带大家从零开始搭建Vdoing主题网站,算是对过去一个月的知识总结。下图就是mybatis-plus官网,是我们年轻人喜欢的风格(这里随便吐槽一下xx园吧,风格还是20年前的,不知道他们的UI设计师是不是还是兼职的)。

二、流程简要描述

如果你是个新手或者是对网站搭建有一定经验的老手,务必先看这段简要描述。

  • 首先GitHub fork作者大大的仓库,便于二次修改,作者也是建议直接fork仓库,然后在仓库中修改自己的配置
  • 如果你有vercel的账号并且完成过网站部署,接下来对你而言只需要一步你的网站就可以上线了,在vercel上创建基于该仓库的一个项目,然后配置相关信息就可以直接build运行了。至此,关于老手的教程结束(汪汪.jpg)。
  • 若从未接触过vercel可以参考下面的vercel部署模块,我们接下来谈谈宝塔和cos部署,二者部署起来流程差不多,都是本地先build打包好一个dist的文件夹,然后上传到cos或者宝塔的站点中,然后cos需要开启一下静态的网站选项,保证可以直接读取到默认的例如index.html等等首页的选项,宝塔只需要创建一个静态网站即可。至此新手的教程结束了(汪汪.jpg)。
  • 若你是名老手,你可能会觉得,这好像还不太够,例如网站的信息统计,网站的评论,网站的站点信息,网站的广告模块,网站如何进行调试等等,觉得不够的可以查看下面的相关内容,这些模块是网站的加分项,可选,若是新手一点不懂这些模块的作用,可以跳过相关部署。
  • 网站部署完,你可能觉得本地开发咋整,其实很简单,把写好的md文件按照约定的文件命名规则放入相应的文件夹即可,如果是采用vercel自动化托管的网站,此时只需要git push到远程仓库,等待编译完成就可以看到新的改动已经被添加到网站上了。

新手的话,可能会被这几个概念弄得云里雾里的,DNS、域名、IP,这几个概念是相互关联的,以下做一点简要介绍:IP即访问网站的唯一地址,这个地址一般由比较多的数字构成,我记得10年前第一次用诺基亚手机上网时就是用的数字ip地址,当时也不知道域名是啥,你可能会觉得有一点烦,为啥ip地址这么长,又不好记,这是技术原因,为了保证ip地址够用而设计的,不过到现在,似乎真的有点不够用了,所以ipv6产生了,为了解决ip地址不好记的痛点,1985年,域名系统正式登场,将简单字符(即域名)和ip地址相关联,同样另一个系统也随之产生,也就是DNS系统,负责ip地址和域名查找工作,也就是,当你在浏览器输入一个域名之后,DNS将负责把这个域名转换成ip地址然后进行访问,所以出现一个网站在一个地方和另一个地方访问内容的微小不同也是正常的,这是DNS为加速访问设置缓存而导致的。

接下来我们谈谈为何有时候网站会打不开,首先响应时间太长了,有两个可能原因,一:端口号配置错误,二:被防火墙拦截,谈谈第二个的解决方案,采用代理绕过防火墙即可。读完这些我相信读者应该有自己对于某些可能出现问题的自我排解能力了,那么接下来就开始我们的搭建网站之旅吧。

三、准备工作

让自己以更加轻松愉快的方式访问自己的网站。务必申请属于自己的域名哦。

1.github注册

what?你居然没有github账号,建议你放弃网站部署(开玩笑)。作为全球最大的代码托管平台,基本上每个稍微接触过开发的应该都用过,如果你还没注册的话,赶紧注册一个,没听过github太丢人了,注册也很简单(有手就行)。

点击进入github官网,这里需要注意一点,如果是国内访问的话,移动是可以的,其他运营商貌似有屏蔽,如果访问不了,自行百度解决。

2.申请属于自己的域名

以自己独特的字符进行访问,建议注册com域名和在国外注册,保证可以直接使用域名进行访问网站,国内注册商由于政策的原因,只提供云服务给备案的域名。

这里推荐去国外的Godaddy平台注册一个域名

关于如何选一个比较好的域名可以看看我的这篇我的域名注册踩坑指南

3.申请注册vercel平台

如果你没有服务器,这是个不错的选择,不过需要注意的是,*vercel.app这个域名被防火墙拦截了,所以要访问的话需要使用自己的域名。

vercel平台是一个可以免费托管个人网站的自动化部署平台,只要你的代码托管平台(类似github,gitlab,gitee等)commit发生变化,它就会自动更新和重新部署,解放生产力。

点击vercel官网sign up注册一个账号,当然也可以选择github直接登录,会更方便一点,可以直接导入自己的仓库,包括私有仓库。

4.下载node和yarn

node是vuepress运行的依赖模块,就像c和java中的编译器和jvm的存在,没有它整个项目不能编译打包。

yarn是一个包管理器,可以下载或者更新你所需要的相关包,便于项目的正常运行,值得注意的是这个并不是必须的,node安装后自带另外一个npm包管理器,功能是类似的,所以这是个可选项.

node

进入node的官网,选择LTS即长期稳定版本下载。会得到一个msi后缀的文件,即开箱即用的版本,不用自己手动配置环境变量啥的,会配置好的,注意安装位置改一下就行,放在除c盘外的盘即可,其他就一步步点击确认即可,最后cmd中输入node有welcome提示即为成功,不成功按照相应提示浏览器搜索即可。

yarn

这个是个包管理工具,和npm差不多,听说更快一点,这里安装是由于主题更新采用的是这个命令,所以这里安装一下。

yarn官网,如果不想配置环境变量的话,还是可以采用msi后缀安装。

5.图床配置

使用url引用图片可以帮助你在任何平台上都可以很方便的插入图片,无需担心本地文件的丢失.

CDN COS配置图床

有了图床,你就可以随时随地采用URL引用你的图片,非常方便,可以参考我写的这篇搭建博客CDN COS搭建图床超详细步骤,有个缺点就是需要备案才能使用自定义域名和CDN服务,不过如果想要白嫖的话,搜索国外的图床也是可以的,国内也有一些提供图床配置的,使用它们的域名上传图片也可以。这里采用的是pic-go图床管理工具,强烈安利,真的太方便了。

路径引用

如果你没有自己的图床也没关系,主题博客还提供本地引用的功能,不过这个更改图片的时候比较麻烦,虽然有时候它可能更快一点点。

6.开发IDE下载

我是用习惯了idea,所以这里推荐idea进行开发,安装node.js插件,然后就可以本地开发了,没有的话安装一下即可。

idea官网

安装node.js插件

至此,准备工作已经完成,接下来就进入今天的主题。

四、本地开发

1.github fork项目

Vdoing主题项目地址,这里建议fork整个仓库,然后自己做一些修改即可,作者大大真的太强了。

2.基础网站配置
主页配置

打开以下目录的index.md,你可能会问咋是md格式的,不应该是html格式的吗?别着急,这个是开发中的,打包之后是index.html

以下字段对应相关的图,可以自行体会一下,对应导航栏下面的几个字段,其中涉及使用URL引入的,可以替换成路径引用,具体字段帮助请自行查看fork过来的仓库介绍,也可以到Vdoing官方文档查阅.

代码语言:markdown复制
home: true
heroImage: https://img.de7v.com/img/new_logo_2.png
# heroImage:/img/web.png
# 这个路径在public下的img目录中
heroText: IT七剑客
tagline: ?互联网中的持剑者
actionText: 立刻进入 →
actionLink: /wresource/
bannerBg: none

通过路径引用的图片目录,把你想要的图片全放进去然后就可以引用了。

config.ts配置

进入config.ts界面

首先我们先找到head位置进行配置,打开网站的小图标,同样也可以使用URL或者本地引用

找到location开头的这段代码,网站的标题和描述写一下,这个会在百度搜索的快照中展示。

代码语言:javascript复制
locales: {
    '/': {//代表baseurl,即网站所有的引用的根路径,默认是没有的,如果文件夹有需要可以修改
        lang: 'zh-CN',
        title: "IT七剑客",
        description: '互联网中的持剑者,七剑客带你斩断一切bug',
    }
},

下面这些代码主要是配置导航栏和其他全局功能,其中logo是最左侧显示的图片,repro是自己的github名,用于直接跳转github主页,其他的取默认即可。

代码语言:markdown复制
sidebarDepth: 2, // 侧边栏显示深度,默认1,最大2(显示到h3标题)
logo: 'https://img.de7v.com/img/new_logo_2.png', // 导航栏logo
repo: 'xyh-fu', // 导航栏右侧生成Github链接
searchMaxSuggestions: 10, // 搜索结果显示最大数
lastUpdated: '上次更新', // 开启更新时间,并配置前缀文字   string | boolean (取值为git提交时间)
docsDir: 'docs', // 编辑的文件夹
// docsBranch: 'master', // 编辑的文件所在分支,默认master。 注意:如果你的分支是main则修改为main
editLinks: true, // 启用编辑
editLinkText: '编辑',

博主信息页面,在侧边栏,可以配置一些基础信息

代码语言:javascript复制
 blogger:{ // 博主信息,显示在首页侧边栏
      avatar: 'https://img.de7v.com/img/new_logo_2.png',
      name: 'IT七剑客',
      slogan: '欢迎投稿加入IT七剑客'
}

最后再说明一下页脚的配置,这里用于配置全局页脚

代码语言:javascript复制
footer:{ // 页脚信息
    createYear: 2022, // 博客创建年份
        //博客版权信息,支持a标签
        copyrightInfo:'IT七剑客 | MIT License<li><img src="https://img.de7v.com/img/badge.png" style="zoom:30%;"><a href  = "https://beian.miit.gov.cn" target="_blank" >闽ICP备2021006579号-4</a></li><li><img src="https://img.de7v.com/img/badge.png" style="zoom:30%;">  <a target="_blank" rel="noopener" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=35012102500470">闽公网安备 35012102500470号</a></li>'
},

至此基本配置已经大功告成,接下来我们谈谈文章是怎么配置和主页路由的规则。

文章誊写和路由设置

首先配置目录页,这个是文章的导航界面,可以分别查看各个目录下的文章列表

代码语言:markdown复制
---
pageComponent: 
  name: Catalogue
  data: 
    path: 01.wresource  安卓
    imgUrl: https://img.de7v.com/img/wresource.png
    description:  Android,Kotlin,Jetpack等技术
title: wresource  安卓
date: 2020-03-11 21:50:53
permalink: /wresource
sidebar: false
article: false
comment: false
editLink: false
author:
  name: wresource
  link: https://github.com/xyh-fu
---

在这里设置目录的路由以及一些基础的配置,放图自行体会,这里需要注意一点,path要和docs下面的相应文章目录路径名一致,这里仅仅只是配置一下界面,真正的文章是放在docs下面的目录中。

关于文章誊写和命名规则具体查看作者的这篇文章关于目录和文章名称约定(这里偷懒一波)。

接下来再次回到之前得index.md中,可以配置主界面相关信息了

代码语言:javascript复制
features: # 可选的
  - title: wresource  安卓
    details: Android,Kotlin,Jetpack等技术
    link: /wresource/ # 可选
    imgUrl: https://img.de7v.com/img/wresource.png # 可选

配置效果如下图所示

回到config.ts界面,我们来搭建一下导航栏,在themeConfig中的nav字段

代码语言:javascript复制
nav: [
          {
              text: '首页',
              link: '/'
          },
          {
            text: 'wresource',
            link: '/wresource/', //目录页链接,此处link是vdoing主题新增的配置项,有二级导航时,可以点击一级导航跳到目录页
          },
          {
            text: '郭霖',
            link: '/guolin/',
          },
          {
            text: '孤寒者',
            link: '/guhanzhe/',
          },
          {
            text: 'IT邦德',
            link: '/jeames007/',
          },
          {
            text: '沉默王二',
            link: '/wang_er/'
          },
        ],

搭建好是这个效果,当然更多效果请参考fork过来中仓库的注释,个人比较喜欢简洁一点的导航栏

3.插件配置

这部分就属于网站的内部配置了,与外观没有多大关系,如果觉得可以了,就不用配置了

站点信息页面

主要用于统计网站相关信息的功能同时也增加文章字数统计以及阅读量统计等等,这个配置参考kbt大大的博客,这里提醒一下readfile文件在博客中失效,建议去kbt大大的github项目主页获取最新的代码。站点信息搭建

这里给出当时踩坑的那个readfile文件代码,如果有不同,以作者的为主。

代码语言:javascript复制
import fs from 'fs'; // 文件模块
import path from 'path'; // 路径模块
import matter from 'gray-matter'; // FrontMatter解析器 https://github.com/jonschlinkert/gray-matter
import chalk from 'chalk' // 命令行打印美化
const log = console.log
const docsRoot = path.join(__dirname, '..', '..', '..', 'docs'); // docs文件路径

/**
 * 获取本站的文章数据
 * 获取所有的 md 文档,可以排除指定目录下的文档
 */
function readFileList(excludeFiles: Array<string> = [''], dir: string = docsRoot, filesList: Array<Object> = []) {
  const files = fs.readdirSync(dir);
  files.forEach((item, index) => {
    let filePath = path.join(dir, item);
    const stat = fs.statSync(filePath);
    if (!(excludeFiles instanceof Array)) {
      log(chalk.yellow(`error: 传入的参数不是一个数组。`))
    }
    excludeFiles.forEach((excludeFile) => {
      if (stat.isDirectory() && item !== '.vuepress' && item !== '@pages' && item !== excludeFile) {
        readFileList(excludeFiles, path.join(dir, item), filesList);  //递归读取文件
      } else {
        if (path.basename(dir) !== 'docs') { // 过滤 docs目录级下的文件

          const fileNameArr = path.basename(filePath).split('.')
          let name = null, type = null;
          if (fileNameArr.length === 2) { // 没有序号的文件
            name = fileNameArr[0]
            type = fileNameArr[1]
          } else if (fileNameArr.length === 3) { // 有序号的文件
            name = fileNameArr[1]
            type = fileNameArr[2]
          } else { // 超过两个‘.’的
            log(chalk.yellow(`warning: 该文件 "${filePath}" 没有按照约定命名,将忽略生成相应数据。`))
            return
          }
          if (type === 'md') { // 过滤非 md 文件
            filesList.push({
              name,
              filePath
            });
          }
        }
      }
    });
  });
  return filesList;
}
/**
 * 获取本站的文章总字数
 * 可以排除某个目录下的 md 文档字数
 */
function readTotalFileWords(excludeFiles = ['']) {
  const filesList = readFileList(excludeFiles);
  let wordCount = 0;
  filesList.forEach((item: any) => {
    const content = getContent(item.filePath);
    let len = counter(content);
    wordCount  = len[0]   len[1];
  });
  if (wordCount < 1000) {
    return wordCount;
  }
  return Math.round(wordCount / 100) / 10   'k';
}
/**
 * 获取每一个文章的字数
 * 可以排除某个目录下的 md 文档字数
 */
function readEachFileWords(excludeFiles: Array<string> = [''], cn: number, en: number) {
  const filesListWords = [];
  const filesList = readFileList(excludeFiles);
  filesList.forEach((item: any) => {
    const content = getContent(item.filePath);
    let len = counter(content);
    // 计算预计的阅读时间
    let readingTime = readTime(len, cn, en);
    let wordsCount: any = 0;
    wordsCount = len[0]   len[1];
    if (wordsCount >= 1000) {
      wordsCount = Math.round(wordsCount / 100) / 10   'k';
    }
    // fileMatterObj => {content:'剔除frontmatter后的文件内容字符串', data:{<frontmatter对象>}, ...}
    const fileMatterObj = matter(content, {});
    const matterData = fileMatterObj.data;
    filesListWords.push({ ...item, wordsCount, readingTime, ...matterData });
  });
  return filesListWords;
}

/**
 * 计算预计的阅读时间
 */
function readTime(len: Array<number>, cn: number = 300, en: number = 160) {
  let readingTime = len[0] / cn   len[1] / en;
  if (readingTime > 60 && readingTime < 60 * 24) {   // 大于一个小时,小于一天
    let hour = Math.trunc(readingTime / 60);
    let minute = Math.trunc(readingTime - hour * 60);
    if (minute === 0) {
      return hour   'h';
    }
    return hour   'h'   minute   'm';
  } else if (readingTime > 60 * 24) {      // 大于一天
    let day = Math.trunc(readingTime / (60 * 24));
    let hour = Math.trunc((readingTime - day * 24 * 60) / 60);
    if (hour === 0) {
      return day   'd';
    }
    return day   'd'   hour   'h';
  }
  return readingTime < 1 ? '1' : Math.trunc(readingTime * 10) / 10   'm';   // 取一位小数
}

/**
 * 读取文件内容
 */
function getContent(filePath: string) {
  return fs.readFileSync(filePath, 'utf8');
}
/**
 * 获取文件内容的字数
 * cn:中文
 * en:一整句英文(没有空格隔开的英文为 1 个)
 */
function counter(content: string) {
  const cn = (content.match(/[u4E00-u9FA5]/g) || []).length;
  const en = (content.replace(/[u4E00-u9FA5]/g, '').match(/[a-zA-Z0-9_u0392-u03c9u0400-u04FF] |[u4E00-u9FFFu3400-u4dbfuf900-ufaffu3040-u309fuac00-ud7afu0400-u04FF] |[u00E4u00C4u00E5u00C5u00F6u00D6] |w /g) || []).length;
  return [cn, en];
}

export {
  readFileList,
  readTotalFileWords,
  readEachFileWords,
}

下面给出效果图

这里有一点比较坑,就是当时这个模块默认挂载到热门标签下面,然而我没有设置标签。最后给挂在了页面底部。请务必仔细阅读作者的博客。

广告配置

首先在config.ts的head中引入下列代码,这里是谷歌广告配置。

代码语言:javascript复制
[
    'script',
    {
        'data-ad-client': '自己的广告id',
        async: 'async',
        src: 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js',
    },
], // 网站关联Google AdSense 与 html格式广告支持(你可以去掉)

然后在themeConfig中添加下列字段

在下列目录中完成html广告的配置

我的配置,在全局右下角添加广告。

代码语言:javascript复制
windowRB:
      ` <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
        <ins class="adsbygoogle"
            style="display:inline-block;
            width:200px;
            height:200px"
            data-ad-client="ca-pub-广告id"
            data-ad-slot="用户名"></ins>
        <script>
            (adsbygoogle = window.adsbygoogle || []).push({});
        </script>`,
百度统计

这部分比较简单,在head中加入以下字段即可(谁说比较简单的,这个我鼓捣了一周,插件用不了,不知道是啥原因,最后采用这个比较简单的方法配置),至于百度统计码,百度一下百度统计即可。它最重要的作用就是分析网站的来访数量以及搜索量等等,站长必备工具之一。

代码语言:javascript复制
[
    'script',
    { 
        src: 'https://hm.baidu.com/hm.js?百度统计码',
    },
],
评论配置

这个是最近配置成功的,踩了好多坑,也是参考kbt大大的博客,我用的也是twikoo评论,之前使用gittalk的,后面发现国内根本不能访问,所以换成了目前这个评论系统。kbt大大写的搭建评论的博客,说明几个坑。

  • 部署时注意是部署云函数,不是该评论系统项目,被这个坑了好久好久。

点击自动部署会自动进入dev分支下的vercel配置,不是整个仓库

  • 关于mongo db,感觉应该是香港节点会更快一点,不知道为啥会推荐us节点
  • 关于环境id

这里应该是最近vercel的默认域名被禁的缘故,vercel.app之类的域名国内均不能访问,所以在部署环境id时需要添加自己的域名进行部署,类似xx.de7v.com。

  • 关于管理员的评论管理

最开始是使用代理才可以进行配置的,之前都失败了,这一步如果没有默认的密码账号输入的话,建议开代理。

五、站点部署

1.COS CDN部署

温馨提示,这部分部署需要国内备案域名,如果没有备案域名,请使用其他两种方式部署。

首先先运行vuepress项目,进入项目路径,终端输入以下命令进行构建项目

代码语言:javascript复制
npm run build

生成静态文件成功之后可以在dist文件夹找到打包好的静态文件

先创建一个存储桶
上传文件

直接将文件复制一下拖拽到cos的以下界面,注意是dist里面的文件,不要传dist整个文件夹,反正最后是存储桶中有如下的内容,即dist里面的文件。

开启静态网站设置

此时还访问不了,如果想直接访问的话,权限管理改成公共读就可以访问了,使用访问节点的url即可,不过我们要介绍使用cdn进行访问,更快。

cdn配置访问

利用cdn进行私有读写,cdn提供给外部访问,配置相关可以查看这篇博客里面的配置,几乎是一样的,不多赘述。CDN COS搭建图床超详细步骤,最后记得开启https访问。

至此我们已经完成了cos cdn部署静态网站。下面是部署成功的站点,访问速度还可以。

2.vercel部署

vercel部署可以说是最简单的部署,还带自动化部署的功能,强烈推荐,目前主站是部署在vercel上的。

进入主界面,选择添加新项目:Add New,选择Project

之后就是选择导入github中的项目,私有仓库也可以,gitpage中这个功能貌似收费,只能public。

配置运行参数,这部分是当初最坑的那个,当时不知道输出填啥,一直构建失败

先选择vue.js构建

接下来就是build和Output settings,按照以下设置即可

其中output directory是很坑,之前不知道这个是输出文件,一直部署dev模式的网站,速度感人。

点击deploy即部署的意思

接下来就是稍微有点长的构建时间,大概10分钟吧,主要是Vdoing作者的文章比较多,构建需要花一定时间。

部署完毕是这样的,不过目前有个小尴尬的事情,自动提供的这几个域名国内访问不了,所以只能自己添加域名了。

在domains中添加自己的域名

先添加,然后根据提示进行添加dns解析

按照提示添加完解析即可

添加完会自动帮你添加ssl证书

大功告成

至此部署已经完成,之后只需要远程提交自己的修改到github上面即可完成修改界面。

3.宝塔部署

不说了,这个是几个中最简单的,先打包,然后上传到网站上,之后直接访问即可。

打包
创建静态网站

记得填入自己的域名并添加dns解析

将里面的文件删去,最后一个.user.ini没删除问题不大,最主要是为了防止冲突

上传完解压一下就行

将解压后的文件复制到网站最开始的目录下,并删去原来的dist和dist.rar文件

最后申请一下免费的证书和开启强制https就结束了(声明,没有hhh.com域名,只是随便输一个)

浏览器键入自己的域名就可以访问了,我的宝塔部署的站点IT七剑客,挺快的,比之前dev模式好多了

六、常用命令

安装node依赖

自动安装缺少的依赖

代码语言:txt复制
npm install

项目调试

在测试功能时使用,该模式下,所有改动均可以快速看到效果,无需重新构建

代码语言:txt复制
npm run dev

项目打包

用于生成环境的打包,项目成功之后可以打包,然后部署到各个地方

代码语言:javascript复制
npm run build

七、写在最后

这次网站的部署大概经历了前前后后一个月,都是凌晨肝一会,书读的少,做事就非常费劲。希望大家能够通过我的这篇文章少走弯路,那这篇文章就是有价值的,有问题评论区留言。

0 人点赞