1. 程式人生 > 前端設計 >從零構建一個伺服器環境中前端專案自動部署服務(上)

從零構建一個伺服器環境中前端專案自動部署服務(上)

今天我們來從零構建一個簡易的前端自動部署專案,為了方便大家理解,除了基礎依賴,儘量不使用其他第三方外掛(我連ui庫都沒裝),儘量減少學習成本,專案中用到了pikaz-shell,一個操作shell外掛,對此有疑惑的話可以前往我之前的pikaz-shell文章檢視。

專案目標

搭建一個伺服器前端專案自動部署api服務,搭建一個部署平臺,通過介面操作完成專案部署。

檔案結構

首先建立一個結構如下的資料夾,並切換到api資料夾,執行npm init -y初始化

├─api
│  ├─app.js
│  └─base.json
└─admin
複製程式碼

api編寫

切換到api資料夾

在package.json檔案中加入專案所需依賴

"dependencies": {
    "koa": "^2.13.0","koa-bodyparser": "^4.3.0","koa-router": "^9.0.1","koa2-cors": "^2.0.6","pikaz-shell": "^0.1.3"
  }
複製程式碼

執行npm install安裝所有依賴

app.js

開啟app.js檔案,編寫所需介面。

寫入koa一個基數架構,引入koa和koa路由,處理跨域(因為我的測試環境都是部署在內網伺服器上,所以跨域設定全部通過,如果需要個性化設定,則可以自己去koa2-cors倉庫瞭解),解析post請求中的body(偷懶,所有請求都使用post方式~~~),以及其他所需功能模組,埠為3000,可自行修改app.listen(3000)為其他埠。

// Koa
const Koa = require('koa');
const app = new Koa();

// 跨域設定
const cors = require('koa2-cors');
app.use(cors());

// 路由
const Router = require('koa-router');
const router = new Router();

// 解析body
const bodyParser = require('koa-bodyparser');
app.use(bodyParser());

const fs = require('fs');

const shell = require
('pikaz-shell'); // 啟動路由 app.use(router.routes()).use(router.allowedMethods()) /* * api編寫 */ console.log("啟動成功") app.listen(3000); 複製程式碼

資料庫

因為我們這個專案是非常小的,使用太大的資料庫未免有點太浪費了,而且遷移部署很麻煩,所以我們使用之前建立的base.json檔案當做一個微型資料庫,寫入

{
  "project": [],"nginx": {}
}
複製程式碼

其中project為專案資訊,nginx為nginx配置

介面

查詢列表介面
router.post('/list',async ctx => {
  const { project,nginx } = JSON.parse(fs.readFileSync('./base.json','utf-8'));
  ctx.body = { code: 200,data: { project,nginx },message: '查詢成功' };
})
複製程式碼

讀取base.json檔案,取出其中的project和nginx值返回

新增專案介面
/**
 * @name: 新增專案
 * @param {String} name/專案名稱
 * @param {String} git/專案git地址
 * @param {String} path/專案所在資料夾位置
 * @param {String} build/打包命令
 * @return: 
 */
router.post('/add',async ctx => {
  const { name,git,path,build } = ctx.request.body
  const data = JSON.parse(fs.readFileSync('./base.json','utf-8'));
  const gitProject = data.project.find(item => item.name === name)
  if (gitProject) {
    ctx.body = { code: 500,data: null,message: '已存在相同名稱的專案' };
    return
  }
  // 工程檔名
  const n = git.split('/')
  const projectName = n[n.length - 1].replace('.git','')
  // clone專案並安裝依賴打包
  const result = await shell([{ cmd: [`git clone ${git}`],path }])
  if (result === true) {
    // 新增入配置中
    data.project.push({ name,projectName,build })
    fs.writeFileSync('./base.json',JSON.stringify(data))
    ctx.body = { code: 200,message: '新增成功' };
  } else {
    ctx.body = { code: 500,message: '新增失敗' };
  }
})
複製程式碼

接收四個引數,分別為專案名稱,專案git地址,專案所在資料夾位置,打包命令,我們使用專案名稱作為主鍵,不可重複,如果重複則返回重複錯誤資訊,之後使用pikaz-shell外掛執行git clone專案,從git地址中獲取clone下來的資料夾名稱,並新增進配置中,之後將專案資訊寫入base.json資料庫中。

編輯專案介面
/**
 * @name: 編輯
 * @param {String} name/專案名稱
 * @param {String} git/專案git地址
 * @param {String} path/專案所在資料夾位置
 * @param {String} build/打包命令
 * @return: 
 */
router.post('/edit','utf-8'));
  const index = data.project.findIndex(item => item.name === name)
  if (index === -1) {
    ctx.body = { code: 500,message: `不存在${name}專案` };
    return
  } else {
    // 配置修改專案
    data.project[index] = { ...data.project[index],build }
    fs.writeFileSync('./base.json',message: '修改成功' };
  }
})
複製程式碼

和新增介面類似,接收同樣的四個引數,讀取base.json資料庫,檢視是否存在相同專案名稱name,不存在則返回錯誤資訊,存在則將對應的專案資訊修改(name是主鍵,不可修改,所以在賦值時並沒有將name賦值,而是保留原有的name),之後將處理好的資料寫入base.json資料庫中。

編輯專案介面
/**
 * @name: 刪除
 * @param {String} name/刪除專案的名稱
 * @return: 
 */
router.post('/del',async ctx => {
  const { name } = ctx.request.body
  const data = JSON.parse(fs.readFileSync('./base.json',message: `不存在${name}專案` };
  } else {
    // 刪除專案檔案
    const project = data.project[index]
    const result = await shell([{ cmd: [`rd/s/q ${project.projectName}`],path: project.path }])
    if (result) {
      // 配置刪除專案
      data.project.splice(index,1)
      fs.writeFileSync('./base.json',JSON.stringify(data))
      ctx.body = { code: 200,message: '刪除成功' };
      return
    }
    ctx.body = { code: 500,message: '刪除失敗' };
  }
})
複製程式碼

基本操作和新增修改沒太大區別,讀取base.json資料庫,查詢傳過來的name,刪除該條專案資訊,再寫入base.json資料庫。

構建專案介面
/**
 * @name: 構建
 * @param {String} name/專案名稱 
 * @return: 
 */
router.post('/build',async ctx => {
  const { name } = ctx.request.body
  // 查詢專案
  const data = JSON.parse(fs.readFileSync('./base.json',message: `${name}專案檔案不存在` };
  } else {
    const project = data.project[index]
    const path = `${project.path}/${project.projectName}`
    if (fs.existsSync(`${path}/node_modules`)) {
      // 存在node_modules則刪除
      await shell([{ cmd: ["rd/s/q node_modules"],path }])
    }
    // 安裝依賴打包
    const result = await shell([{ cmd: ["git pull","npm install",project.build],path }])
    if (result === true) {
      ctx.body = { code: 200,message: "build成功" };
    } else {
      ctx.body = { code: 500,message: "build失敗" };
    }
  }
})
複製程式碼

構建介面接收一個專案名稱name引數,查詢base.json中porject中的相同name的專案資訊,使用專案資訊中的路徑path和資料夾名稱projectName組成專案的絕對定位地址,在專案中查詢是否有node_modules依賴資料夾,如果有,則刪除;之後進行git pull拉取專案,npm install安裝依賴,以及專案資訊中的build打包命令。

至此,整個專案構建api服務已完成(nginx部署部分放到下篇)

api呼叫

如專案的新增api呼叫

// api服務地址
const api="http://127.0.0.1:3000";
// 新增的專案資訊
const addProject={ name: "pikaz-excel-js",git: "https://github.com/pikaz-18/pikaz-excel-js.git",path: "D:\",build: "npm run build" };
// 新增
fetch(`${api}/add`,{
        method: 'POST',body: JSON.stringify(addProject),headers: {
          'Content-Type': 'application/json'
        }
      }).then(res => {
        res.json().then(data => {
          if (data.code === 200) {
            // 構建
            fetch(`${api}/build`,{
              method: 'POST',body: JSON.stringify({ name:addProject.name }),headers: {
                'Content-Type': 'application/json'
              }
            }).then(res => {
              res.json().then(data => {
            })
            }).catch(err => {
              console.log(err)
            })
            addProject = { name: "",git: "",path: "",build: "" }
          }
        })
      }).catch(err => {
        console.log(err)
      })
複製程式碼

呼叫新增/add介面,新增成功後呼叫/build構建介面,即可完成專案的新增與構建。

可以以此為基礎構建一個專案部署介面,也可以在專案根目錄中加入一個build.js檔案,裡面寫好請求/build介面的構建請求,在package.json中的打包命令

"scripts": {
    "test": "node build.js && vue-cli-service build"
  },複製程式碼

加入node build.js,即可在執行npm run test,在專案構建的時候可同時更新測試環境,完成自動更新啦。

admin專案部署介面就不細說了,可直接檢視本專案的admin資料夾,因為只是很簡單的調取api,相信這一定難不倒聰明的你,。

專案啟動

我使用pm2的方式啟動,只需切換到api資料夾執行

npm run dev
複製程式碼

即可啟動,如果不想使用pm2的話,也可以直接啟動

node app.js
複製程式碼

注意

在使用本專案前,請確保伺服器環境安裝了git,node,pm2這些必要環境與外掛,並且開放了api服務所使用的埠(也可以使用nginx代理)。

專案地址

github.com/pikaz-18/pi…

最後

nginx配置修改放在下篇講,如果全部放在本篇太臃腫了(其實我也想再水一篇)。

本專案只是一個極簡實現(只為了讓大家對思路看的更清楚),實現了一個測試環境伺服器端的前端專案自動新增、修改、刪除、查詢、構建,因為我是使用在內網伺服器環境中的,所以我也沒做賬號驗證,如果需要的話可自行新增如jwt驗證等驗證方式,另外錯誤處理也基本沒做太多,如果想要更完善的錯誤處理,也可自行新增。

如果覺得對你有幫助的話,請點個贊吧。