1. 程式人生 > >前端工程化之部署篇

前端工程化之部署篇

前言
    部署簡單來說就是將構建產出的程式碼部署到伺服器上,在開發中我們通常的操作就是使用ftp將程式碼上傳到伺服器上固定目錄下即可,所以這項工作在很多開發看起來是簡單而又無聊的工作,這種部署方式從本質上來說沒毛病,但是隻適用於由少數人維護的規模較小的專案,如果這是個使用者量龐大的產品,擁有多體系的技術團隊,那麼,我們在設計部署流程的時候就需要考慮許多其他的因素了,比如如何多人協作,提高部署效率,控制部署時的安全等等,這個時候就不再是一個簡單的ftp上傳程式碼這麼簡單了。

    要做到前端資源自動化部署首先需要的就是設計合適的部署流程,這個和前端專案的大小和部署的環境是有直接聯絡的,比如測試環境,準生產環境,生產環境,他們的部署流程差異是比較大的,一般測試環境我們開發人員可以隨便造,準生產環境和生產環境就需要專門的運維人員,按照嚴格的釋出流程來部署了,這個時候,我們開發人員一般只需要提供程式碼的倉庫地址和版本號,其他的都交給類似jenkins這種整合化平臺來進行統一整合,當然這裡面可能需要用到一些指令碼,比如我所在的公司每個專案中目錄中都建立有一個資料夾裡面全部是一些python指令碼,用來給jenkis打包使用的,這裡不是我們要講的點,這裡只提一下。

    前面提到了部署流程,規範的流程是保障事情有條不紊向前推進的基礎,就像我們想去"浪漫的土耳其",那麼我們就得首先辦理護照,然後再購買機票,訂酒店…然後去找土耳其小姐姐。其實我覺得首先還是得看看自己的錢包還剩多少和房貸還有多少沒還。扯遠了,回到前端自動化部署上來。在設計流程的時候我們需要考慮的三大因素:

  1. 快速部署
  2. 協同部署
  3. 保證部署安全

下面就一步一步簡單總結一下。

快速部署

     前面提到的使用sftp工具這種簡單粗暴的方式來上傳構建好的前端程式碼到伺服器,雖然也相對比較快速,但是手動部署和自動化部署畢竟level還是差很多的,就像坐綠皮車和坐高鐵那檔次還是有那麼一點點的,所以我們需要用自動化部署來代替手動 ,這樣一方面可以提高部署效率,另一方面開發人員可以少做一些他們以為的無用功,然後把時間多花點在改bug和寫bug這種事上來。
大多數開發在後期都需要頻繁的將修改後的程式碼部署到伺服器上去,這個時候我們原始的部署流程是:

Created with Raphaël 2.2.0開始通過SSH登入伺服器開啟sftp圖形化介面上傳程式碼結束

看起來簡單 ,但是手動去重複這種機械化的工作,不免讓人感到乏味。這個時候就需要用程式碼來幫我部署。下面講解一下我自己在vue-cli的基礎上實現的本地快速部署方案

實現步驟:

  1. 配置需要部署的目標伺服器資訊
  2. 實現部署行為
  3. 實現命令列
配置需要部署的目標伺服器資訊:

    在部署的時候我們需要做到目標伺服器地址的資訊可配置化,所以我在config目錄下的index.js檔案中增了伺服器的相關配置項:

{
 ...
 publish:{
      remoteDir:'/xxx/xxx/xxx/target'
,//遠端上傳目錄(伺服器) localSourcePath:"",//本地需要上傳的資源路徑(預設專案根目錄下的dist資料夾) serverConfig:{//伺服器驗證資訊 host: '', username: '***', password: '***', algorithms: { "kex": [ "diffie-hellman-group1-sha1", "ecdh-sha2-nistp256", "ecdh-sha2-nistp384", "ecdh-sha2-nistp521", "diffie-hellman-group-exchange-sha256", "diffie-hellman-group14-sha1" ], "cipher": [ "3des-cbc", "aes128-cbc", "aes192-cbc", "aes256-cbc", "aes128-ctr", "aes192-ctr", "aes256-ctr", "[email protected]", "[email protected]", "arcfour", "arcfour128", "arcfour256", "blowfish-cbc", "cast128-cbc", ], "serverHostKey": [ "ssh-rsa", "ecdsa-sha2-nistp256", "ecdsa-sha2-nistp384", "ecdsa-sha2-nistp521" ], "hmac": [ "hmac-sha2-256", "hmac-sha2-512", "hmac-sha1" ] } } }

這裡algorithms這個配置項主要是解決在使用node-ssh2模組連線目標伺服器的時候出現的伺服器和客戶端 加密方式不一致的問題,如果你在使用node-ssh2模組時也可能會遇見相同的錯誤,所以把這個配置項加上就解決了。這裡個配置項配置好後就不需要在改變了。其他的配置項基本都是需要部署的伺服器資訊。

實現部署行為

    實現部署行為主要是基於sftp協議,這裡使用到了node-ssh2中實現的sftp相關的方法。我在這裡實現流程主要是分以下幾步:

  1. 構建,壓縮構建後的程式碼
  2. 通過node-ssh2連線目標伺服器
  3. 通過node-ssh2中的sftp相關方法上傳壓縮檔案,解壓,刪除壓縮檔案
  4. 上傳失敗時執行回滾操作

    大致的流程圖:
部署實現原理
實現程式碼在build資料夾裡面的publish.js

const uploadBySftp = require("./modules/ssh.js");
let config = require("../config/index.js");
const path = require("path");
const chalk = require("chalk");
const ora = require("ora");
async function startUpload(config){
      config = initOption(config);
      const localPath = config.publish.localSourcePath;
      const targetPath = config.publish.remoteDir;
      let desc =  "*******************************************\n"
                 +"***              開始部署               ***\n"
                 +"*******************************************\n"
    //1 壓縮
    let localZipPath = await uploadBySftp.zipLocalFile(localPath,targetPath);
    //2 連線ssh
     let upload = new uploadBySftp(config.publish.serverConfig);
     await upload.connect();
     try {
            //3 上傳檔案
            let remotePath = await upload.startUploadFile(localZipPath,targetPath,true);
            //4 解壓
            let remoteZipPath = await upload.unzipRemoteFile(remotePath,targetPath,false);
            //5 刪除遠端壓縮檔案
            await upload.deleteZipFile(remoteZipPath);
            //刪除原先已經存在的資料夾
            await upload.deleteFolder(upload.newName);
            let desc =  "\n******************************************\n"
                        +"***              部署成功              ***\n"
                       +"******************************************\n"
            console.log(chalk.green(desc));
     
     } catch (error) {
            console.error(chalk.red("檔案部署失敗"));
            await upload.rolUp();//開始回滾
     }
     //關閉連線
     upload.close();
}
/**
 * 初始化引數
 */
function initOption(config){
   let hostPattern = /(?:(?:(?:25[0-5]|2[0-4]\d|(?:(?:1\d{2})|(?:[1-9]?\d)))\.){3}(?:25[0-5]|2[0-4]\d|(?:(?:1\d{2})|(?:[1-9]?\d))))/ig;
   let remoteHost = process.argv[2];
   let dirPattern = /(\/opt\/dss\/client\/){1}/ig
   let dir = process.argv[3];
  if(remoteHost){
    if(hostPattern.test(remoteHost)){
      config.publish.serverConfig.host = remoteHost;
    }
  }

   if(dir){
      config.publish.remoteDir = path.join(path.dirname(config.publish.remoteDir),dir).split(path.sep).join("/");
      console.log(config.publish.remoteDir);
   }
   //校驗輸出地址是否合法
   if(!dirPattern.test(config.publish.remoteDir)){
      throw new Error("上傳地址非法");
      return
  }
   if(config.publish){
      if(!config.publish.remoteDir){
        throw new Error("請配置遠端資料夾地址")
        return
      }

      if(!config.publish.localSourcePath){
          config.publish.localSourcePath = path.join(process.cwd(),"dist");
      }

      if(!config.publish.serverConfig.host||!config.publish.serverConfig.username||!config.publish.serverConfig.password){
        throw new Error("請配置遠端伺服器資訊")
        return
      }

      return config;
   }else{
      return;
   }
};
startUpload(config);

這裡沒有實現程式碼構建,這是因為vue-cli構建的vue專案已經幫我們實現了,只需要在npm run build之後執行這個部署操作就OK了,在後面實現釋出命令的時候再講;
initOption方法主要時為了對伺服器配置資訊進行校驗。

    具體的方法實現在build/modules/ssh.js裡面

實現命令列

    在使用vue-cli構建的專案中,我們可以使用npm run dev來啟動本地開發環境,npm run build構建輸出程式碼,這裡我們實現一個npm run publish命令來實現部署原生代碼到伺服器的操作。首先需要在專案根目錄下的package.json中新增npm run publish命令

 {
  ...
  "scripts":{
    ...
    "publish""npm run build&&node ./publish.js"
  }
 }

配置完之後,我們就可以使用

npm run publish

來實現快速部署了,在執行命令前我們需要要不正配置檔案中伺服器的相關資訊已經配置完成。這在一定程度上降低了我們部署的靈活性,在真實開發中我們一般不只有一臺測試換伺服器,有時候我們需要向不同的伺服器部署,這時候就需要去改變配置引數,顯得有點麻煩。所以這裡新增了命令列注入引數的方式,來實現靈活部署,例如:

  1. npm run publish 172.25.20.xxx 實現向不同的伺服器來部署程式碼
  2. npm run publish 172.25.20.xxx dirname 實現不是到伺服器上某個資料夾裡面面去。

這樣我們就可以在在開發中是先快速的向伺服器部署了。
    快速部署其實就是將上面的手動上傳程式碼變成了用程式來幫助我們實現上傳,但是本質上還是一個簡單的程式碼上傳和替換,這隻適合在本地開發環境到開發測試環境的部署,並且只適合單人或極少數人維護和技術體系簡單的前端專案。如果是前端結構複雜,技術團隊眾多的前端專案,就需要考慮協同部署了。

協同部署

    協同部署主要是解決多人同時開發的問題,因為你提交程式碼後會覆蓋別人的程式碼,導致別人開發的功能模組失效。這個時候,就需要一個統一的管理平臺來執行部署

在這裡插入圖片描述

從流程圖上可以看出,協同部署需要統一管理平臺來實現統一部署,當所有開發人員都提交版本後,這個時候在平臺上觸發打包部署,然後就可以繼續去寫bug了…。當然,統一管理平臺會消耗一定的資源,所以需要根據專案自身的情況來決定了是否使用了,不過現在雲管理平臺已經非常普遍了,所以使用起來也是非常方便和簡單的。

安全部署

    簡單來說就是需要保證部署操作的安全,避免誤操作。就比如前一段時間阿里雲宕機事件,據說就是某個"實習生"錯誤的執行了delete指令碼,導致使用者無法登陸,這種影響可想而知。當然我們前端部署不會涉及到對使用者資料的操作,最嚴重的就是頁面無法訪問,恢復起來也是相對容易。但是這不是我們不重視前端安全部署的理由,比如那天一覺醒來天貓的頁面無法訪問了那問題就大條了。當然這對廣大已婚男士來說可能這就是福音了,媳婦兒可以消停一下了。但是作為開發來說這就是嚴重的事故了,前兩天順豐程式猿誤操作事件可以瞭解一下。所以在進行部署的時候一定要考慮到安全,要做到安全部署主要從三個方面下手,一方面是部署許可權,另一方面就是有專門的人員負責稽核部署請求,最後就是版本回退。

部署許可權

    正常情況下生產環境都是由專門的運維人員負責部署,我們開發人員就不需要嚇操那份心了,最多就是熬夜打輔助,站在他們旁邊陪著他們部署。至於運維人員那邊怎麼實現安全部署,我就不知道了。下面我們主要說一下準生產環境和開發測試環境的部署。

部署請求稽核

    準生產環境也叫模擬環境,對於我們開發來說它就是生產環境,它的部署流程也是要嚴格按照生產環境的部署要求來。通常情況下發起部署請求後,需要專門的人員來稽核你的部署請求是否合理合法,只有請求通過後才能執行部署,這裡需要專門的稽核人員,這個人一般是經驗非常豐富的開發人員,有可能就是我們常說的大牛。當然要是最後出了問題,他也是要陪你一起背鍋的…。

版本回退

    說完了前面部署許可權和部署稽核後下面就來說所版本回退,一般當你使用到版本回退的時候,也基本上宣佈你這次部署失敗了,部署失敗意味著可能又要多加幾個班了。版本回退一般是在升級的時候用到的。回退一方面是在部署後發現有嚴重bug的時候,需要回退到之前的穩定版本;保證生產正常;另一種情況就是在自動化部署過程中發生錯誤了,部署無法繼續進行,需要回退到上一個版本。要做到回退關鍵就是需要在部署前對上一個版本在進行備份,所以第一次發版就不存在什麼回退了,因為無路可退,沒有上一個版本怎麼回退呢。
    這裡就拿我自己實現的本地自動部署方案說一下,因為我的部署物件是開發測試環境,所以安全性就要低的多,一方面對部署的地址進行校驗,因為在部署的過程中需要對伺服器上存在的相同路徑檔案進行重新命名,為了防止錯誤的將其他重要檔案重新命名所以我們一般將上傳的路徑是固定的,因為程式碼在伺服器上位置是固定了的,在上傳的時候校驗一下,有沒有輸入非法路徑。另一方面如果部署過程中失敗,就執行回退操作。

本地自動化部程式碼 github地址,有心興趣的可以看看。

總結

    這篇文章算是是在看了《前端工程化設計與實踐》部署篇以後的一個簡單總結記錄吧,目前前端工程化的書籍不是太多,大多都是以部落格的形式存在,講的內容只集中在工程化的某個環節或者講的比較粗線條,就像我這裡只總結了一下部署,這只是工程化中的一角,後面我會結合書籍的講解和自己的實踐分享工程化的腳手架,構建…。如果有興趣的朋友可以購買這本書來看看,我不是打廣告,我作者沒半毛錢關係,只是我看完一遍後對於前端工程化清楚的理解,書讀三遍其義自見,我打算再讀幾遍,然後結合書中講解運用到工作中來,畢竟實踐是檢驗真理的唯一標準。好了,收工,還是那句話請忽略文中的"通假字"。明天是國慶節了,祝大家國慶快樂!祝祖國富強,繁榮!祝自己一切安好!

相關推薦

前端工程化部署

前言     部署簡單來說就是將構建產出的程式碼部署到伺服器上,在開發中我們通常的操作就是使用ftp將程式碼上傳到伺服器上固定目錄下即可,所以這項工作在很多開發看起來是簡單而又無聊的工作,這種部署方式從本質上來說沒毛病,但是隻適用於由少數人維護的規模較小的專案

前端開發CSS

重要 utf import 無效 nbsp 出現 bsp 示例 減少 一、CSS介紹和語法 二、CSS引入方式 三、基本選擇器 四、高級選擇器 五、偽類選擇器 六、偽元素選擇器 1?? CSS介紹和語法   1、 CSS的介紹   (1)為什麽需要C

前端面試CSS整理

盒模型,box-sizing 盒模型組成:content+padding+border+margin ; 在標準盒模型中,css中給元素設定的width和height就是content寬高 在怪異盒模型下:css中給元素設定的width和height=co

Web前端工程化VSCode+Git 解決衝突和error

         多人協作開發使用版本控制難免會有衝突,在前端使用VSCode和Git過程中,就會遇到大大小小的衝突,有的merge一下,然後提交推送就可解決,有的是因為HEAD指標混亂造成,本地和遠端分支拉取/合併問題。 問題1、直接解決衝

web前端工程化依賴注入

傳統依賴控制,由使用者自己new   依賴注入 控制器從內部轉到了外部 注入器     把se

web前端工程化路由

控制檢視應用狀態的物件 除錯階段,更新元件和路由的時候,需要重新執行,瀏覽器更新是沒有效果的,只有靜態頁面的更新能夠被刷新出來。 路由的5個物件 Routes,path中不加/

Web前端工程化Angular元件

1、元件概念         如何理解元件,可以幫助你如何理解前端工程化,就是把頁面上顯示的內容,劃分成一個個的元件,組合到一起就變成了我們熟悉的網頁。 看一下下面這個百度頁面,怎麼劃分,可以從head、body、footer分三部分,在大的元件上

前端工程化Nodejs+Angular+webStorm+VSCode安裝與配置

angular是在nodejs基礎上執行的,所以先安裝nodejs。 安裝Nodejs 在官網上下載 合適的版本 下載node-8.9.0-x64.msi 一路下一步,直到安裝完成 請先在終端/控制檯視窗中執行命令 node -v 和 npm -v

前端面試js整理(一)

js的基本型別有哪些?引用型別有哪些?null和undefined的區別 js變數的值有兩種: 1.基本型別值:存放在棧記憶體的簡單資料型別。如Number、String 、Boolean、Null和Undefined這物種 2.引用型別值:存放在堆記憶

Kubernetes管理Docker叢集部署

什麼是Kubernetes? Kubernetes是Google開源的容器叢集管理系統,實現基於Docker構建容器,利用Kubernetes能很方面管理多臺Docker主機中的容器。 主要功能如下: 1)將多臺Docker主機抽象為一個資源,以叢集方式管理容器,

MongoDB上手部署

主從複製 主從複製是一個簡單的資料庫同步備份的叢集技術 在資料庫叢集中要明確知道誰是主伺服器,主伺服器只有一臺 從伺服器要知道自己的資料來源也就是知道自己的主伺服器是誰 –master用來確定主伺服器,–slave和–source 來控制從伺服器 主伺

前端面試HTML整理

HTML5新特性,語義化 語義化標籤比起傳統的div+css的樣式佈局來說,更遵循W3C規則,有利於團隊的開發維護,更有利於SEO優化,方便其他裝置解析 舉幾個例說明: 標籤 語義化 <section></sect

前端工程化動態資料代理

引言 在前端開發過程中,開發者通常都會遇到前端資料不能正常獲取的問題,這就需要開發者之間’想辦法‘搞到這些資料;開發過程中我們可能遇到的場景: 後端介面資料開發中暫時不可用,需要前端在自己本地mock介面資料進行開發 重構一個已有的前端功能,在測試環境開發功能,這時可能

前端深入css丨2020年前,徹底掌握css動畫【transition】

寫在前面 馬上就2020年了,不知道小夥伴們今年學習了css3動畫了嗎? 說起來css動畫是一個很尬的事,一方面因為公司用css動畫比較少,另一方面大部分開發者習慣了用JavaScript來做動畫,所以就導致了許多程式設計師比較排斥來學習css動畫(至少我是),但是一個不懂css動畫的前端工程師不能稱之為

前端深入css丨2020年前,徹底掌握css動畫【animation】

寫在前面 馬上就2020年了,不知道小夥伴們今年學習了css3動畫了嗎? 說起來css動畫是一個很尬的事,一方面因為公司用css動畫比較少,另一方面大部分開發者習慣了用JavaScript來做動畫,所以就導致了許多程式設計師比較排斥來學習css動畫(至少我是),但是一個不懂css動畫的前端工程師不能稱之為掌握

前端深入css丨初探【transform】,手把手帶你實現1024程式設計師節動畫

寫在前面 馬上就2020年了,不知道小夥伴們今年學習了css3動畫了嗎? 說起來css動畫是一個很尬的事,一方面因為公司用css動畫比較少,另一方面大部分開發者習慣了用JavaScript來做動畫,所以就導致了許多程式設計師比較排斥來學習css動畫(至少我是),但是一個不懂css動畫的前端工程師不能稱之為掌握

前端的UI設計與交互導航

頂部 隱藏 標簽 距離 例如 適合 操作類 允許 垂直 在廣義上,任何告知用戶他在哪裏,他能去什麽地方以及如何到達那裏的方式,都可以稱之為導航。當設計者使用導航或者自定義一些導航結構時,請註意:盡可能提供標識、上下文線索,避免用戶迷路;保持導航樣式和行為一致或者減少導航數量

前端面試基礎-htmlH5新特性

-h 側邊欄 沒有 開發者 制作 article 廣告 隱藏 val h5的新特性(目前個人所了解)如下 語義化標簽 表單新特性 視頻(video)和音頻(audio) canvas畫布 svg繪圖 地理定位 為鼠標提供的拖放API webworker (重點)Stora

前端開發JavaScript基礎

object 行為 基礎篇 類型轉換 設計 介紹 目的 數據類型轉換 引入 主要內容:   1、JavaScript介紹   2、JavaScript的引入方式   3、javaScript變量和命名規則   4、五種基本數據類型   5、運算符   6、字符串

前端開發JavaScript HTML DOM理論

parent paragraph app style document col () 刪除 create 主要內容:   1、HTML DOM元素   2、HTML DOM事件   3、HTML DOM實例 一、DOM元素   主要操作有添加、刪除和替換HT