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、部署的整个流程。