【第2134期】前端工程師是如何做「資損防控」的?

2021-02-20 前端早讀課

前言

U1S1就是」資損防控「所吸引的。今日前端早讀課文章由阿里@菉竹分享,由@居裡先生授權分享。

@石凱,花名菉竹,2017年碩士畢業於杭州電子科技大學,目前任職於阿里巴巴淘系技術部頻道與D2C智能組,主要負責營銷工具和資損防控工作

正文從這開始~~

資損 —— 顧名思義就是平臺發生了與用戶或客戶心理預期不符、直接或間接產生經濟損失的場景。

一直以來,資損問題就在我們的生產環境中不斷發生,而且隨著業務的規模和疆土不斷擴大,經濟損失的規模也在不斷擴大,這直接對平臺、客戶和用戶都產生了非常不良的影響。尤其在某一時間段連續發生高資損風險問題,惡劣程度上升到集團,對平臺的生產和運營產生很高的負面影響,所以大家高度重視資損風險的防控。

本文希望通過我們的思考以及淘系雙 11 的實踐為大家提供一些資損防控的經驗參考,也歡迎大家提出寶貴的意見。

探索之路

在資損防控方面,服務端比前端起步要早,而且做得也非常專業,比如各種離線或實時的容災冪等檢查、鏈路對帳告警、關鍵配置巡檢、關鍵標巡檢等等。

然而對於前端而言,阿里淘系技術部是從 2019 年雙 11 前夕開始才開始重視起前端資損防護問題,所以一年前並沒有沉澱什麼產品化方案,當時能採取的手段就是對案例的總結、對問題的定義、對程度的定級、對紅線的定論,通過一些規章制度、學習考試的手段來強化資損防控的文化意識,通過一些人肉盤點、case by case 的人工預演方式來規避資損風險保障業務的穩定。比如下文,就是人工預演這個很直接的土辦法的介紹。

人工預演

由於缺少產品化手段,去年的雙 11 、雙 12 等大促,前端採用的都是人肉盤點、人工預演的土辦法來做保障。我們分析了前端所有可能出現的資損風險點,並制定了一套前端的專屬資防規章制度和風險編碼表,並圍繞這些資損風險點,盤點所有參與雙11的業務前端代碼,對資損問題的識別、預防、止血和恢復過程進行詳細的人工預演。

印象中 2019 年雙 11,前端 C 端資損防控,總共進行 6 天,每天 2 場(下午與晚上),每場平均 3.5 小時,大概 4 位評委,共進行 73 例預演,每例預演大概 15 分鐘且至少 2 位預演者參與,耗費人力總成本均值在 200 小時(折算 25 人日),這個數字相比雙 11 整體的人力投入水平來說,也是非常恐怖的。

通過上述方式,過程中我們屬實提前發現了一些資損風險問題,雖然最後每場大促線上都沒有出現資損問題,但這個土辦法在過程中人力和時間消耗還是非常恐怖的,而且防控效果如何完全依賴當時現場的評委 review 的效果好壞。由此可見,人工預演這種方式不僅時間和人力成本過高,而且防護效果有限,並不適合作為長期的防控手段。所以,我們向前探索準備通過一些產品化的手段來解決防控效果和成本問題,就有了如下的一些嘗試。

前後端對帳

如上文所提,受人工預演方式的成本、防控效果限制,我們去年雙 12 之後開始嘗試資損防控的產品化方案設計。根據以往權益營銷活動出現過的資損案例來看,當消費者看到的權益信息與實際到帳的權益信息不一致時,容易引起大面積客戶投訴。譬如:

對於上述這類權益信息前臺展示和後端發放不一致的問題,及時的監控報警對於止血、控制資損規模至關重要。為此,我們針對類似問題為業務產品的生產階段設計了一套前後端對帳的產品化方案。

前後端對帳的整體思路如下:

對帳方案整體涉及採集層統一接入、數據實時處理對帳以及報警訂閱,具體如下:

接入層:前端封裝統一的 SDK ,覆蓋 web、weex 和 miniapp,在頁面端採集權益的關鍵信息;

數據層:基於 Blink 進行數據實時處理,存儲到 SLS 日誌以及 METAQ 消息,並通過後端平臺訂閱日誌消息進行實時對帳;

應用層:訂閱權益的對帳消息並打通實時報警流程,以及通過 SLS 日誌,查看權益的實時大盤以及模塊治理。

然而,項目上線一段時間後,我們發現效果並不如預期:

一方面,由於前端 SDK 對業務代碼是有一定侵入性的,所以各方業務在接入前後端對帳時,或多或少還是存在一定的成本。尤其是對一些穩定的線上老業務,反而容易在改造時引入新的問題;

另一方面,前端 SDK 採集的權益信息無法直接從 UI 展現層識別(金額可能被截斷),從報警情況來看,發現的問題均是各方的業務開發同學上報錯權益欄位而非真的前後端權益不一致導致的誤報。

從實際表現來看,我們原本期望用前後端對帳的方式能夠及時發現業務產品在生產階段中權益信息在前端表達和服務下發不一致的情況,然而這套方案由於前端拿不到 UI 的利益點欄位、問題發現率很低且存在一定接入成本等原因,並不能滿足我們的需求,我們只能繼續探索其他的資損防控手段。所以我們把目光聚焦到業務產品的研發階段,看看能否從產品的研發階段中探索出一些資損預防的產品化手段出來,所以就有了以下的嘗試。

靜態代碼掃描

在嘗試前後端對帳方案不足預期後,我們開始重新思考:人工預演的方式可以幫我們發現潛在的資損風險問題,但其主要問題在於需要投入大量人力和時間成本,那麼為什麼不想辦法降低這個成本呢?

為此,我們從代碼的 CcdeReview 過程中摸索出了一種 基於 AST(Abstract Syntax Tree,抽象語法樹)的前端代碼靜態掃描方案,可以在一定程度上規避金額計算、數字造假、數字歧義、文案過期等問題。這種機器替代人為 CodeReview 的方式,不僅省去了人力成本,而且還為 CR 的質量提供了一道基準保障。

靜態代碼掃描的整體方案思路如下:

其背後具體的原理介紹如下。

AST

在計算機科學中,抽象語法樹(Abstract Syntax Tree,AST)或簡稱語法樹(Syntax tree),是原始碼語法結構的一種抽象表示。它以樹狀的形式表現程式語言的語法結構,樹上的每個節點都表示原始碼中的一種結構。

這是摘自百科上對 AST 的一段解釋,我們再來看一個 code ⇌ AST 相互轉換的簡單示例:

如上所示,代碼片段var str = "hello world" 被拆解成了多個部分,最終以一棵樹的形式表示出來(如果想查看更多原始碼對應的 AST,可以使用神器 astexplorer(https://astexplorer.net/) 在線嘗試)。

代碼掃描的基礎正是建立在倉庫代碼的 AST 解析和遍歷之上的,為此,我們需要藉助 Babel 來完成這部分工作

Babel

Babel(https://babel.docschina.org/docs/en/) 其實是一個 JavaScript 編譯器,主要用於在舊的瀏覽器或環境中將 ECMAScript 2015+ 代碼轉換為向後兼容版本的 JavaScript 代碼。

簡單來說,為了將 ES2015+ 代碼轉換成向後兼容版本代碼(比如 ES5),Babel 每次都需要先將原始碼解析成 AST,然後修改 AST 使其符合 ES5 語法,最後再重新生成代碼。總結一下就是 3 個階段:

parse -> transform -> generate。

由上可以看到 Babel 不但完成了 AST 的解析工作,而且由於其編譯 js 代碼的使命,它還提供了一套完善的 visitor 插件機制用於擴展。有關 『如何自定義 Babel 插件』,可以查看這份 Babel 插件手冊(https://github.com/jamiebuilds/babel-handbook/blob/master/translations/zh-Hans/plugin-handbook.md)。根據手冊,我們就可以使用以下代碼添加自定義規則來完成代碼掃描任務:

const fs = require('fs');

const parser = require('@babel/parser');

const traverse = require('@babel/traverse').default;

// 編寫自定義規則插件

const visitor = {

// TODO:待添加

};

// 原始碼

const code = fs.readfilesync('your/file');

// code -> ast

const ast = parser.parse(code);

// 用自定義規則遍歷 ast (即代碼掃描)

traverse(ast, visitor);

自定義規則

介紹完 AST 和 Babel 後,我們再回到資損防控問題上來。根據以往的經驗來看,前端容易造成資損/輿情的代碼往往有:

金額賦默認值

金額計算

數字造假、固定金額/積分

過期時效文案 …

因此,我們就可以根據上述這些 case 自定義規則來編寫 Babel 插件。就拿 『金額賦默認值』 為例,我們可以列舉日常代碼中的一些 bad cases,然後使用 astexplorer 分析其 AST,最後再針對性地編寫匹配規則即可。

// 金額賦默認值 bad cases

// case 1: 直接賦默認值

const price = 10;

// case 2: ES6解構語法賦默認值

const {price = 10} = data;

// case 3: "||"運算符賦默認值

const price = data.price || 10;

// ...

case 1: 直接賦默認值

根據上面的 code vs AST 關係圖可以看到,我們只要找到 VariableDeclarator 節點,且同時滿足 id 是金額變量,init 是大於 0 的數值節點這兩個條件即可。代碼如下:

const t = require('@babel/types');

const visitor = {

VariableDeclarator(path) {

const {id, init} = path.node;

if(

t.isIdentifer(id) &&

isPrice(id.name) &&

t.isNumericLiteral(init) &&

init.value > 0

) {

// 直接賦默認值 匹配成功!

}

}

};

case 2: ES6解構語法賦默認值

觀察上面的關係圖,我們可以得出結論:找到 AssignmentPattern 節點,且同時滿足 left 是金額變量,right 是大於 0 的數值節點這兩個條件。代碼如下:

const t = require('@babel/types');

const visitor = {

VariableDeclarator(path) {

const {id, init} = path.node;

if(

t.isIdentifer(id) &&

isPrice(id.name) &&

t.isNumericLiteral(init) &&

init.value > 0

) {

// 直接賦默認值 匹配成功!

}

}

};

case 3: "||"運算符賦默認值

上圖的規則同樣也不複雜,但需要注意一點:實際代碼中,= 右側的賦值表達式可能會複雜的多,甚至包含了一些邏輯運算。因此,我們需要改變策略:遍歷右側的賦值表達式中是否包含 "|| 正數" 的模式。代碼如下:

const t = require('@babel/types');

const visitor = {

VariableDeclarator(path) {

const {id, init} = path.node;

if(t.isIdentifer(id) && isPrice(id.name)) {

path.traverse({

LogicalExpression(subPath) {

const {operator, right} = subPath.node;

if(

operator === '||' &&

t.isNumericLiteral(right) &&

right.value > 0

) {

// "||"運算符賦默認值 匹配成功!

}

}

});

}

}

};

通過上述的3個例子,我們就已經能把絕大部分 『金額賦默認值』 的代碼給掃描出來。其他的一些場景也是如此,只要根據代碼生成的 AST 找到規律,然後編寫對應的 Babel 插件即可。

小結

然而,靜態代碼掃描工具雖然能夠幫助我們從代碼層面上發現一些共性問題,但面對不同的業務邏輯仍然是沒有感知的,以至於不容易挖掘出代碼中深層次的問題。因此,在面對 UI、多態、複雜交互邏輯等場景時,純靠靜態代碼掃描不足以完全解決問題。所以在第一道防護工序之後,我們又設計了第二道防護工序,具體介紹如下。

UI 測試掃描

根據以往發生的資損故障來看,問題往往多發生在代碼變更時,開發同學的新改動影響到了業務的原有功能,而測試同學又恰好沒有回歸到這點。對測試同學而言,業務每次的全量回歸工作量是巨大且重複的。就拿領取紅包的例子來說,不同的帳號(人群)、領取成功、網絡超時、重複領取、沒有資格、服務故障等等都是資損通常需要考慮在內的測試用例。此時,如果能有一個 UI 自動化回歸測試工具,既能為業務提供一個保障,又能解放測試同學。然而,傳統的 UI 自動化測試需要開發同學編寫對應的自動化測試代碼,不但有上手成本,而且還造成了額外的工作負擔。

為此,我們又提出一種 基於錄製/回放的 UI 測試掃描方案:開發/測試同學只需提供一個可正常訪問的頁面地址,正常的功能測試錄成測試用例,在項目發布的時候就會進行一次頁面回放,最後再通過 UI 測試用例快照比對的方式判定本次功能回歸是否通過。

UI 測試掃描的整體思路如下:

其背後的原理介紹如下。

頁面代理

代理頁面本質是一個 web 服務,它通過 url 參數方式接收原始頁面連結和注入腳本地址,由伺服器請求原始頁面返回對應的 html 文檔,並且在返回文檔頭部注入接口攔截腳本、調試工具腳本以及url參數中取得的自定義注入腳本。代理頁面擁有和原始頁一樣的 html ,同時也會添加上原始頁的 query 參數,直接訪問代理頁除了 js 的 location 變量,其他環境和原頁面相差無幾。至於 location 變量,試了很多方案,發現都改寫不了,一重寫頁面就跳轉,多次嘗試無果後我們發現可以換個思路解這個問題,既然重寫不了我們就替換掉它,我們將頁面所有的 script 腳本包了一層 with,如下圖所示,我們將頁面內所有的js腳本的上下文改寫,使之讀取的 location 是被我們重寫的,從而達到代理頁的渲染運行結果和原始頁一致的效果。

with({ location: $proxyLocation }) {

// js code

// ...

}

錄製腳本

通過上述的頁面代理,我們就可以在訪問原頁面的時候注入我們的錄製腳本。為了能夠支持頁面的回放,錄製的時候就要提供兩份數據:

錄製期間產生的所有網絡訪問數據

用戶操作數據(包括點擊、滾動等)

要想記錄網絡訪問的數據並不難,此處不展開多述,可以借用 AOP 的思想,在網絡請求的回調中增加一個 interceptor ,同時保存下本次請求的 url,param,response,以便回放的時候匹配使用。

再來看下又該如何劫持用戶的操作數據,其實在 h5 頁面中,用戶的任何觸摸操作都會依次觸發 onTouchStart、onTouchMove、onTouchEnd 事件,所以我們只需攔截這三個事件對應的 targetEvent 參數即可。就拿攔截 onTouchStart 為例:

document.addEventListener('touchstart', (evt) => {

const touch = _.get(evt, 'targetTouches.0', {});

const selector = DomUtils.getSelector(evt.target);

if(shouldHijack(selector)) {

const now = Date.now();

touchQueue.push({

selector,

scrollTop,

timestamp: now,

action: 'touchstart',

position: {

pageX: touch.pageX,

pageY: touch.pageY + this.getScrollTop(),

}

});

this.lastAction = 'touchStart';

}

});

如上可以看到,我們記錄下了觸發事件的事件類型、節點選擇器、時間戳、頁面距離頂部高度以及坐標位置等信息,這些都是回放時必不可少的數據。

再來看頁面的滾動攔截,只要劫持 onScroll 事件即可。不過這裡需要注意一點,頁面滾動分兩種:手指接觸屏幕時的拖動,手指離開屏幕後的慣性滾動。前者會同時觸發 onTouchMove 和 onScroll,而後者只會觸發 onScroll。

document.addEventListener('scroll', (evt) => {

if(!this.isRecording || this.lastAction === 'touchmove') return;

this.touchQueue.push({

action: 'scroll',

timestamp: Date.now(),

scrollTop: this.getScrollTop(),

});

this.lastAction = 'scroll';

};

回放腳本

回放腳本同樣依賴代理頁面的注入能力,但做的事剛好和錄製腳本相反:

攔截請求,使用錄製時記錄的網絡數據 mock

按照時序依次派發 touchEvent 事件

類似地,攔截請求和錄製時的原理大體一致,只需根據本次請求的請求參數從錄製時攔截的數據中找到對應的匹配即可。

再來看下如何根據時序派發 touchEvent 事件來模擬回放,核心代碼如下:

let isPlaying = false;

async function replay() {

isPlaying = true;

const {touchQueue = []} = await load('recordData');

while(isPlaying && touchQueue.length > 0) {

const item = touchQueue.shift();

const {action, delayTime, scrollTop} = item;

await sleep(delayTime);

setScrollTop(scrollTop);

if(action !== 'scroll') {

dispatchEvent(item);

}

}

}

派發事件是基於 dom 的 dispatchEvent 方法,可以參考 [MDN(https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent) 文檔,代碼如下:

function dispatchEvent(info) {

const {selector, action, position: {pageX, pageY}} = info;

// 模擬事件觸發(touchstart, touchmove, touchend)

const element = document.querySelector(selector);

if(!element) {

console.warn(`element with selector ${selector} not found`);

return;

}

const touchObj = new Touch({

identifier: Date.now(),

target: element,

clientX: pageX,

clientY: pageY,

pageX: pageX,

pageY: pageY,

radiusX: 2.5,

radiusY: 2.5,

rotationAngle: 10,

force: 0.5,

});

const touchEvent = new TouchEvent(action, {

bubbles: true,

shiftKey: true,

cancelable: true,

touches: [touchObj],

targetTouches: [touchObj],

changedTouches: [touchObj],

});

element.dispatchEvent(touchEvent);

}

快照對比難點分析

根據前文的介紹,我們已經可以分別拿到錄製和回放的最後一幀快照,所以接下來我們就希望設計出一套算法對這兩個快照做內容一致性的自動化判斷。從不同的輸入案例來看,我們主要面臨以下的幾個難點:

相同文字在不同型號的手機上會有不同的字體字號顯示,像素級比對會將相同文字誤判為不一致。

對於紅包等彈層圖片,只需關注紅包彈層信息是否一致,無關的背景會導致模型誤判。

由於回放/錄製在時間戳上無法保證嚴格一致性,兩張快照往往存在位置上的位移偏差。

算法設計

整體的算法流程如下圖所示,下面我們分步驟闡述算法思路。

首先對兩張快照計算 SIFT 相似度進行初篩。匹配的核心問題是將同一目標在不同時間、不同解析度、不同光照、不同方向的情況下所成的像對應起來。圖像的局部特徵,對旋轉、尺度縮放、亮度變化保持不變,對視角變化、仿射變換、噪聲也保持一定程度的穩定性。相似度低於閾值的兩張快照判為不通過,通過快照會做進一步精細比對。

針對彈層圖片,需要預先對背景等無關信息做去除,僅保留彈層信息。這邊先將圖片從 RGB 空間轉換成 LUV 空間。L 分量會保留圖片的亮度信息,便於根據亮度值二值化圖片,去除無效背景,效果如下。

將預處理好的乾淨圖片送到 OCR(光學字符識別) 模型,提取出文字內容及相對應的坐標信息。針對像素過小的文字信息進行刪除,往往是噪聲產生的錯誤信息。

按照返回的坐標信息進行文字的位置還原,方便下一步做內容比對。

由上一步產出的結果進行內容比對,在圖上標註出兩張快照不一致的地方作為輸出,算法結束。

效果演示

不通過:

通過:

小結

誠然,我們通過 UI 掃描工具改變了傳統編寫 UI 測試代碼的方式,測試同學只需在功能測試的時候順便錄製一份測試用例即可,這不但降低了測試同學的自動化的學習成本和回歸的時間成本,而且還為每次業務的發布提供了一道自動化回歸保障。不過,在本次雙 11 前端資防工作實際落地中,我們仍然遇到了一些問題:

UI 測試掃描目前暫時只支持 h5,還不兼容淘系內的其他一些前端技術棧(比如 weex、直播、小程序等),導致這些業務仍然只能通過人工 review 的方式保障;

我們雖然對快照對比的算法進行了優化,但在實際應用中仍遇到一些由於算法判斷不準導致誤判的情況。因此,我們還將繼續優化快照對比算法,進一步提升判斷的準確度。

目前的快照對比只校驗了錄製和回放的最後一幀(即最終狀態),大量的中間狀態信息沒有被利用起來,從而丟失了過程的校驗。因此,後續我們將考慮引入視頻的對比算法,達到真正的錄製/回放全對比。

基於目前的頁面代理機制,錄製功能只支持當前頁的操作錄製,對於頁面跳轉類的測試用例還無法覆蓋。因此,我們接下來也將繼續升級頁面代理和錄製/回放腳本,支持鏈路層面的測試用例覆蓋。

以上遇到的這些問題均是我們接下來繼續重點突破的挑戰。

總結與展望

如前文所述,淘系的前端資防工作一年內悄然變化著,從最初的人工預演到目前的三道遞進式的產品化防控手段:

【已產品化】針對可以在代碼級別靜態掃描分析出來的資損風險問題,做了第一道產品化防控手段——資損/輿情風險代碼掃描工具;

【已產品化】針對 UI、多態、複雜交互邏輯等不能從代碼級別分析出來的資損風險問題,與測試團隊合作做了第二道產品化防控手段——資損/輿情風險 UI 測試掃描,通過 UI 測試用例快照比對預防資損風險;

【兜底方案】針對上述產品化手段不能覆蓋的特殊場景,暫時先依賴人工預演作為兜底防護方案。

相比於去年的雙 11 資防工作,今年我們依靠上述方案甚至取消了人工預演的環節。預演者也從去年需要準備相關文檔(如止血方案、預案等)變成今年錄製 UI 測試用例,其中需要準備的時間成本幾乎打平,但大大節省了預演的參會時間;除此之外,預防效果也因其範圍更聚焦、防護組合更全面,要比去年效果更佳。當然了,目前的這些方案都還只是預防手段,無法百分之百保障線上不會發生資損故障,每個人對於資防的態度仍不能掉以輕心。

在接下來的工作中,考慮到目前的資防方案僅能做代碼缺陷方面的預防,產品設計、運營配置等方向還沒有實質性的防控方法,所以後續我們將在構思鏈路級別的、生產環境以及運營環境上的防控手段,建設一些告警和自動止血機制為平臺保駕護航。

關於本文作者:@菉竹原文:https://mp.weixin.qq.com/s/ZKtS47uOtjEHdEjKw0Y-uQ

為你推薦

【第2130期】前端元編程——使用註解加速你的前端開發

【第2118期】前端安全生產在ICBU的探索與落地

歡迎自薦投稿,前端早讀課等你來

相關焦點

  • 寫給想成為前端工程師的同學們―前端工程師是做什麼的?
    前端工程師是網際網路時代軟體產品研發中不可缺少的一種專業研發角色。不僅僅是前端改來改去,PHP服務端做業務的同學也面臨這樣的問題,業務邏輯改來改去。越底層通用性越強,改動相對較少。不過事情都是有兩面性的,首先可以這麼想想,是底層基礎服務的市場大還是網際網路業務和產品的市場大。其次,基礎服務的通用性很容易達成,而產品層面上如何通用化,如何在業務驅動的產品研發中利用工程化和工具化提升開發效率,這其實是一個很難的問題。
  • 4982億背後的前端技術—2020天貓雙11前端體系大揭秘
    即是業務上新的嘗試,在技術上也要解決架構選型、對帳、一致性表達、排期等問題。做好本職首先要做的就是做好本職工作,保障需求研發和穩定性。需求研發方面,我們通過D2C實現了大部分UI模塊自動開發、通過建設Eva互動體系降低互動研發成本、通過Serverless的一體化研發提升研發和運維效率,使前端不再成為資源瓶頸。
  • 如何規劃HTML5前端工程師職業發展路線?
    在學習前端之前,我們需要先思考我們要成為一個什麼樣前端工程師。接下來我們以時間線的方式,來告訴我們什麼時間該做什麼事兒。本文以普通人為例,也是想給普通人一些思路,結合自己的情況走出自己的路,超人請自行退出。
  • 母雞與前端工程師
    來自:阮一峰的網絡日誌作者:阮一峰原載2016年第29隻要你會做網頁,尤其是手機App的頁面,或者微信的活動頁面,就不愁找不到工作。哪怕你剛剛學會幾個月,或者剛從培訓班畢業,只要能拿出作品,就會有比其他行業高得多的起薪。等到有了一兩年工作經驗,工資就可以達到大學教授的水平。這樣的就業行情,怎不令人趨之若騖。儘管每年都有好幾萬新人加入,網際網路公司還是在喊,工程師嚴重短缺。
  • 如何成為一名卓越的前端工程師
    最近我收到一封讀者來信讓我陷入了思考,信是這麼寫的:Hi Philip,您是否介意我問您是如何成為一名卓越 (great) 的前端工程師的?對此您有什麼建議嗎?我不得不承認,我很驚訝被問這樣的問題,因為我從來不覺得自己是個很卓越的前端工程師。甚至我入行頭幾年時並不認為自己可以做好這一行。我只確定自己比自己想像中還才疏學淺,而且大家面試我的時候都不知道從何問起。
  • 前端工程師憑什麼這麼值錢?
    【CSDN編者按】前端工程師的薪資之高是業界公認的事實,但是很多人會質疑前端工程師,認為他們並不能稱為軟體工程師,也「配不上」高昂的報酬。本文的作者分享了自己從一個前端菜鳥成長為一個10人前端團隊主管的從業經歷,並表示,前端人員的技術特性就是很值錢!以下為譯文:我第一次通過軟體賺錢是在2008年。
  • 一名合格前端工程師的進階指南!
    所以,應用前端工程化的項目,往往能夠更好地規避風險,分散流程壓力,降低開發難度。3. 更易獲得面試官青睞前端的崗位技能已經發生深刻的變化。有人甚至戲言成前端工程師為前端配置工程師。fouber(張雲龍)曾經在自己的博文中說:「前端是一種技術問題較少、工程問題較多的軟體開發領域。」
  • Web前端工程師具體是做什麼的?發展好嗎?
    關於Web前端都有這些問題吧Web前端工程師是做什麼的?現在發展前景怎麼樣?零基礎學習難嗎?發展好嗎?這是很多想了解Web前端的人員都關心的。Web前端工程師具體是做什麼的Web前端工程師是做什麼的?Web前端工程師具體是做什麼的懂用戶UI交互,也懂網站SEO;會開發、會調試、會後臺開發語音、精通開發工具。配合後臺開發人員實現產品界面和功能,完成表現層及前後端交互的架構設計和開發。
  • 前端開發工程師的工作內容是什麼?
    隨著Internet的發展和多個終端的普及,前端開發工程師逐漸受到歡迎,但是前端開發工程師的具體工作內容是什麼?大多數人對此知之甚少,前端開發工程師是在近幾年才開始受到各大企業的重視,那麼,前端開發工程師到底是做什麼的?下面編輯帶大家認識下!一.什麼是HTML5前端開發?
  • 如何成為一名優秀的前端開發工程師
    前端工程師是軟體團隊重要的組成部分,不論是傳統的Web開發團隊、移動互聯開發團隊還是大數據開發團隊,都離不開前端工程師,可以說隨著目前軟體應用場景的增加,前端工程師也越來越重要,前端開發的邊界也在不斷獲得突破,形成了包含Web前端、移動端、小程序和部分後端開發任務的「大前端」生態。
  • 為什麼前端工程師薪資越來越高?
    我們再從兩個方面分析:前端到底是做什麼的呢?首先是掌握JavaScript、HTML+css,這是前端最基礎的要求;其次是學習css3+html5,當今網際網路行業,也越來越注重網站的美觀性和易用性;最後是學習後臺語言。
  • web前端開發工程師的三種級別
    隨著信息技術不斷發展,前端技術的發展也經歷了不同的階段。前端概念隨著移動智慧型手機的普及被正式提出,混合APP開始被廣泛開發。近年來,由於前端技術開始實現工程化,一些企業前端開發任務逐漸向後端拓展,邏輯思維能力也逐漸成為前端開發人員必備的能力。
  • 做好這些,下一個年薪30萬的前端工程師就是你!
    對於很多前端工程師來說,很容易進入工作的舒適區,該熟悉的業務已經熟悉了,然後就是重複用輪子。殊不知,這樣很容易讓自己的成長處於原地打轉,以及低水平重複的狀態,自然無法成長,也就無法高薪。2020年,前端工程師該如何高薪成長?
  • 前端工程師,還在學習那些永無止盡的框架麼?
    關於這個問題,我曾經和前手機淘寶前端負責人 winter 聊過,他曾經帶過幾十人的前端團隊,也非常熱衷於工程師的培養,對前端工程師成長有很獨到的理解。對於前端來說,winter 認為不過時的技能還是一個工程師的「內功」,對應不同級別的前端工程師來說,需要具備的核心技能也不太相同。
  • 聊聊前端工程師的職業規劃
    問起這個,也就根據自己的經歷發表一下對前端工程師的看法吧,「我說的都是錯的」,僅供參考。從我接收第一份前端需求開始,到現在也有五個年頭了。自己也從一個愣頭青變成一個快到而立之年的大叔,時間真的是譁啦譁啦的快。這五年裡,其實可以分成三部分:1~2,3~4,5。1~2 吸吸吸,瘋狂的吸取知識剛畢業時滿腔熱情,一門心思只往前端事業發展。
  • 想成為一名web前端開發工程師,培訓和自學如何選擇
    對於編程人員來說,對前端樣式的要求就肯定越來越高,Web前端工作也變得越來越重要。很多人想要學習Web前端技術,成為一名Web前端工程師,web前端技術吸引著很多小夥伴想去學習,但是如何學習web前端技術,是報名web培訓班學習還是自學好呢?今天和大家一起探討一下:
  • 前端工程師面試題匯總
    如何兼容低版本的IE?視差滾動效果,如何給每頁做不同的動畫?(回到頂部,向下滑動要再次出現,和只出現一次分別怎麼做?)::before 和 :after中雙冒號和單冒號 有什麼區別?解釋一下這2個偽元素的作用。如何修改chrome記住密碼後自動填充表單的黃色背景 ?你對line-height是如何理解的?
  • 前端工程師的進階之路
    又或者是網頁重構工程師,JS工程師,UI/UX,切圖仔等等。那麼歸根這些都是為前端服務的,說了這麼多,那麼前端的價值到底在哪裡呢?前端的價值在哪呢?第一點是前端的本職工作,是在功能上和後端的主要區分,也是前端崗位存在的原因。
  • 為什麼2017年Web前端開發工程師薪資越來越高?
    所以在供不應求的前端招聘市場上,優秀的前端工程師才是有話語權的那一方。前端開發是做什麼的?前端是網際網路時代軟體產品研發中不可缺少的一種專業研發角色。從狹義上講,前端工程師使用 HTML、CSS、JavaScript 等專業技能和工具將產品UI設計稿實現成網站產品,涵蓋用戶PC端、移動端網頁,處理視覺和交互問題。
  • 前端工程師面臨巨大危機,前端真的會被淘汰嗎?看看大咖們怎麼說
    事情起因是這樣子的,有團隊做了一款可以直接生成網頁的手機APP發布了。某知友就慌亂了,覺得前端工程師會被AI所取代,開始糾結學習前端還是後端。「手機APP可以直接生成網頁,取代了前端工程師的一部分工作,隨著APP的進一步開發使用,前端開發的行業空間將更加狹小,是不是就意味著,前端開發正面臨著被淘汰的局面?」前端真的會被取代嗎?答案是否定的。