個人博客制作簡介
一、寫在前面
很久之前自己就做了個人博客了,但是種種原因,沒有把自己的制作過程整理記錄下來,時間長了重裝系統,這些步驟都比較生疏了,導致再想重新撿起有點困難,不過還是盡量回憶整理一下,以便之后參考。
二、准備工作
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) }) %> <% } %> <% } %>
七、總結
上面只是簡單地筆記,中間可能有一些問題,需要多查資料總結。