為什麼?
為什麼要實現自動部署?
在2個月的時間裡,一直都在忙著整理部落格,每一個程式設計師都有一個部落格夢(當然也不排除有些是沒有的),我先後使用過各種部落格系統:
這些都因為前前後後的原因,我沒有采用,而是自己寫了一個部落格系統:vue-blog-generater【請允許我再求一波star】點選這裡檢視說明文件
為什麼呢?因為我需要一個自己對其高度熟悉的系統,這樣有什麼問題,我都知道問題出在哪,因為之前的這些系統,當然很好,但是無論是主題的編輯,還是程式碼的部署以及自定義,這些都不能滿足我的要求。
話說回來,當我實現好了基礎功能和頁面之後,我開心了好一會兒,然後把一些還有意義的博文轉移過來,這就涉及到了釋出和部署。
我們都知道一個vue-cli
生成的專案,通常打包的目錄都是dist
,那麼我實際上需要掛載到伺服器上的程式碼就是這個dist
中的程式碼。
那按照常理,整個文章的更新流程應該是這樣:
- 新建檔案,編寫
markdown
博文 npm run build
編譯到dist
- 將
dist
的檔案上傳到對應的程式碼倉庫dist
- 將當前生成器的檔案同步上傳到對應程式碼倉庫
main
- 登入伺服器,
git clone dist倉庫
到指定的位置
看到了吧,只是更新一篇文章,卻需要這麼多步驟,是不是覺得很麻煩呢?麻煩就對了,在這裡我們就是來解決這個麻煩的。
如何做?
我明白了為什麼要做自動部署,但是我從哪下手呢?
做一件事情之前,我們要理清楚思路,有哪些步驟呢?其實非常簡單:
- 新建檔案,編寫
markdown
博文【這一步是跑不掉的】 npm run build
編譯到dist
,執行build.js
中判斷config.js
中是否配置了dist
的遠端倉庫地址。
如果配置了就對當前專案的dist
目錄,進行git
初始化,同時將整體程式碼上傳到Main倉庫
這裡預設不配置,Main
倉庫相當於本地倉庫關聯的遠端倉庫- 給本地
dist
目錄關聯遠端倉庫,並把程式碼推送到指定的dist
對應的遠端倉庫中。 - 伺服器進行配置,當接受到託管平臺傳送的
POST
請求時,做出對應的響應:拉取遠端dist
倉庫的master
分支並且強制覆蓋本地的master
分支
具體實現?
我們先來看看在第2,3個所說的內容怎麼實現。
- 準備工作:安裝需要的庫
shell
幫助我們在nodejs中執行命令chalk
豐富列印資訊
//安裝shell
yarn add shell --save
yarn add chalk --save
複製程式碼
- 我們在
build.js
中設計一個函式autoUpdate
,來幫助我們提交main
倉庫和我們的dist
倉庫的更新,我們先實現更新main
倉庫:請注意:這裡需要使用await確保程式碼的執行順序
const config = require('../config')
const shell = require('shelljs')
async function autoUpdate() {
console.log(chalk.cyan(
`Start to upload whole project to coding.net`
))
if (!shell.which('git')) {
//向命令列列印git命令不可用的提示資訊
shell.echo('Sorry, this script requires git');
//退出當前程式
shell.exit(1);
}
// 推送當前目錄[main 目錄]的程式碼
await shell.exec('git add .')
await shell.exec(`git commit -m '${config.commitMessage}'`).code
await shell.exec('git push origin master -f');
console.log(chalk.green(
`main dir-> succeed`
))
}
複製程式碼
- 在
@/config/index.js
中配置 dist遠端倉庫 相關的屬性的值
module.exports = {
...
distOriginSSh: 'git@github.com:xxx/xxx-blog-xxx.git',
...
}
複製程式碼
- 在
autoUpdate
中新增提交dist
倉庫的更新的程式碼:請注意:這裡需要使用await確保程式碼的執行順序
//進入到dist目錄下
await shell.cd('dist');
//執行 git init
await shell.exec(config.initLocal)
//刪除本地的dist已經對應的遠端倉庫
await shell.exec(config.deleteRemote)
//新增目標遠端倉庫到dist
await shell.exec(`git remote add origin '${config.distOriginSSh}'`)
//提交
await shell.exec('git add .')
let code = await shell.exec(`git commit -m '${config.commitMessage}'`).code
if (code !== 0) {
await shell.echo('Error: Git commit failed');
await shell.exit(code);
} else {
await shell.exec('git push origin master -f');
//chalk 這個庫是為了豐富列印資訊的
console.log(chalk.green(
`dist-> succeed`
))
}
複製程式碼
實現了本地上傳到遠端倉庫,那麼接下來我們需要去做幾件事,來實現步驟4:
這裡預設你已經在伺服器上完成了對dist程式碼的部署
- 在自己的伺服器上啟動一個服務,監聽
POST
的請求,如果確定這個請求是通知我們需要更新伺服器上對應dist
目錄對應的原始碼的話,執行對應的git
命令來更新。 - 配置遠端倉庫的
hooks
,在監聽到我們的push
請求時,就會自動POST
一個請求到我們配置的hooks
對應的地址中。這個地址也就是我們在伺服器上啟動的服務地址。
Okay,知道了要做什麼,那我們就開始吧。首先在伺服器上啟動一個node server
,我們新建一個server.js
,並且進入到編輯狀態
touch server.js
//如果你安裝了vim
vim server.js
//如果沒有安裝vim,可以用vi
vi server.js
//進入檔案後,我們可以按a健進入 insert狀態
複製程式碼
可以參考我的server.js
進行配置 請注意,需要你自己配置埠和路徑,我已經去除了我自己的配置
var http = require('http')
, exec = require('exec')
// 配製你的埠號
const PORT = XXX
, PATH = './xxx'
//PATH:你的dist目錄的路徑,相對於server.js所在的目錄而言。
var deployServer = http.createServer(function(request, response) {
if (request.url.search(/deploy\/?$/i) > 0) {
var commands = [
'cd ' + PATH,
'git fetch --all',
'git reset --hard origin/master',
'git pull'
].join(' && ')
exec(commands, function(err, out, code) {
if (err instanceof Error) {
response.writeHead(500)
response.end('Server Internal Error.')
throw err
}
process.stderr.write(err)
process.stdout.write(out)
response.writeHead(200)
response.end('Deploy Done.')
})
} else {
response.writeHead(404)
複製程式碼
編輯完成後,然後我們先按下esc
然後輸入:wq!
儲存檔案。然後node server.js
啟動一個服務。但是你又會發現,node server.js
這樣啟動的服務會在一段時間後自動停止,所以我們需要來用一個守護程式的工具來守護我們的服務,推薦大家使用forever
#安裝
npm install forever -g
#啟動
forever server.js
複製程式碼
還沒有結束,我們還需要在nginx
配置檔案中設定一個代理,將對應子域名代理到我們剛剛配置的埠上。這樣做的原因是因為我只有一個域名···
你可能會問什麼是子域名,比如我有一個一級域名dendoink.com
那麼我可以在解析的時候多新增一條新記錄xxx.dendoink.com
,這個就是子域名,他同樣可以訪問到我們域名對應的伺服器。
如果你使用的也是nginx來管理服務,那可以參考我下面的配置
server {
listen 80;
# 配置你的子域名
server_name xxx.你的域名.com;
#charset koi8-r;
access_log /var/log/nginx/githook.dendoink.com.access.log main;
# 這裡是重點
location / {
proxy_pass http://127.0.0.1:1024;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
複製程式碼
這樣配置好以後我們就可以通過外部訪問到我們定義好的服務啦。只需要把這個地址加入到對應的githook的配置中【具體的hook配置參考你的託管平臺教程】。
是不是很簡單呢?有任何問題可以掘金和我聯絡,或者郵件 dendise7en@gmail.com
另外求一波關注和star -> 看這裡,最美部落格系統~
另外求一波關注和star -> 看這裡,最美部落格系統~
另外求一波關注和star -> 看這裡,最美部落格系統~
特別宣告:題圖來源unsplash