个人博客制作简介
个人博客制作简介
一、写在前面
很久之前自己就做了个人博客了,但是种种原因,没有把自己的制作过程整理记录下来,时间长了重装系统,这些步骤都比较生疏了,导致再想重新捡起有点困难,不过还是尽量回忆整理一下,以便之后参考。
二、准备工作
2.1 安装git
首先下载安装git,然后配置相关信息,和自己的github连接到一起。这是因为我们的个人博客为了节省成本,其实是嵌套到github上面运行的,言外之意,github才是我们的服务器,博客的模式是B/S模式访问。
git config --global user.name "name"
git config --global user.email "email"
创建ssh连接:
ssh-keygen -t rsa -C "email"
设置生成公钥私钥之后,将公钥复制出来,放到github的秘钥库内,完成连接。
ssh -T git@github.com #测试是否能正常连接
2.2 安装nodejs
其次,安装nodejs,安装完成之后用于下载相关插件。
2.3 安装hexo
然后使用npm安装hexo。注意此时使用npm安装插件可能出现问题,比如“rollbackFailedOptional: verb npm-session”,这样的原因是国外的源不稳定或者其他原因,此时可以换用淘宝的源。
1、更改npm源
npm config set registry https://registry.npm.taobao.org
#恢复:npm config set registry http://registry.npmjs.org
– 配置后可通过下面方式来验证是否成功
npm config get registry或npm info express
2、使用cnpm
先删除原有的所有代理
npm config rm proxy
npm config rm https-proxy
然后安装淘宝的cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
然后安装hexo:
npm install -g hexo-cli
测试是否安装成功:
hexo -v
三、创建博客
首先明确hexo常用的命令,这是具体文档:
1、hexo init hexo init 命令用于初始化本地文件夹为网站的根目录 $ hexo init [folder] folder 可选参数,用以指定初始化目录的路径,若无指定则默认为当前目录 2、hexo new hexo new 命令用于新建文章,一般可以简写为 hexo n $ hexo new [layout] <title> layout 可选参数,用以指定文章类型,若无指定则默认由配置文件中的default_layout 选项决定 title 必填参数,用以指定文章标题,如果参数值中含有空格,则需要使用双引号包围 3、hexo generate hexo generate 命令用于生成静态文件,一般可以简写为 hexo g $ hexo generate -d 选项,指定生成后部署,与 hexo d -g 等价 4、hexo server hexo server 命令用于启动本地服务器,一般可以简写为 hexo s $ hexo server -p 选项,指定服务器端口,默认为 4000 -i 选项,指定服务器 IP 地址,默认为 0.0.0.0 -s 选项,静态模式 ,仅提供 public 文件夹中的文件并禁用文件监视 说明:运行服务器前需要安装 hexo-server 插件 $ npm install hexo-server --save 5、hexo deploy hexo deploy 命令用于部署网站,一般可以简写为 hexo d -g 选项,指定生成后部署,与 hexo g -d 等价 6、hexo clean hexo clean 命令用于清理缓存文件,是一个比较常用的命令 网站显示异常时可尝试此操作 7、Option (1)hexo --safe hexo --safe 表示安全模式,用于禁用加载插件和脚本 (2)hexo --debug hexo --debug 表示调试模式,用于将消息详细记录到终端和 debug.log 文件 (3)hexo --silent hexo --silent 表示静默模式,用于静默输出到终端
其次,在磁盘中新建文件夹用来存放博客文件,然后使用命令初始化:
hexo init 博客名(最好英文)
此时会在该文件夹下创建这样名称的博客,并且生成一些附属文件。
创建完之后需要进入该文件夹,使用npm install初始化博客。
cd 博客名
npm install
然后运行如下命令运行本地系统:
hexo g
hexo server
至此在本地搭建网站成功,但是真正的网站需要在远程进行访问,因此,需要借助github进行部署。
四、部署到github产生的问题
这里需要借助github中一项便利的功能github page。在GitHub.com中New repository,新建仓库,创建和自身用户名相同的仓库,后面加.github.io,这种格式会被github识别,定位到具体的网址,即xxxx.github.io,xxx为GitHub用户名。
接下来就可以将自己本地的网站部署到github上了,只需要修改网站中的_config.yml文件,将deploy属性绑定到github上面。
设置完之后安装deploy-git,进行部署。
npm install hexo-deployer-git --save
最后将网站上传部署到github。
hexo clean #清除了之前生成的东西,也可以不加。
hexo generate #生成静态文章,可以用 hexo g缩写
hexo deploy #部署文章,可以用hexo d缩写
五、解决部署问题(更换电脑)
通过上述操作就可以访问网站了,但是如果更换了电脑,使用git clone命令,将github page中的网站文件下载过来。
可以发现,这样有一个很严重的问题,那就是在上传的过程中,使用hexo d命令,git仅仅上传的是根据源文件生成的网页文件,对于之前设置的一些md等源文件等都没有上传,我们下载下来也不能进行修改,并且不能编辑新的内容,此时这里有两种解决办法,第一种是所有的源文件打包,在新电脑上解压部署环境执行,但是比较麻烦,并且导致文件可能不同步,第二种是将源文件上传到github中保存,这里也有两种方式,(1)创建一个仓库进行存储,(2)在github page仓库中新建分支hexo,专门用来存储源文件,显然第二种方式更方便快捷,因此,我们需要在创建github page中作如下操作,再新建一个分支hexo,此时有两个分支:master和hexo,然后将hexo设为主分支,在git中切换到hexo分支提交所有文件,并且在hexo分支下使用hexo d完成部署,因为hexo d会查找部署的分支,这里在配置文件中将分支设置为master即可。
简单的说就是把Hexo环境push到hexo分支:
1. 创建仓库,http://xxx.github.io;
2. 创建两个分支:master 与 hexo;
3. 在github上设置hexo为默认分支(因为只需要手动管理这个分支上的Hexo网站文件);
4. 使用git clone git@github.com:xxx/xxx.github.io.git拷贝仓库;此时会拷贝出来hexo主分支的内容,当然也有master的内容,不过hexo直接显示。
5. 如果是新电脑,则在本地文件夹hexo分支下,通过Git bash依次执行npm install hexo、hexo init、npm install 和 npm install hexo-deployer-git,
此时hexo环境已经部署完毕并且初始化完成;如果已经部署过hexo环境,则使用npm install 和 npm install hexo-deployer-git进行初始化;
6. 修改hexo文件夹下的_config.yml中的deploy参数,分支改为master;这个时候使用hexo d命令,则读取该文件,找到master分支进行push;
7. 在hexo分支下,依次执行git add .、git commit -m "..."、git push origin hexo提交网站相关的文件;
8. 在hexo分支下,执行hexo g -d生成网站并部署到GitHub上,此时网站静态内容会被push到master分支;
真正正确的具体步骤如下:
新建仓库,默认创建了master分支,再创建hexo分支,并且设置hexo分支为默认分支:
此时这两个分支都为空,然后下载该仓库:
git clone git@github.com:xxx/xxx.github.io.git
进入xxx.github.io中(此时因为hexo为默认分支,所以默认就在hexo分支下),删除除了.git之外所有文件,一般没有其他文件。然后将我们的博客源文件的某些必要文件复制到xxx.github.io文件夹下,具体有如下文件。
在这里,.gitignore文件非常重要,需要屏蔽一些不需要上传到github上的文件,这些文件如下:
1 .DS_Store 2 Thumbs.db 3 db.json 4 *.log 5 node_modules/ 6 public/ 7 .deploy*/
到了这一步,有两种方法,第一种是初始化hexo分支下的文件,生成必需的目录,第二种是直接将hexo分支的内容push到远程仓库,这两种方式都一样,因为.gitignore文件会屏蔽生成的文件,言外之意这两种方式上传的内容一致,对于package-lock.json其实也可以自动生成。
初始化方法(在hexo分支下):
npm install
npm install hexo-deployer-git --save
无论哪一种方式都要防止嵌套克隆,因为theme中的主题可能是从网上git clone下来的,这样就会造成嵌套,导致上传很麻烦,即使上传成功,也会有安全风险,因此如果之前克隆过theme中的主题文件,那么应该把主题文件中的.git文件夹删掉,显示隐藏文件检查是否存在。
到了这一步就可以真正上传了,在hexo分支下执行如下命令,将会上传到github的hexo分支,但是master分支依旧为空:
git add .
git commit -m "..."
git push origin hexo
然后在hexo分支下将静态文件部署到master分支下:
在hexo分支下:
hexo clean
hexo g -d
至此这两个分支具有不同的内容,并且可以灵活适配。以后每次编辑文件上传都需要执行上面的操作(提交源文件到hexo分支,提交网页到master分支),这样即可完美解决文件同步问题,此后更换电脑,只需要git clone下来,部署相应的环境,然后切换到hexo分支下编辑撰写新文档,提交文件即可。
git clone git@github.com:xxx.github.io.git #下载
cd xxx.github.io
#以下操作均在hexo分支下完成:
#初始化环境 npm install hexo npm install npm install hexo-deployer-git --save
#上传到hexo分支
git add . git commit -m "..." git push origin hexo
#上传到master分支
hexo clean hexo g -d
注意:在提交的时候出现“warning: LF will be replaced by CRLF in”,原因是需要提交的文件是在windows下生成的,windows中的换行符为 CRLF, 而在linux下的换行符为LF,所以在执行add . 时出现提示,解决办法:
git config --global core.autocrlf false
五、域名注册
注册域名有很多渠道,比如阿里云、腾讯云、华为云等,这里使用阿里云作为演示。在博客以github作为服务器之后,访问的时候需要输入xxx.github.io来登录,看起来不是很美观,因此可以通过注册域名来屏蔽这一信息,通过设置cname即可,在域名解析中将github和自己注册的域名绑定。同时需要在github page中创建CNAME文件,在该文件中写入自己申请的域名。
六、yilia主题设置
- 安装和配置
博客需要好的主题,当然有默认的主题,不过可能不是很美观,本文使用yilia主题。安装只需要输入从git中克隆下来放到themes文件夹下即可。然后修改hexo根目录下的 _config.yml :theme: yilia,最后git pull更新即可。
git clone https://github.com/litten/hexo-theme-yilia.git themes/yilia
在yilia文件夹下面的_config.xml比较重要,是该主题的核心配置。
1 # Header 2 3 menu: 4 主页: / 5 # 所有文章: /allPages 6 # 随笔: /tags 7 # 相册: /photos 8 9 # SubNav 10 subnav: 11 github: "https://github.com/zyrWork" 12 weibo: "https://weibo.com/zyrlovelsx" 13 #rss: /atom.xml 14 zhihu: "https://www.zhihu.com/people/zyrlovelsx" 15 rss: "https://www.cnblogs.com/zyrblog/" 16 qq: "https://user.qzone.qq.com/" 17 weixin: "https://wx.qq.com/" 18 #jianshu: "#" 19 #douban: "#" 20 #segmentfault: "#" 21 bilibili: "https://space.bilibili.com/278563689/" 22 #acfun: "#" 23 mail: "mailto:2655100813@qq.com" 24 #facebook: "#" 25 #google: "#" 26 #twitter: "#" 27 #linkedin: "#" 28 29 30 31 # 是否需要修改 root 路径 32 # 如果您的网站存放在子目录中,例如 http://yoursite.com/blog, 33 # 请将您的 url 设为 http://yoursite.com/blog 并把 root 设为 /blog/。 34 root: 35 36 # Content 37 38 # 文章太长,截断按钮文字 39 excerpt_link: 阅读全文 40 # 文章卡片右下角常驻链接,不需要请设置为false 41 show_all_link: '展开全文' 42 # 数学公式 43 mathjax: true 44 # 是否在新窗口打开链接 45 open_in_new: true 46 fancybox: true 47 #是否开启动画效果 48 animate: true 49 50 # 打赏 51 # 打赏type设定:0-关闭打赏; 1-文章对应的md文件里有reward:true属性,才有打赏; 2-所有文章均有打赏 52 reward_type: 2 53 # 打赏wording 54 reward_wording: '谢谢你请我吃糖果' 55 # 支付宝二维码图片地址,跟你设置头像的方式一样。比如:/assets/img/alipay.jpg 56 alipay: /assets/img/alipay.jpg 57 # 微信二维码图片地址 58 weixin: /assets/img/weixin.png 59 60 # 目录 61 # 目录设定:0-不显示目录; 1-文章对应的md文件里有toc:true属性,才有目录; 2-所有文章均显示目录 62 toc: 2 63 # 根据自己的习惯来设置,如果你的目录标题习惯有标号,置为true即可隐藏hexo重复的序号;否则置为false 64 toc_hide_index: true 65 # 目录为空时的提示 66 toc_empty_wording: '目录,不存在的…' 67 68 # 是否有快速回到顶部的按钮 69 top: true 70 71 # Miscellaneous 72 baidu_analytics: '' 73 google_analytics: '' 74 favicon: /assets/img/favicon.jpg 75 76 #你的头像url 77 avatar: /assets/img/avatar.jpg 78 79 #是否开启分享 80 share_jia: true 81 share_addthis: false 82 83 #评论:1、多说;2、网易云跟帖;3、畅言;4、Disqus 不需要使用某项,直接设置值为false,或注释掉 84 #具体请参考wiki:https://github.com/litten/hexo-theme-yilia/wiki/ 85 86 #1、多说 87 duoshuo: true 88 89 #2、网易云跟帖 90 wangyiyun: true 91 92 #3、畅言 93 changyan_appid: true 94 changyan_conf: true 95 96 #4、Disqus 在hexo根目录的config里也有disqus_shortname字段,优先使用yilia的 97 disqus: false 98 99 # 样式定制 - 一般不需要修改,除非有很强的定制欲望… 100 style: 101 # 头像上面的背景颜色 102 header: '#ff6434' 103 # 右滑板块背景 104 slider: 'linear-gradient(200deg,#a0cfe4,#e7c37e)' 105 106 # slider的设置 107 slider: 108 # 是否默认展开tags板块 109 showTags: false 110 111 # 智能菜单 112 # 如不需要,将该对应项置为false 113 # 比如 114 #smart_menu: 115 # friends: false 116 smart_menu: 117 innerArchive: '所有文章' 118 friends: '友链' 119 aboutme: '关于我' 120 121 friends: 122 百度一下: http://www.baidu.com 123 我的博客: https://www.cnblogs.com/zyrblog/ 124 CSDN: https://me.csdn.net/zyr940716 125 关于算法: https://unclegem.cn/ 126 框架作者: http://litten.me/ 127 Java技术栈1: https://ruider.github.io/ 128 Java技术栈2: http://huzb.me/ 129 Java技术栈3: http://www.tianxiaobo.com/ 130 131 132 aboutme: 寻梦者<br><br>努力学习,青春不负<br>提升自我!
其中图片来源于根目录:
- 不蒜子统计
通过不蒜子可以统计访问量。
不蒜子可以给任何类型的个人站点使用,对于hexo,打开themes/主题/layout/_partial/footer.ejs添加上述脚本即可,当然也可以添加到 header 中。
<!--统计start--> <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script> <span id="busuanzi_container_site_pv">本站总访问量<span id="busuanzi_value_site_pv"></span>次</span> <span id="busuanzi_container_site_uv">总访客数<span id="busuanzi_value_site_uv"></span>人次</span> <!--统计end-->
- 统计时间
<div class="footer-right"> <span id="timeDate">载入天数...</span><span id="times">载入时分秒...</span> <script> var now = new Date(); function createtime() { var grt= new Date("5/1/2019 12:00:00");//此处修改你的建站时间或者网站上线时间 now.setTime(now.getTime()+250); days = (now - grt ) / 1000 / 60 / 60 / 24; dnum = Math.floor(days); hours = (now - grt ) / 1000 / 60 / 60 - (24 * dnum); hnum = Math.floor(hours); if(String(hnum).length ==1 ){hnum = "0" + hnum;} minutes = (now - grt ) / 1000 /60 - (24 * 60 * dnum) - (60 * hnum); mnum = Math.floor(minutes); if(String(mnum).length ==1 ){mnum = "0" + mnum;} seconds = (now - grt ) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum); snum = Math.round(seconds); if(String(snum).length ==1 ){snum = "0" + snum;} document.getElementById("timeDate").innerHTML = "本站已安全运行 "+dnum+" 天 "; document.getElementById("times").innerHTML = hnum + " 小时 " + mnum + " 分 " + snum + " 秒"; } setInterval("createtime()",250); </script> </div>
于是footer.ejs如下:
<footer id="footer"> <div class="outer"> <div id="footer-info"> <div class="footer-left"> © <%= date(new Date(), 'YYYY') %> <%= config.author || config.title %> </div> <!--统计start--> <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script> <span id="busuanzi_container_site_pv">本站总访问量<span id="busuanzi_value_site_pv"></span>次</span> <span id="busuanzi_container_site_uv">总访客数<span id="busuanzi_value_site_uv"></span>人次</span> <!--统计end--> <div class="footer-right"> <span id="timeDate">载入天数...</span><span id="times">载入时分秒...</span> <script> var now = new Date(); function createtime() { var grt= new Date("5/1/2019 12:00:00");//此处修改你的建站时间或者网站上线时间 now.setTime(now.getTime()+250); days = (now - grt ) / 1000 / 60 / 60 / 24; dnum = Math.floor(days); hours = (now - grt ) / 1000 / 60 / 60 - (24 * dnum); hnum = Math.floor(hours); if(String(hnum).length ==1 ){hnum = "0" + hnum;} minutes = (now - grt ) / 1000 /60 - (24 * 60 * dnum) - (60 * hnum); mnum = Math.floor(minutes); if(String(mnum).length ==1 ){mnum = "0" + mnum;} seconds = (now - grt ) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum); snum = Math.round(seconds); if(String(snum).length ==1 ){snum = "0" + snum;} document.getElementById("timeDate").innerHTML = "本站已安全运行 "+dnum+" 天 "; document.getElementById("times").innerHTML = hnum + " 小时 " + mnum + " 分 " + snum + " 秒"; } setInterval("createtime()",250); </script> </div> </div> </div> </footer>
- article.ejs文件,设置字数统计、文章导航、微信支付宝打赏
<article id="<%= post.layout %>-<%= post.slug %>" class="article article-type-<%= post.layout %> <%if(index){%> article-index<%}%>" itemscope itemprop="blogPost"> <div class="article-inner"> <% if (post.link || post.title){ %> <header class="article-header"> <%- partial('post/title', {class_name: 'article-title'}) %> <% if (!post.noDate){ %> <%- partial('post/date', {class_name: 'archive-article-date', date_format: null}) %> <!-- 需要添加的位置--> <!-- 开始添加字数统计--> <% if(theme.word_count && !post.no_word_count){%> <%- partial('post/word') %> <% } %> <!-- 添加完成 --> <% } %> </header> <% } %> <!-- 目录内容 --> <% if (!index && post.toc){ %> <p class="show-toc-btn" id="show-toc-btn" onclick="showToc();" style="display:none"> <span class="btn-bg"></span> <span class="btn-text">文章导航</span> </p> <div id="toc-article" class="toc-article"> <span id="toc-close" class="toc-close" title="隐藏导航" onclick="showBtn();">×</span> <strong class="toc-title">文章目录</strong> <%- toc(post.content) %> </div> <script type="text/javascript"> function showToc(){ var toc_article = document.getElementById("toc-article"); var show_toc_btn = document.getElementById("show-toc-btn"); toc_article.setAttribute("style","display:block"); show_toc_btn.setAttribute("style","display:none"); }; function showBtn(){ var toc_article = document.getElementById("toc-article"); var show_toc_btn = document.getElementById("show-toc-btn"); toc_article.setAttribute("style","display:none"); show_toc_btn.setAttribute("style","display:block"); }; </script> <% } %> <!-- 目录内容结束 --> <div class="article-entry" itemprop="articleBody"> <% if (post.excerpt && index){ %> <%- post.excerpt %> <% if (theme.excerpt_link) { %> <a class="article-more-a" href="<%- url_for(post.path) %>#more"><%= theme.excerpt_link %> >></a> <% } %> <% } else { %> <%- post.content %> <% } %> <% if ((theme.reward_type === 2 || (theme.reward_type === 1 && post.reward)) && !index){ %> <div class="page-reward"> <a href="javascript:;" class="page-reward-btn tooltip-top"> <div class="tooltip tooltip-east"> <span class="tooltip-item"> 赏 </span> <span class="tooltip-content"> <span class="tooltip-text"> <span class="tooltip-inner"> <p class="reward-p"><i class="icon icon-quo-left"></i><%= theme.reward_wording%><i class="icon icon-quo-right"></i></p> <div class="reward-box"> <% if(theme.alipay) {%> <div class="reward-box-item"> <img class="reward-img" src="<%= theme.alipay%>"> <span class="reward-type">支付宝</span> </div> <% } %> <% if(theme.weixin) {%> <div class="reward-box-item"> <img class="reward-img" src="<%= theme.weixin%>"> <span class="reward-type">微信</span> </div> <% } %> </div> </span> </span> </span> </div> </a> </div> <% } %> </div> <div class="article-info article-info-index"> <%if(post.top){%> <div class="article-pop-out tagcloud"> <i class="icon-tuding"></i> <a class="article-tag-list-link color3">置顶</a> </div> <% } %> <%- partial('post/tag') %> <%- partial('post/category') %> <% if (index && theme.show_all_link){ %> <p class="article-more-link"> <a class="article-more-a" href="<%- url_for(post.path) %>"><%= theme.show_all_link %> >></a> </p> <% } %> <% if (!index && theme.share_jia){ %> <%- partial('post/share') %> <% } %> <div class="clearfix"></div> </div> </div> </article> <% if (!index){ %> <%- partial('post/nav') %> <% } %> <%- partial('_partial/aside') %> <% if (!index && post.comments){ %> <% if (theme.duoshuo){ %> <%- partial('post/duoshuo', { key: post.slug, title: post.title, url: config.url+url_for(post.path) }) %> <% } %> <% if (theme.wangyiyun){ %> <%- partial('post/wangyiyun', { key: post.slug, title: post.title, url: config.url+url_for(post.path) }) %> <% } %> <% if (theme.changyan_appid && theme.changyan_conf){ %> <%- partial('post/changyan', { key: post.slug, title: post.title, url: config.url+url_for(post.path) }) %> <% } %> <% if (theme.disqus || config.disqus_shortname){ %> <section id="comments"> <div id="disqus_thread"></div> <script type="text/javascript"> /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */ var disqus_shortname = '<%= theme.disqus || config.disqus_shortname %>'; // required: replace example with your forum shortname /* * * DON'T EDIT BELOW THIS LINE * * */ (function() { var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js'; (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); })(); </script> <noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> </section> <% } %> <% if (theme.gitment_owner && theme.gitment_repo &&theme.gitment_oauth && theme.gitment_oauth.client_id && theme.gitment_oauth.client_secret){ %> <%- partial('post/gitment', { key: post.slug, title: post.title, url: config.url+url_for(post.path) }) %> <% } %> <% } %>
七、总结
上面只是简单地笔记,中间可能有一些问题,需要多查资料总结。