前端開發只是前端項目的一部分,開發完還須要部署,在沒有持續集成的狀況下,每次手動構建(build)、上傳,還要藉助xftp等第三方的軟件。重複繁瑣的手動工做。最近在npm倉庫發現了一個
ftp
的包,因而想到基於該包封裝個簡單的函數:根據配置的用戶名
和密
碼,以及源文件目錄
、服務器文件目錄
,執行上傳。javascript
效果圖以下:前端
mkdir ftp-loader
、cd ftp-loader
、npm init
新建並初始化項目java
npm i ftp ora
安裝依賴 :ftp 核心依賴、ora是一款spinner庫(loading效果
)git
編寫一個函數,接收一個對象有五個屬性:域名
、用戶名
、密碼
、上傳文件的目錄
、服務器目錄
。github
實現步驟以下:npm
ftp庫
、ora庫
ready
後開始上傳,並開始loadingpromise
對象若是根目錄下直接發送,若是有子文件夾,先在服務器建立文件夾再發送,若是再有深層次的文件夾則繼續下潛。loading
、關閉鏈接。當文件目錄下有子目錄時須要在服務端建立相應的目錄,該過程是異步的。 發送文件的過程也是異步的。數組
讀取文件並收集文件路徑到數組過程須要是同步的。promise
client
的mkdir
方法有個遞歸選項能夠直接建立父目錄,爲了不異步、同步的可能產生的問題,咱們採用該方法建立目錄。服務器
因爲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.
爲了方便有興趣的讀者測試,我在測試文件直接放了域名、用戶名、密碼。