發佈一款ftp部署前端資源的npm包

前端開發只是前端項目的一部分,開發完還須要部署,在沒有持續集成的狀況下,每次手動構建(build)、上傳,還要藉助xftp等第三方的軟件。重複繁瑣的手動工做。最近在npm倉庫發現了一個ftp的包,因而想到基於該包封裝個簡單的函數:根據配置的用戶名碼,以及源文件目錄服務器文件目錄,執行上傳。javascript

效果圖以下:前端

環境配置

mkdir ftp-loadercd ftp-loadernpm init 新建並初始化項目java

npm i ftp ora安裝依賴 :ftp 核心依賴、ora是一款spinner庫(loading效果git

編寫入口文件

編寫一個函數,接收一個對象有五個屬性:域名用戶名密碼上傳文件的目錄服務器目錄github

實現步驟以下:npm

  1. 引入ftp庫ora庫
  2. 經過ftp鏈接服務器,ready後開始上傳,並開始loading
  3. 從起點開始,讀取文件或遞歸讀取目錄,並將文件路徑(包括文件名)放入一個數組(只存放有效的文件,若是是文件夾讀取下面的文件)。
  4. 遍歷文件路徑數組,藉助promise對象若是根目錄下直接發送,若是有子文件夾,先在服務器建立文件夾再發送,若是再有深層次的文件夾則繼續下潛。
  5. 待全部文件發送完畢後,中止loading、關閉鏈接。

遇到的問題:

當文件目錄下有子目錄時須要在服務端建立相應的目錄,該過程是異步的。 發送文件的過程也是異步的。數組

讀取文件並收集文件路徑到數組過程須要是同步的。promise

clientmkdir方法有個遞歸選項能夠直接建立父目錄,爲了不異步、同步的可能產生的問題,咱們採用該方法建立目錄。服務器

因爲ftp庫建立文件夾是異步的、發送文件也是異步的,所以須要藉助promise對象,在Promise.all的then和catch裏分別提示成功、失敗,並關閉loading、鏈接異步

代碼示例
var Client = require('ftp');
var fs = require('fs');
var spinner = require('ora')()

var client = new Client();


module.exports = function({ host,user,password,sourceDir,targetDir }){
    var filepaths = [];
    function readFilesFromDir(parentPath,filePath){
        let currentPath = "";
        if(parentPath === ""){
            currentPath = filePath;
        }else{
            currentPath = parentPath+'/'+filePath;
        }
        let sourcePath = `${sourceDir}/${currentPath}`;

        if(fs.lstatSync(sourcePath).isDirectory()){
            let files = fs.readdirSync(sourcePath);
            for(let filePath of files){
                readFilesFromDir(currentPath,filePath); 
            } 
        }else{
            filepaths.push(currentPath)
        }
        
    }

    function readyFn(){
        spinner.start();
        fs.readdir(sourceDir, function(err,files){
            if(err) throw err;
            for(let filePath of files){
                readFilesFromDir("",filePath);
            }
            transferFiles();
        })
    }
    function transferFile(filePath){
        return new Promise((res,rej)=>{
            let parentPath = filePath.lastIndexOf('/') !== -1 && filePath.substring(0 , filePath.lastIndexOf('/') );
            let sourcePath = `${sourceDir}/${filePath}`;
            let targetPath = `${targetDir}/${filePath}`;
            let newDirInServer = `${targetDir}/${parentPath}`;
            if(!parentPath || parentPath === '.'){
                client.put(sourcePath, targetPath,function(err) {
                    if (err) throw err;
                    console.log(sourcePath+'-----'+targetPath)
                    res(true);
                });
            }else{
                client.mkdir(newDirInServer,true,function(err){
                    if(err) throw err;
                    client.put(sourcePath, targetPath,function(err) {
                        if (err) throw err;
                        console.log(sourcePath+'-----'+targetPath)
                        res(true);
                    });
                })
            }
        })
    }
    function transferFiles(){
        let promises = [];
        filepaths.forEach(filePath=>{
            promises.push(transferFile(filePath))
        })
        Promise.all(promises).then(res=>{
            console.log('上傳成功!')
            spinner.stop();
            client.end();
        }).catch(rej=>{
            console.log('上傳失敗!');
            spinner.stop();
            client.end();
        })

    }
    client.on('ready', readyFn);
    // connect to localhost:21 as anonymous
    client.connect({
        host,
        user,
        password
    });
}
複製代碼

測試

服務器:採用的西部數碼的虛擬主機(便宜)

mkdir test-files新建測試文件夾並複製一份構建好的文件進去(dist文件夾)。

配置test.js文件:

var main  = require('./index')
main({
    host:'你的主機域名',
    user:'ftp用戶名',
    password:'ftp密碼',
    sourceDir:"./test-files/dist",//上傳文件目錄
    targetDir:"wwwroot/test-ftp"//服務端目標目錄
})
複製代碼

npm run test 上傳完畢後經過軟件可看到所欲的文件已經在這了:

發佈

npm publish,具體發佈過程可參考個人另外一篇文章:發佈一款npm包幫助理解npm


全文完,全部代碼已經上傳至github.

爲了方便有興趣的讀者測試,我在測試文件直接放了域名、用戶名、密碼。

相關文章
相關標籤/搜索