现在成熟的前端团队里面都有自己的内部构建平台,我司云长便是我们 CI/CD 的提效利器。我先来简单介绍下我司的云长,此云长非彼云长,云长主要做的是:获取部署的项目,分支,环境基本信息后开始拉取代码,安装依赖,打包,并且将项目的一些资源静态文件上传 CDN,再将生成的代码再打包成镜像文件,然后将这份镜像上传到镜像仓库后,最后调用 K8S 的镜像部署服务,进行镜像按环境的部署,这就是我们云长做的事情。如果想从零开始搭建一个自己团队的部署平台可以看下我们往期文章 [如何搭建适合自己团队的构建部署平台] ,本期我们只是针对云长中静态资源本地化的功能做细致阐述。
为了网络安全,客户会要求我们的应用是要完全部署在内网的,那我们需要做什么呢?第一我们需要考虑前端代码中是不是有些直接访问外网资源?第二是不是后端返回了静态资源地址在某种情况下就访问了?第三 CDN 资源具体有那些类型呢?前端直接访问的 CDN 的资源太普遍了,如下既有 at.alicdn.com,又有我们自己内部的静态资源 luban.zcycdn.com, sitecdn.zcycdn.com 等。如下这些就在我们代码中使用的静态资源地址。
<link rel='stylesheet' href='//at.alicdn.com/t/fontnm.css' />
<img src="https://sitecdn.zcycdn.com/f2e/8.png"alt="收货人"/>
<img src="https://luban.zcycdn.com/f2e/8.png"alt="收货人"/>
//css中字体文件
src:url(https://sitecdn.zcycdn.com/t/font_148178j4i.eot);
src:url(https://sitecdn.zcycdn.com/t/font1_4i.woff);
为了保证我们内网中可以访问我们讨论出以下两个方案
我们通过 DNS 服务这一层去处理,具体 DNS 如何进行的二域名,三级域名进行解析,如何 DNS 缓存,以及什么是 13 台根服务器,我们这次不做深入探讨,我们只需要 DNS 的可以进行域名解析,解析到指定的 IP 服务上即可。
那我们是不是可以想一下,是不是把代码中访问的静态资源的域名拦截一下,DNS 解析成本地服务的地址是不是就可以了呢?为了更清楚的理解,我做一个例子如下:
我们代码中需要访问某个图片,CDN 地址:https://cdn.zcycdn.com/b/a.js
上传提前把 a.js 这个文件提前放到本地服务器上访问地址:https://demo.com/b/a.js
当代码运行的时候,代码中访问了 https://cdn.zcycdn.com 的时候,DNS 直接地址解析成 https://demo.com 的 IP 地址,达到访问静态资源的目的
看起来这个蛮简单的,不需要各个业务负责人排查修改自己代码中的静态资源,胜利在望了,兴致冲冲的跑去找运维童鞋提议是不是可以这样做,然而运维把我说的服服帖帖。运维童鞋说:静态资源放在对象存储或者服务器上,通过IP或者域名的方式都可以请求的到,不过 IP 只支持 HTTP 的方式,域名+SSL 证书的方式支持 HTTPS,可以做一些加密,让你的资源或者请求内容进行加密,不容易被破解,域名证书之前有 3 到 5 年的,3 年前已经改掉了,目前申请的证书都是一年的,那就预示着不仅仅要用户配置我们提供的 DNS 规则,还要配合我们一年一更新证,想要客户这样配合那是不容易。如下图所示:
DNS 只是帮我们把域名解析成了 IP, HTTPS 还需要证书验证服务器身份,仅仅 DNS 拦截解析还不够。模拟实现了一波大致思路:自己启动一个静态资源服务,以及 DNS 本地解析服务,当访问 juejin.cn 域名的时候 IP 解析成本地的 IP 并且成功访问到静态资源,具体如下。
暂时存放静态资源,模拟服务器上的资源
启动服务访问静态资源
我们的目的:如果访问 http://juejin.cn:3000/zcy.png (http://juejin.cn:3000/zcy.png) 的时候访问到我们本地服务的静态资源:http://10.201.45.121:3000/zcy.png (http://10.201.45.121:3000/zcy.png)
访问:http://juejin.cn:3000/zcy.png(http://juejin:3000/zcy.png)
如果是https://juejin.cn:3000/zcy.png (https://juejin:3000/zcy.png)
如果访问的是 HTTP 请求那就可以访问,HTTPS 就不能访问,侧面证明了 HTTPS 的证书问题。HTTPS 对称加密的秘钥我们采用非对称加密传输,数据传输还是使用对称加密,这保证了数据加密传输,为了保证防止冒充,CA(Certificate Authority), 颁发的证书就称为数字证书 (Digital Certificate),在非对称加密阶段,服务器会把证书会带着非对称加密的公钥,一起返回,向浏览器证明服务器的身份 HTTPS 相比 HTTP 多了一层 SSL/TLS(安全层)如下图。
项目在构建的时候扫描出项目中的静态资源地址,从我们公网的 CDN 服务放到客户自己的服务器上,修改源文件中的静态资源地址为客户本地服务的访问地址。
优缺点一目了然,方案一无需修改代码,但是需要充分得到客户的大力信任与支持需要配置 DNS 转发,方案二无需劳烦客户,即使后面有新增域名也不需要和客户沟通,完全自己解决,但是对代码有侵入性,会替换静态资源的地址
统一封装 runCommand 执行命令
function runCommand(cmd, args, options, before, end) {
return new Promise((resolve, reject) => {
log(before, blue)
const spawn = childProcess.spawn(
cmd,
args,
Object.assign(
{
cwd: global.WORKSPACE,
stdio: 'inherit',
shell: true,
},
options
)
)
spawn.on('error', (error) => {
log(error, chalk.red)
reject(error)
});
spawn.on('close', (code) => {
if (code !== 0) {
return reject(`sh: ${cmd} ${args.join(' ')}`)
}
end && log(end, green)
resolve()
});
})
}
切换公司 nrm
runCommand('nrm', ['use', 'zcy-server'], {}, 'switch nrm registry to zcy', 'switch nrm registry to zcy success')
下载依赖
runCommand('npm', ['i', '--unsafe-perm'], {}, 'npm install', 'npm install success')
不同环境需要上传不同的地址因此需要动态修改 webpack 的 publicPath
const cdnConfigStr = `assetsPublicPath: 'http://dev.com',`
replaceFileContent(configPath, /assetsPublicPath:.+,/g, cdnConfigStr)
exports.replaceFileContent = function(filePath, source, target) {
const fileContent = fs.readFileSync(filePath, 'utf-8')
let targetFileContent = fileContent
if (Array.isArray(source)) {
source.forEach(([s, target]) => {
if (target) {
targetFileContent = targetFileContent.replace(s, target)
}
})
} else {
targetFileContent = fileContent.replace(source, target)
}
fs.writeFileSync(filePath, targetFileContent, 'utf-8')
}
编译项目
runCommand('npm', ['run', 'build'], {}, `webpack build`, `webpack build success`)
const replaceWebpackDistContent =
async function(options = {},collectionAssets,folder) {
const fileContent = fs.readFileSync(filePath, 'utf-8');
let targetFileContent=fileContent;
[
[/(https\:)?\/\/g.alicdn.com\/[-a-zA-Z0-9@:%_\+.~#?&//=]+\.[-a-zA-Z0-9@:%_\+.~#?&//=]+/g, cdn],
[/(https?\:)?\/\/sitecdn.zcycdn.com\/[-a-zA-Z0-9@:%_\+.~#?&//=]+\.[-a-zA-Z0-9@:%_\+.~#?&//=]+/g, cdn],
[/(https\:)?\/\/cdn.zcycdn.com\/[-a-zA-Z0-9@:%_\+.~#?&//=]+\.[-a-zA-Z0-9@:%_\+.~#?&//=]+/g, cdn],
].forEach(([reg,uri])=>{
targetFileContent=targetFileContent.replace(reg,function(match){
let basename = '';
let uriMath = match;
basename = path.basename(uriMath);
if(uriMath.slice(0,4)!='http'){
uriMath='https:'+uriMath;
}
const parseUrl = url.parse(uriMath);
collectionAssets({src:uriMath,fileName:path.basename(parseUrl.pathname)});
console.log('替换前',match);
const myURL= new URL(projectName, uri);
const replacedUrl = uri+'/'+projectName+parseUrl.path+(parseUrl.hash||'');
console.log('替换后', replacedUrl);
return replacedUrl;
})
})
fs.writeFileSync(filePath, targetFileContent, 'utf-8')
}
获取写死在前端代码中的静态资源
const downloadAssetsFiles= async function(img,forder){
const staticAssets='staticAssets';
let assetsUrl=getPwdPath(`${forder||''}${path.sep}${staticAssets}`);
if(!fs.existsSync(assetsUrl)){
fs.mkdirSync(assetsUrl);
}
return Promise.all(img.objUnique('src').map(({src,fileName})=>{
if(fileName){
return new Promise(function(resolve,reject){
const originFileDir = path.join(assetsUrl,path.dirname(url.parse(src).pathname));
fs.mkdirSync(originFileDir,{recursive:true});
const uri = path.join(originFileDir,fileName);
download(uri,src,resolve,reject);
}).catch(err=>{
console.log(err)
throw new Error(err);
})
}
}))
}
function download(loadedUrl,src){
const writeStream = fs.createWriteStream(loadedUrl);
const readStream = request(src);
readStream.pipe(writeStream);
readStream.on('end', function() {
console.log(fileName,'文件下载成功');
});
writeStream.on("finish", function() {
console.log(fileName,"文件写入成功");
writeStream.end();
});
}
downloadAssetsFiles(assetsArr,'dist');
// 发现替换资源里还有cdn,因此替换下载后的cdn里面的cdn
const assetsArr=[];
await replaceWebpackDistContent(options,collectionAssets,'staticAssets');
await downloadAssetsFiles(assetsArr,'dist');
const ossEndpoint = process.env.OSS_ENDPOINT;
const commonOptions = {
accessKeyId: process.env.OSS_ACCESSKEYID ,
accessKeySecret: process.env.OSS_ACCESSKEYSECRET,
bucket: process.env.OSS_BUCKET,
timeout: '120s',
}
const extraOptions = ossEndpoint
? {
endpoint: ossEndpoint, // 从全局数据获取,没有会依赖 region
cname: true,
} : {
region: process.env.OSS_REGION,
}
const ossOptions = Object.assign({}, commonOptions, extraOptions);
const client = new OSS(ossOptions);
//onlinePath 访问的文件地址
//curPath 上传的文件地址
result = await client.put(onlinePath, curPath);
参考文档
SSL/TLS证书1年有效期新规 (https://www.trustasia.com/view-398-day-limit/)
node child_process 文档 (https://link.juejin.cn/?target=http%3A%2F%2Fnodejs.cn%2Fapi%2Fchild_process.html%23child_process_child_process_fork_modulepath_args_options)
深入理解Node.js 进程与线程 (https://link.juejin.cn/?target=https%3A%2F%2Fblog.csdn.net%2Fxgangzai%2Farticle%2Fdetails%2F98919412)
本文由哈喽比特于1年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/TT9sNgwgiuhQAucCmJWfRg
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。