CDN加速是Web應用性能優化和用戶體驗提高的相當重要的一環,當一個項目構建部署時,就須要考慮到如何高效的去完成相關資源的CDN部署。css
本文以一個基於 vue-cli3
構建的項目實例,來簡單講解如何配合Teamcity,自動進行阿里雲CDN資源部署和持續集成。html
vue-cli3 默認支持將項目以 test
、development
、production
三種模式構建,其中 production
模式將在 build 後生成 dist
目錄。咱們在項目路徑下插入 .env.[mode]
格式的文件就能夠實現自定義模式。vue
一般,默認的構建模式沒法知足項目研發需求。一個項目至少須要包含node
development
模式,不生成 dist 靜態目錄,使用 vue-dev-server運行項目;按照這個模型,咱們須要自定義一個 deploy
模式,來實現和普通 production
打包後,資源引入路徑的區別。webpack
首先,環境建立git
在項目根目錄下建立 .env.deploy
文件,添加內容以下:web
NODE_ENV=production DEPLOY=online
NODE_ENV
的設置表明webpack構建時使用production
模式,即會生成 dist
靜態目錄。DEPLOY
的設置,是一個咱們定義的變量,用於在配置中區分deploy
和production
模式。vue-cli
其次,配置文件npm
在 vue.config.js
中,配置 BASE_URL
json
// 根據自定義的變量來進行內容設置 let BASE_URL = '/' switch(process.env.DEPLOY) { case 'online': BASE_URL = 'http://web-cdn.xxx.com/' break default: BASE_URL = '/' } module.exports = { publicPath: BASE_URL, .... }
該配置會使得當程序使用 deploy
模式運行時,打包的資源根路徑爲咱們的CDN地址。
最後,構建命令
在 package.json
中,配置使用 deploy
模式的打包命令
"scripts": { "build": "vue-cli-service build", "deploy": "vue-cli-service build --mode deploy", ... }
當用戶執行 npm run build
時,會生成以 /
爲資源路徑的文件;
當用戶執行 npm run deploy
時,生成 index.html
中的資源路徑就變成了咱們配置的CDN路徑。
<!DOCTYPE html> <html> <head> <meta charset=utf-8> <meta http-equiv=X-UA-Compatible content="IE=edge"> <meta name=viewport content="width=device-width,initial-scale=1"> <link rel=icon href=http://web-cdn.xxx.com/favicon.ico> <title>Demo</title> <link href=http://web-cdn.xxx.com/css/chunk-0fabbc4c.08fa0fd2.css rel=prefetch> <link href=http://web-cdn.xxx.com/css/chunk-1025f268.0dc416de.css rel=prefetch> <link href=http://web-cdn.xxx.com/js/app.84dcc9e6.js rel=preload as=script> </head> <body> <div id=app></div> <script src=http://web-cdn.xxx.com/js/chunk-vendors.614ecc0c.js></script> <script src=http://web-cdn.xxx.com/js/app.84dcc9e6.js></script> </body> </html>
接下來,咱們要作的就是配置一個CDN,並可以把這些資源傳上去。
首先,在阿里雲上配置CDN,作好域名CNAME解析,並獲取到阿里雲的 accessKeyId
、accessKeySecret
、Region
、BucketName
等信息,而後選擇一種語言,寫好上傳腳本。
這裏咱們以Node腳本爲例:
// oss-deploy.js let OSS = require('ali-oss') let fs = require('fs') let client = new OSS({ region: 'oss-cn-hangzhou', accessKeyId: 'xxx', accessKeySecret: 'xxx', bucket: 'xxx' }) // 使用async+await方法,實現同步化,方便在失敗後重試處理 async function put(fileName) { try { let result = await client.put(fileName, '../dist/' + fileName) console.log('File Upload Success: ', fileName) } catch (e) { console.log('File Upload Failed: ', fileName) // 這裏省略異常/失敗的重試 } } // 讀取打包後的 dist 路徑,按照原文件夾結構,進行上傳 let readFileList = (path, filesList) => { let files = fs.readdirSync(path) files.forEach(itm => { if (itm) { let stat = fs.statSync(path + itm) if (stat.isDirectory()) { readFileList(path + itm + '/', filesList) } else { filesList.push(path + itm) } } }) return filesList } let dist = readFileList('../dist/', []) // 遞歸執行文件上傳操做 let i = 0, l = dist.length let uploadAsset = () => { if (i < l) { let name = dist[i].split('../dist/')[1] put(name) i++ uploadAsset() } } uploadAsset()
執行
npm install --save-dev ali-oss node oss-deploy.js
便可看到文件已經被上傳到了CDN路徑下。
上面的兩個模塊,已經實現了基本的CDN部署。但咱們在項目開發的時候,確定不但願每次 build完,都去本身執行上傳CDN,再去服務器上部署。
這裏咱們再把 TeamCity
上實現自動build、一鍵上線的流程簡單闡述。
TeamCity上的執行腳本以下:
cd /apps/kaleido-cms/ git pull -f origin master npm install npm run deploy git add dist/* git commit -m "Deploy" git push origin master cd /apps/kaleido-cms/deploy node oss-deploy.js ssh root@10.0.0.1 "./deploy_cms.sh" ssh root@10.0.0.2 "./deploy_cms.sh"
由於線上服務一般是集羣模式,而 webpack在不一樣服務器執行build,會產生不一樣的哈希值版本號,會致使遠程資源沒法獲取到。因此咱們須要在持續集成部署的服務器上作build操做,生成dist路徑,上傳到git和cdn。最後再到集羣的每一個服務器上拉取靜態文件便可。
補充:
經過這套操做,最終咱們實現了在TeamCity上,一鍵執行打包、上傳CDN、部署的整個流程。