交代背景
通過不到半年努力硫戈,我司前端開發(fā)已經(jīng)完全轉(zhuǎn)向 CI/CD了倍谜,在轉(zhuǎn)型的道路上瓢省, 對(duì)于前端代碼的異常監(jiān)控(聽云/senTry部分頁面有用)窟坐,沒有一個(gè)自己 主動(dòng)觸發(fā)的定時(shí)巡檢系統(tǒng)海渊,為了進(jìn)一步提升質(zhì)量,我們進(jìn)行了 前端巡檢系統(tǒng)的開發(fā)
系統(tǒng)現(xiàn)狀
- 系統(tǒng)是從8月初開發(fā),中旬上線的狸涌。運(yùn)行了1個(gè)月切省,通過不同組前端小伙伴之間的努力,線上已經(jīng)沒有標(biāo)紅報(bào)錯(cuò)帕胆,且在 請(qǐng)求數(shù)/大文件請(qǐng)求/白屏?xí)r間都有明顯提升朝捆。
- 對(duì)接測試/部署系統(tǒng)后,每次代碼發(fā)布都會(huì)執(zhí)行巡檢懒豹,為前端代碼部署提供了保障
項(xiàng)目主要npm依賴
-
puppeteer芙盘,googleChrome出品的無頭瀏覽器驯用,你可以像 控制木偶一樣,控制瀏覽器幫你打開頁面/填寫表單/在控制臺(tái)執(zhí)行腳本等等儒老,所以他的名字叫
puppeteer
- node-schedule蝴乔,nodeJs執(zhí)行定時(shí)任務(wù)/腳本的工具,詳細(xì)介紹
- pm2,大名鼎鼎的PM2,不管在win/mac/linux都能幫你守護(hù)nodeJs程序
-
koa驮樊,出接口對(duì)接 測試系統(tǒng)/對(duì)接系統(tǒng)用的薇正,當(dāng)然還有什么
koa-XXX/axios
一堆 - log4js,解決生產(chǎn)環(huán)境無法調(diào)試多記錄日志的工具
- mongodb,持久化數(shù)據(jù)使用囚衔,無論是巡檢記錄/log信息
- mongoose挖腰,優(yōu)雅的使用nodeJs鏈接mongodb
- shelljs,不用考慮兼容性练湿,直接寫shell的nodeJs工具
- standard猴仑,沒有規(guī)矩不成方圓,代碼規(guī)范還是需要的
- 釘釘群機(jī)器人肥哎,把定期結(jié)果/通知/報(bào)錯(cuò) 不同類型的消息即使發(fā)送給不同的群
主要實(shí)現(xiàn)
puppeteer在centos7上安裝有點(diǎn)費(fèi)勁
報(bào)錯(cuò):
...node_modules/puppeteer/.local-chromium/linux-496140/chrome-linux/chrome: error while loading shared libraries: libpangocairo-1.0.so.0: cannot open shared object file: No such file or directory
解決:
#依賴庫
yum install pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64 alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 -y
#字體
yum install ipa-gothic-fonts xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc -y
報(bào)錯(cuò)
:
(node:30559) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Failed to connect to chrome!
(node:30559) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
解決:
const browser = await puppeteer.launch({args: ['--no-sandbox', '--disable-setuid-sandbox']});
模擬移動(dòng)端設(shè)備 或者 設(shè)置UA - emulate - iphone為例
const puppeteer = require('puppeteer');
const devices = require('puppeteer/DeviceDescriptors');
const iPhone = devices['iPhone 6'];
puppeteer.launch().then(async browser => {
const page = await browser.newPage();
await page.emulate(iPhone);
await page.goto('https://www.google.com');
// other actions...
await browser.close();
});
設(shè)置瀏覽器分辨率 - setViewport
const puppeteer = require('puppeteer');
puppeteer.launch().then(async browser => {
const page = await browser.newPage();
await page.setViewport({
width: 1920,
height: 1080
})
await page.goto('https://www.google.com');
// other actions...
await browser.close();
});
URL列表 需要一次一次打開怎么處理
- 循環(huán)就好了辽俗,雖然耗時(shí)時(shí)間長,不過能減少 因?yàn)镃PU/內(nèi)存/網(wǎng)絡(luò)帶來的不穩(wěn)定因素
puppeteer核心代碼
const puppeteer = require('puppeteer')
const devices = require('puppeteer/DeviceDescriptors')
const iPhone = devices['iPhone 8']
const _platform = process.platform
const _conf = _platform === 'darwin1' ? {
headless: false
} : {
args: ['--no-sandbox', '--disable-setuid-sandbox']
}
module.exports = async function run (url, isMobile) {
return new Promise(async (resolve, reject) => {
const _arr = []
for (let i = 0; i < url.length; i++) {
await puppeteer.launch(_conf).then(async browser => {
const promises = []
const _url = url[i]
promises.push(browser.newPage().then(async page => {
if (isMobile) {
await page.emulate(iPhone)
} else {
await page.setViewport({
width: 1920,
height: 1080
})
await page.setUserAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36')
}
await page.goto(_url).catch(async error => {
// await page.close()
console.log(error)
})
await page.close()
}))
await Promise.all(promises).catch(e => {
console.log('---catch start---')
console.log(e)
console.log('---catch start---')
})
await browser.close()
})
}
resolve(_arr)
})
}
定時(shí)任務(wù)
const schedule = require('node-schedule')
const URL = require('../../config/j')
const run = require('./../service/p')
const Rule = new schedule.RecurrenceRule()
Rule.second = [10, 20, 30, 40, 50, 55]
schedule.scheduleJob(Rule, async function () {
site({
pageArr: URL(),
isMobile: 1
})
})
async function site (...params) {
await run(params[0].pageArr, params[0].isMobile).catch(e => {
console.log(e)
})
console.log('end')
}
URL列表
const router = [
'https://www.baidu.com/'篡诽,
'https://www.baidu.com/'
]
module.exports = function arr () {
return router
}
gitHub 簡易源碼
https://github.com/kyle920326/pupp
可以直接clone下來崖飘,參考查看
npm install
npm run dev
備注
koa,log4js,mongodb的部分留到以后再寫哈,先把主要實(shí)現(xiàn)記錄下