時光如梭,白駒過隙,2019年轉瞬即逝。這一年對於 PLUS 會員項目前端同窗來講是坎坷和充實的,如白巖鬆所說,痛並快樂着。回首望去,異業合做權益的陸續接入,6.18大促和雙11活動的需求扎堆,中間穿插部分機型首屏白頁等問題的困擾,在一陣慌亂以後,咱們逐漸穩住了陣腳。在完成平常需求的同時,基於原有框架,對項目的穩定性、加載、體驗、開發效率等方面作了更多夯實。javascript
2019年,累計支持了近90多個大小需求。主要分爲四類:產品升級、異業合做、促銷活動、緊急需求。在這些需求中包含了經典卡新增用戶權益的需求,如健康、讀書、快遞券、95折商品權益。也大大擴展了和其餘異業的聯合,如騰訊視頻、攜程旅遊、酷狗音樂等。此外還有研發側發起的性能優化、用戶體驗優化等。css
PLUS 會員項目橫跨三個職場,研發和項目側在北京(2處職場),產品在上海團隊。溝通顯得尤其重要,任何一個微小的問題,均可能在用戶中被放大,每一次操做上線都需當心謹慎,如履薄冰。html
項目功能複雜,狀態繁瑣,業務邏輯經常內含玄機,一個改動有可能會影響數十個狀態,牽一髮而動全身。整頁紙都容不下一個彈窗的交互邏輯,改一處而崩所有。此外,時常並行十來個需求,每週須要數次合併功能上線,還有那不得不說的恐怖魔咒:上線頻繁通宵~~~前端
然而,破繭成蝶,涅槃重生,哪個不是須要痛到極致以後才能獲得昇華。在經歷了瘋狂的成長以後,PLUS 會員項目像個橫衝直撞的孩子,咱們決心從新梳理,改變現狀,讓他健康成長。本文將從性能優化,開發效率,流程優化這三個方面闡述,如圖所示:vue
首先請容許我簡單介紹下 PLUS,京東爲向核心客戶提供更優質的購物體驗,特別推出京東 PLUS 會員,包含十幾項權益:java
更多權益就不贅述了,更多 戳這裏node
此外,購買京東 PLUS 會員聯名卡,就擁有了兩個以上的會員權益,噓~ 低調,畢竟你們都是有會員身份的人~~webpack
孩子:媽媽,我想買京東 PLUS 會員~ 媽媽:買,買個聯名卡,一個頂兩個,夠不夠? 孩子:夠了,謝謝媽媽,媽媽真好!git
接下來就帶你們看一下 PLUS 會員部分頁面的廬山真面目吧:github
OK,廣告結束,下面進入正題。
PLUS 會員項目 18 年開始選用 Vue 技術棧,使用了團隊自行開發的 Gaea 構建工具和 NutUI 組件庫,此外引入了 Carefree,SMock,Vuex,TS,PWA等。
Gaea構建工具 ,是咱們團隊自主開發的一套 Vue 技術棧構建工具,基於 Node.js、Webpack 模版工程等的 Vue 技術棧的整套解決方案,包含了開發、調試、打包上線完整的工做流程。極大的提升了工做效率,目前團隊全部 Vue 業務都使用該腳手架。
NutUI組件庫 ,是一套京東風格的輕量級移動端 Vue 組件庫,由咱們團隊歷時數年打磨,目前有30+京東移動端項目使用,github上獲得1.5k+的star。該 Vue 組件庫提供大量的可複用的 Vue 基礎組件,極大的便利了 PLUS 項目的開發。
Carefree ,一套不依賴 wifi 熱點的移動 web 真機測試一站式解決方案,是咱們團隊在平常開發中發現真機很依賴電腦發出熱點才能進行調試的痛點,針對這一問題,旨在擺脫wifi熱點束縛,讓移動web真機測試自由自在而自主研發的一套解決方案。
SMock ,由團隊自主研發,針對項目前期尚無數據的問題,分析須要 mock 的文檔,輸出相應的 mock 數據,並啓動 node 服務,供前端開發時調試使用,提升前端開發效率,支持跨域訪問。
此外,咱們引入了 Vuex 作狀態管理,PWA 作數據緩存和離線應用,也嘗試使用 TypeScript 語言開發。
提升頁面渲染性能,改善用戶體驗,是團隊一直重視的方向。首頁已經使用了不少方法來優化性能,包括使用骨架屏減小用戶等待體驗、核心數據直接出以此減小請求接口時間,樓層內部滾動懶加載,使用 Webp 縮小圖片大小等等。因此一開始咱們猶如站在巨人的肩膀上,一動不動,生怕一不當心失足掉下去~~~
事情的原由,是在半年前,頁面卡死白屏問題會時不時的冒出來,像個幽靈同樣困擾着咱們。並且是隨機偶然出現的,幾千萬用戶中總會有幾部手機被幸運之神選中————讓其出現白屏、卡死、氣的拿手機砸牆!但是一樣的手機、一樣的配置、一樣的 APP 版本,在咱們這邊卻老是安然無恙。在此期間咱們嘗試了不少方法排查,好比
因而茶不思飯不想,百思不得其解。這難道是量子力學中薛定諤的貓?事物最後變化的結果是根據人爲觀測而變化的?那解決後是否是能夠得到下一屆的諾貝爾物理學獎呢?想一想忽然還有點小激動呢...
好在皇天不負有心人,在切換了多種網速,模擬各類環境的嘗試下,發如今頁面卡死的狀況下,每每會上報一個錯誤,就是依賴的變量沒有定義致使的。
咱們知道基於 Webpack 腳手架和 Vue 框架開發的項目,會打包生成一個依賴 JS 文件,一個業務 JS 文件。爲了便於上線,當時採用動態生成靜態資源的連接。而瀏覽器每每會並行下載多個外部靜態資源,若是業務 JS 文件一旦先於依賴 JS 文件執行,則找不到依賴變量,結局只有一個:那就是頁面卡死!
好了,真兇既然已經鎖定,接下來就是如何修改了,鑑於動態生成靜態資源外鏈有可能致使 JS 執行順序的不肯定,咱們又改回成了 Webpack 打包自動注入靜態資源連接的形式。然而,事情真的就這麼結束了嗎?
果真,以後白屏像幽靈同樣,依然偶現!雖然比以前少了一些客訴,但仍然會不時的零星出現幾例。而且隨着時間的推移,需求愈來愈多,每次都要並行開發不少個需求。爲了並行開發代碼不衝突,以及避免每次上線時客戶端緩存舊文件,因此每次上線都是使用新版本號的文件。可是這樣致使即便改動一點代碼,也要前端、後端一塊兒上線,在快速迭代需求的狀況下,每次改動都要後端研發修改十幾個靜態資源的版本號,前、後端研發不堪其擾。因而咱們決定使用公司的頭尾系統,把靜態資源的路徑放在頭尾系統中,每次上線新文件後,前端推送頭尾,一鍵部署靜態資源到各個服務器。然而好事多磨,因爲維護多個頁面,每一個頁面對應兩個靜態文件:一個是 JS 文件,一個是 CSS 文件,分別放在<body>
的尾部和<head>
之中。致使每次改動頭尾文件都要涉及到十幾個文件的修改(哎,好想念當年後端同窗幫忙修改版本號的日子~),維護成本劇增,且隨着頁面的增多,這一現象有增無減;
此外,爲了緩解用戶在等待頁面渲染中的焦急心情,早已經在返回的 HTML 中增長了骨架屏。然而遺憾的是,咱們發如今 IOS 系統中骨架屏並不會出現,而是直接呈現出最終渲染的頁面。
基於解決以上問題,咱們沒有像碰見危險就把頭埋進沙子中的鴕鳥同樣逃避,而是決定主動優化,去啃下這個硬骨頭!
常規的瀏覽器渲染機制,客戶端從服務器請求回 HTML 以後,HTML 解析器就會從 HTML 文件的頭部到尾部,一個個地遍歷這些節點。當這些節點是普通節點的話,HTML 解析器就會將這些節點加入到 DOM 樹中。當這些節點是 JS 代碼的話,HTML 解析器就會將控制權交給 JS 解析器。若是這些節點是 CSS 代碼的話,HTML 解析器就會將控制權交給 CSS 解析器。不過,當外聯的 JS 代碼和 CSS 代碼還沒從服務器傳到瀏覽器的時候,這個時候若是 DOM 樹上有可視元素的話,瀏覽器一般會選擇在這個時候,將一些內容提早渲染到屏幕上來。可是問題就在於 IOS 系統中的 WebView 並無將首屏直出的這部分 HTML 頁面顯示出來。HTML 中直出的 DOM 結構會等待外部 CSS 和 JS 加載執行後才統一進行渲染。
爲了驗證這一猜測,咱們能夠把 HTML 代碼化簡到最少的代碼:只掛載元素中放置一個紅色 div,在其外面放一個綠色 div。
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0,viewport-fit=cover" name="viewport">
<title>PLUS會員</title>
<link rel="stylesheet" type="text/css" href="//static.360buyimg.com/exploit/mplus/4.3.2/v4/css/index.css">
<script>document.documentElement.style.fontSize = 320 / 7.5 + "px"</script>
</head>
<body>
<div id="app">
<div style="width:100%;height: 200px;background:red;"></div>
</div>
<div style="width: 100%;height: 200px;background:green;"></div>
<script type="text/javascript" src="//static.360buyimg.com/exploit/mplus/lib/4.1/vendor.dll.js"></script>
<script type="text/javascript" src="//static.360buyimg.com/exploit/mplus/4.3.2/v4/js/index.js"></script>
</body>
</html>複製代碼
而後在IOS系統中效果以下圖所示:
能夠看到,因爲紅色 div 位於掛載元素之中,直接被生成的 Vue 頁面替換掉了;綠色 div 是和 Vue 頁面一塊兒渲染出來,因爲完整的頁面須要調用不少接口判斷,因此顯示的稍晚。可是不管哪個 div 都是在 Vue 最初的頁面渲染前不會顯示的。
那麼 IOS 端的骨架屏面臨着同樣的境遇,若是放在掛載元素裏面,根本不會顯示;若是放在掛載元素外面,就會和 Vue 渲染頁面同時出現,也就失去了骨架屏的意義。
爲了不使用外部下載 CSS 和 JS,致使 IOS 系統影響首屏直出骨架屏的渲染,仍要採用待骨架屏加載完以後,再去動態引入 JS 和 CSS,因爲首頁骨架屏的代碼量自己並不大,待其加載後再去動態引入靜態資源,時間影響不大(後面有實驗數據)。可是又回到了第一階段中,動態生成靜態資源致使的 JS 執行順序問題。
因此,繞了一圈,無解,劇終~
等等,開玩笑,此可輕易言敗!通過屢次的嘗試,咱們採用了引入事件監聽的方法,核心思想是待依賴文件都加載完以後,再去執行業務代碼。 好處是:
在此過程當中須要注意:
var oFragment = document.createDocumentFragment();
var indexScript1 = document.createElement('script');
var indexScript2= document.createElement('script');
oFragment.appendChild(indexScript1);
oFragment.appendChild(indexScript2);
body.appendChild(oFragment);複製代碼
<script type="text/javascript">
var staticVersion = 'dev';
</script>
<script type="text/javascript">
//頭尾系統的版本號,從新定義 staticVersion
var staticVersion = '1.0.0';
</script>
<script type="text/javascript">
window.onload = function(){
if(staticVersion != 'dev'){
//動態生成代碼
}
}
</script>複製代碼
通過實驗,在正常網絡狀況下,IOS系統中頁面雖然渲染平均慢了 266ms,可是骨架屏再也不等待 CSS 和 JS 的加載,提早了1000ms左右出現。在弱網狀況下,頁面渲染時間相差無幾,骨架屏依然能夠在 HTML 返回後快速渲染出來。
解決了如下問題:
頁面樓層懶加載,可以頗有效的提升首頁加載速度,減小沒必要要的請求。在 PLUS 會員首頁中,底部長長的商品樓層非常符合懶加載的條件,用戶並不會在進來的時候看到商品樓層。在以前的項目中,每次滑動商品樓層只請求一頁的數據,減小沒必要要的請求和渲染。可是還有待優化空間,若是用戶的手機首屏並無顯示商品樓層,咱們就不須要在剛進來就加載該部分的 JS 代碼。再來看這個文件的大小,線上通過壓縮後的 JS 文件 11.7k,CSS 大小16.8k,加起來總共有 28.3k 了,這樣看來已經不小了。
爲了進一步減小首頁沒必要要的加載,咱們使用了 Vue-lazyload 插件,來實現組件的懶加載功能,而且使用預加載技術,讓瀏覽器空閒時間先把該文件下載下來,避免用戶滑動到商品樓測纔去下載對應的靜態資源。
基於 webpack 的 @babel/plugin-syntax-dynamic-import
和 Vue-lazyload 插件很容易實現異步加載代碼的獨立打包。
尤爲注意頁面中處於該商品樓層上面的區域,若是沒有固定高度的樓層,必定要保證渲染完成後,再去觸發計算商品樓層的是否在可視區域內。最終懶加載組件曝光後,再去加載商品樓層。記得取消 network 面板中的 Disable cache,效果以下:
能夠看到效果,頁面商品樓層纔去加載floor-feeds.js 文件,而且已經有了預加載,因此從緩存中獲取,時間爲2ms。
如上圖所示,在小屏手機下,進入頁面並不會加載 floor-feeds.js,只有在頁面往下滑動時,纔會從預加載 Prefetch 中加載該文件。 最後兼顧一下用戶體驗和性能,在大屏手機下的商品樓層,在首屏下面呼之欲出,此時設置懶加載功能意義不大,由於用戶稍微滑動一下屏幕,就會露出商品樓層,而且渲染商品樓層也須要時間。而在一些小屏幕手機下,商品樓層距離首屏很遠,商品樓層的懶加載就顯得非常重要了。
PWA 全稱 Progressive Web App,即漸進式 WEB 應用。是近兩年來比較火的一個技術,經常使用來實現離線緩存功能,用戶能夠較快的訪問已經訪問過的頁面,PLUS 會員首次使用了該技術,具體的代碼就不說了,線上示例一搜一麻袋,這裏聊一聊較少說起的坑吧。
儘可能把 sw.js 要放在和頁面 HTML 同一個目錄下,不然註冊 serviceWorker 無效; 最初模板代碼發在了 src/template/index.html,我把 sw.js 放在了根目錄,也就是和 src 一個路徑下,再去配置 scope ,老是提示註冊 serviceWorker 無效;
終於註冊成功以後,代碼也不報錯,但是查看控制檯中的 Network,全部的請求並無走 serviceWorker,配置文件改了又改,緩存刪了又刪,Network 中的 Disable cache 也取消選擇,最後才發現環境的配置問題!以下圖所示:
打開瀏覽器的控制檯,選擇 Application 頁籤,左側選擇 Service Workers 頁籤,必定要注意這三個選項:
我最開始的 Bypass for netWork 默認選中,因此致使頁面請求一直走的是網絡請求。
注意的是,咱們這次只是在更新迭代較少的異常狀態頁面加入了 PWA 做爲嘗試,其餘狀態按照每週至少兩次上線,同時並行十來個需求的節奏,每一個頁面對應一個 sw.js 文件的狀況來講,若是每次都要後端去更新 sw.js 的文件,我感受後端童鞋又要扛着五米長的大刀找我來玩耍了~~~
提到TypeScript你們確定不陌生,它是 JavaScript 的一個超集,主要提供了類型系統和對ES6的支持。它的出現讓開發人員在編譯階段就能檢測大部分錯誤,增長了代碼的可讀性和可維護性。可是面對上千萬用戶的 PLUS 會員項目,咱們遲遲不敢動手,考慮到 PLUS 會員項目影響範圍較廣,業務邏輯複雜,且不斷有新的業務需求加入,小小的變化可能會產生嚴重的、意想不到的後果。
本着當心求證再擴大戰果的思想。咱們嘗試在新頁面的需求中,把 TypeScript 引入進來,在這個全新的頁面上進行一場 Vue + Webpack + Vuex + TypeScript 的小實驗。基於安全這一原則,在不改動原有項目代碼的基礎上,咱們當心翼翼的踏上了外界傳言 vue + typescript 深坑的探雷之路:
通過以上步驟,在原來的 JavaScript 項目基礎上進行 TypeScript 改造,以後就能夠使用 TypeScript 語法進行開發了。開發過程跟 Vue 項目開發沒有什麼區別,但有幾點是咱們開發時遇到的問題,拋磚引玉:
一、背景圖片路徑問題
若是你的項目中有這樣引入圖片:
.weixin {
background: url("../img/weixin-pay.png") no-repeat center;
background-size: 0.46rem 0.41rem;
}複製代碼
而且在 ts 文件中是經過 import 引入的 css 文件
<style lang="scss">@import '../asset/css/pay-method.scss';</style>複製代碼
那麼在啓動服務的時候可能會訪問不到背景圖片,這個問題初步判斷是路徑解析錯誤的問題。在嘗試了把樣式直接寫到頁面中或者寫到 common.css 裏仍是路徑用@來引入,都不能解決,最終在入口文件中引入 css 文件就能解決這個問題。
二、引入組件
原有項目中引入組件咱們可能會是這樣:
import Dialog from "@/component/dialog/index.js";
Dialog.install(Vue);複製代碼
但若是引用了 TS 後,咱們須要這樣改寫下不然將會報錯:
import Dialog from '@/component/dialog/index.js';
(Dialog as any).install(Vue);
複製代碼
三、this 的使用
在 TS 中咱們想使用 this 引入全局組件,但它所指向的上下文並非全局,因此要使用全局的組件就要對 this 進行下定義:
(this as any).$toast.text('正在處理中,請稍後再試~');
複製代碼
四、全局變量的聲明
在引入 TS 以後,若是在項目中想用 window
等全局變量,都須要在代碼最前邊聲明一下
declare var wx;
declare var MPing;
declare var window;複製代碼
以上是目前在開發項目時遇到的問題,以及咱們如今的處理方法,可能不是最優的解決方案,歡迎留言一塊兒討論學習~~
隨着迭代需求的日益增加,代碼冗餘度和繁瑣度也越發嚴重,久而久之可維護性就會變差。此外,開發人員書寫代碼水平、風格不一,有可能留有隱患,對此,通常在項目上線前,最好要進行 CodeReview,發現問題後便於修改,趁着安排好的測試資源檢查無誤後上線。。。
然而,對於 PLUS 團隊成員來講,紛至沓來的需求壓力以及各個需求卡死的上線日期,每每可以實現需求按時上線已經實屬不易。因此只能在項目上線後,見縫插針式的抽時間進行 CodeReview,這就致使了修改後沒有項目排期,沒有測試資源的尷尬境地。可是爲了推進從 CodeReview 中發現的問題,可以順利上線,咱們在每次 CodeReview 以後,作了如下事情:
至此,咱們從加強代碼的健壯性、優化用戶體驗、提升頁面渲染性能,優化代碼結構、提升開發人員效率幾個方面着重入手,排查了一些待優化的問題,並對這些問題進行梳理,申請項目排期和寶貴的測試資源,推進優化需求上線。
如何提升開發工做效率?在提高性能和用戶體驗的同時,也是咱們苦苦思索的方向。磨刀不誤砍柴工,只有解決開發過程當中對研發人員的痛點,才能讓研發人員更加快速的進入業務的開發之中。
Vue框架開發項目,組件化思想已經深刻人心,可是隨着項目複雜度的深刻,咱們發現每次新建一個組件,都要在首頁進行引入文件路徑,而且在 components 中添加該組件:
若是有十幾個組件,這裏就要 import 十幾個組件,相似的還有單頁面應用,每次新增路由時,也要引入大量的路由。面對這種狀況,爲了提升開發人員的工做效率,減小開發組件工序,咱們使用自動導入文件夾中的組件的方法,避免頁面引入過多的 import 和機械單調的引入步驟;
const files = require.context('./', false, /\.vue$/); //引入當前路徑下全部的vue文件
let configRouters = {};
const modules = {};
files.keys().forEach(key => {
const handleKey = key.replace('.vue', '').replace('./', '');//提取vue文件名字
const newName = handleKey.split('-'); //將floor-coupon.vue 改成 ['floor','name','defal']
let newString = '';
newName.forEach((item, index) => {
let newStr = '';
if ( index !== 0) {
newStr = item.substring(0, 1).first.toLocaleUpperCase() + item.substring(1);
} else {
newStr = item;
}
newString += newStr;
})
configRouters[newString] = files(key).default;//將files文件和對應的配置文件 configRouters 聯繫起來
})
export default configRouters; //導出配置文件
複製代碼
import configRouters from '@/component/myIndex.js';
export default {
components: configRouters, //把組件配置文件賦值給 components 便可。
}複製代碼
這樣經過上述方式,每次新增的組件,在文件夾中直接新建便可,實現了自動引入組件的功能。 經過以上優化的好處是:
工欲善其事,必先利其器。一款擁有着高效率的開發流程是每一位研發人所追求的。爲了便捷快速的開發,通常在本地使用 webpack-dev-server
啓動項目。然而一旦進入後續迭代,因爲存在接口跨域和登錄信息限制問題,沒法在本地打開頁面進行開發。以往大都使用 whistle 或者 fildder 採起配置線上代理文件看調試效果,以下所示進行配置:
plus.m.jd.com/index https://localhost:8080/index.html
plus.m.jd.com/js/ https://localhost:8080/js/
plus.m.jd.com/css/ https://localhost:8080/css/
plus.m.jd.com/img/ https://localhost:8080/img/
plus.m.jd.com/vendordev.dll.js https://localhost:8080/vendordev.dll.js複製代碼
由於每一個頁面都對應一套配置代理文件,多個頁面則有不一樣的配置代理文件。切換配置代理和操做起來,配置過程甚是繁瑣。 爲了解決以上問題,如何在本地開啓的環境上也能調用接口?就須要解決請求跨域和登錄信息兩隻攔路虎。
目前解決跨域經常使用的方法是採用 webpack-dev-server 結合 proxy 接口代理或者使用 Nginx 都可配置跨域的代理。因爲在本地配置好 webpack-dev-server 以後,全部項目成員均可以使用,一勞永逸。咱們採用了配置 webpack-dev-server 中 proxy 的接口代理,在 webpack.config.js 文件中對 webpack-dev-server 配置以下:
proxy: [
{
context: ['/user','/apis'], //使用context屬性,能夠把多個代理到同一個target下
target: 'https://rsp.jd.com/', //把用 user 和 apis 開頭的接口代理到 https://rsp.jd.com/域名下
secure: false, //默認不支持運行在https上,且使用了無效證書的後端服務器,這裏設置爲true,能夠支持
changeOrigin: true,//若是接口跨域,須要進行這個參數配置
pathRewrite: {'^/apis': ''},//因爲apis開頭的路徑,是人爲添加方便區分哪些接口要代理的,因此這裏去掉apis
headers: { //設置請求頭
origin: 'https://plus.m.jd.com', //請求接口限制來源,因此要改動請求源
host: 'rsp.jd.com',//設置請求頭的host
referer: 'https://plus.m.jd.com/index'//設置請求頭的referer,由於後端接口會有限制
}
}
]複製代碼
通過上述配置請求接口,而且設置項目中全部的接口前綴是 user 和 apis 開頭,若是是本地開發才新增的前綴,就須要根據開發環境切換接口前綴,在上線環境上刪除該前綴。
這樣,就能夠在本地開發時解決跨域問題,若是出現狀態碼錯誤,就要問一下後端是否是作了什麼限制,通常修改請求頭 headers 對應的信息便可。
解決了跨域問題,接口還能不能訪問,由於請求接口還須要攜帶 cookie 信息來判斷用戶是否登錄。咱們知道用戶登錄後,瀏覽器會把當前用戶信息對應的 id 值保存到 cookie 中,以後每次請求都會攜帶該域名下的 cookie 來判斷用戶登錄狀態。而本地開發的項目,是沒法攜帶 plus 域名下的 cookie,因此本地訪問的接口都會返回用戶未登錄,從而沒法獲取相關數據。
瀏覽器說了:一切不給登錄 cookie 就想要數據的行爲都是耍流氓!好吧,這種行爲能夠理解,畢竟不能空手套白狼,咱們只好曲線救國。因爲服務器爲了防止 XSS 攻擊,對 cookie 中用戶信息的 id 值設置了 httpOnly 屬性,避免使用 JS 獲取。但這樣致使咱們也沒有辦法使用 JS 獲取用戶信息的 cookie,因此咱們只好先在瀏覽器中訪問線上的 plus 頁面。而後在dev-tool面板上查找到用戶信息的 id,而後把該值放在本地的 cookie 中。這樣啓動本地 webpack-dev-server 服務,在以後的請求中把該 cookie 攜帶過去:
經過以上兩個核心步驟,開發人員能夠實如今本地一鍵命令便可啓動項目,極大的給開發人員提供了便利。如需模擬不一樣狀態用戶,只須要在js中替換對應的cookie變量便可。
世界由於多樣性而變得如此精彩,可是用在代碼格式上,倒是一場災難!在團隊協做開發當中,相信小夥伴們大部分會碰見如下尷尬的場景:
爲了不這種狀況,咱們使用了超高人氣的自動格式化工具 Prettier,它能夠自動的按配置好的規範幫你完成代碼的格式化,這不只省時省力,還能提升你的代碼閱讀性,簡直就是團隊協做開發的福音!
安裝使用 Prettier 的步驟以下所示:
這樣每次修改代碼後,保存文件的時候就會自動格式化。若是想一鍵把項目中全部文件都進行格式化,還能夠使用命令行的方式,這裏推薦在 package.json 中配置scripts命令:
"prettier:check": "prettier -l src/**/*.{js,vue,scss}",
//"prettier:check" 是檢查項目src目錄下的任何js、vue、scss文件是否存在格式問題;
"prettier:fix": "prettier --write src/**/*.{js,vue,scss}"
//"prettier:fix" 是一鍵格式化項目中src目錄下全部js、vue、scss文件;複製代碼
這樣咱們就能夠經過執行命令方式,來檢查代碼格式和自動修復格式,減小團隊不一樣開發人員代碼風格不同,以及單獨修改代碼格式的弊端,一勞永逸。
PLUS項目快速的迭代需求和多個需求並行開發的節奏,致使每次都要新拉分支進行開發,可是每每狂歡以後一地雞毛,貪圖一時的便利進行代碼提交,每每是到最後也沒法想起最初的修改目的。git版本管理系統爲代碼的有序和穩定作出了突出貢獻,可是便利的同時也須要規範和優化,才能使得git展示出更多的價值。
全部的提交建議使用 標識:內容 的形式,說明這次提交的目的,使每次提交都有價值
標識 | 說明 |
---|---|
feat | 新功能(feature) |
fix | 修補bug |
docs | 文檔(documentation) |
style | 格式(不影響代碼運行的變更) |
refactor | 重構(即不是新增功能,也不是修改bug的代碼變更) |
test | 增長測試 |
chore | 構建過程或輔助工具的變更 |
上面是 PLUS 項目中的一段提交信息,一連幾個相同的提交,像這樣提交價值就會減弱。通常來講,commit message 應該清晰明瞭,說明本次提交的目的。對於這種狀況的發生,通常有如下幾種場景:
針對這兩種狀況:
能夠使用 git stash
,去暫時保存,但不提交代碼,等切換回分支的時候,再讀取出來開發 git stash apply
;
針對第二種狀況已經提交了,這時候能夠用 git commit --amend
,撤銷上一次提交到暫存區,並從新提交內容;
注意:該方法必定要在未提交到遠程的commit進行操做,千萬不要提交到遠程以後在執行此命令。
回想起2019年,別有一番滋味在心頭~~經歷過通宵達旦的上線,眼神迷離的看見次日前來上班的同事。也遇到過週末早上忽然被電話驚醒,支持緊急需求的狀況。有的時候剛剛下班,卻被通知有需求要馬上評審。也有過壓力大、陷入迷茫困惑、情緒波動的時候。雖然說咱們無怨無悔,可是一個規範化的流程,本不該該讓人如此精疲力盡。工做就是一個不斷遇到問題而且解決問題過程,主動推動項目的規範化,提升人效,纔是正面問題的態度。因此咱們主動在如下方向進行了推動:
團隊的人員變更和快速迭代的需求,一度讓新加入的成員對 PLUS 項目不知如何下手。同時,一個合格的項目也須要制定開發規範,既可讓開發成員快速的瞭解進入項目,還能讓老成員明確規範化開發流程。所以,咱們團隊主要從如下幾個方面進行彙總:
包括但並不限於以上方向,經過制定總結項目規範,彙總開發時遇到的問題,有力的推動團隊開發人員對項目的熟悉,避免了新加入的成員經過本身摸着石頭過河的現狀,有利於快速的融入 PLUS 項目,順利的承擔起開發工做。
PLUS業務發展快,頻繁的需求評審,隨時隨地咚咚會議,困擾着整個 PLUS 項目團隊成員。原計劃安排的事情每每被迫中斷,手頭的工做不得不加班消化。久而久之,不但會讓團隊成員疲於應付,也打亂整個項目的排期進度,嚴重的引發蝴蝶效應,以後的需求有可能都會受到影響,所以解決這一問題迫在眉睫。
在項目覆盤會議上,呼籲創建更加合理的評審機制,將需求評審會議規範化。好在各個團隊的大力配合下,經過了每兩週進行一次需求集體評審的制度。對於緊急需求,根據其緊急程度評估是否單獨組織評審。
經過肯定需求評審機制以後,除非遇上6.18大促、雙11活動等節日有着密集的評審,其餘時間有了很大的改善,合理的評審機制,讓你們能夠更好的安排手頭的工做,讓人頭疼的需求混亂狀況有了較大的緩解。
學習如逆水行舟,不進則退。在前端技術日益更新的大環境下,若是隻考慮實現業務需求,團隊成員不但會慢慢的進入溫馨區,也會逐漸會在技術上逐漸掉隊。可是每週都要支持多個並行需求,加上前端主動發起的項目優化工做,再讓團隊成員去學習一些新的知識,時間上每每會顯得捉襟見肘。因此咱們不能漫無目的的去學習新知識。必須結合 PLUS 會員項目有的放矢。學習到的新技術能夠在 PLUS 項目中獲得實踐,不管是推動代碼更加完善仍是優化用戶體驗,都可以學以至用才行。
因而基於以上目標,咱們開始有意識的去探索。因爲項目使用 Vue 開發,一直在關注 Vue 3 的源碼公佈,其中使用的 TypeScript 技術映入咱們眼簾。發現 TypeScript 有不少優勢,尤爲是對多人合做開發的項目,增長了代碼的可讀性和可維護性。無規矩不成方圓,因而咱們團隊制定好學習計劃,每一個人利用空餘時間進行學習,在項目需求不緊張的時候,組織部分紅員對該項技術作了技術分享和知識討論。此外,在新頁面中進行了引入 TypeScript 的嘗試工做,因而才了上面對 TypeScript 的實踐部分。
因爲 PLUS 會員迭代需求不少,大部分需求都涉及到視覺稿的更新,和設計師的密切溝通是常態。在這個過程當中咱們發現兩個比較突出的問題。
設計師使用公司的產品協做工具 RELAY (類藍湖),可是有些圖片沒有給到切圖,或者到咱們開發的時候發現有些切圖沒有符合研發預期,因而聯繫視覺設計師去要對應的切圖的時候,因爲你們都很忙,可能不會及時回覆。問題就會阻塞,遇到嚴重的狀況,好比重構頁面時缺失不少切圖,或者相關字號、顏色等信息沒法獲取時,就會致使項目進度卡住。無形中增長了溝通成本。
需求上線須要通過視覺設計師的樣式走查,走查問題須要再修改。然而種種緣由,不少次都是項目晚上上線,下午才視覺走查。致使研發沒有時間改動,何況一旦改動也容易致使其餘的樣式問題。
經歷過幾回以後,咱們和視覺設計師們坐下來一塊兒探討了如何解決這些問題。
經過以上方法,最大程度的保證了研發在開發項目時拿到本身但願的視覺信息,避免了臨時抱佛腳,到開發時纔去溝通的問題,減小了溝通成本。此外提早通知視覺設計師進行樣式走查,避免了上線前的改動,容易帶來的隱患問題。
因爲歷史緣由,PLUS 會員項目有三個分支,分佈着不一樣狀態的 9 個頁面。第一批開發的頁面時間在兩年前,當時採用的一些技術和開發代碼不是很規範,裏面混雜着 jdf + zepto 技術棧的一些代碼。 在後續的開發過程當中逐漸延伸出共三個開發主分支:V二、V三、V4。
V4 新特性包括
下圖 Chrome 內置的自動化測試評估工具 Audits 對 V4 新頁面性能評分較高
骨架屏的引入縮短白屏等待時間,如圖測試在200ms-600ms白屏期間展現骨架屏,白屏時間縮短2/3,有助於提高頁面的主觀加載速度,進而提高用戶體驗。
所以遷移到V4從性能和開發效率方面考慮顯得尤其重要。尤爲當多個並行需求過來,涉及到基於從三個主分支新拉出一系列子分支進行開發,維護多個版本的弊端一覽無遺。爲此咱們主動發聲,以提效爲出發點講道理擺事實。首先爭取到產品側的理解和支持(特別感謝)得以立項提需,後續獲得項目經理及測試的資源支持。推進產品側關注代碼版本遷移的狀況,在以後的需求迭代中,逐漸將老版本的代碼遷移到最新的 V4 分支上。
目前爲止,V2 分支上的季卡過時首頁、年卡過時首頁、尊享商品頁面[後改成省錢攻略頁]、個人PLUS頁面(正式過時、試用中狀態)、試用過時30天內均遷移到 V4 上。還剩下 V2 改動不多的異常首頁及 V3 中的試用中及試用過時30天內代碼。這一進程還沒有結束,最終的目標是把全部用戶狀態和頁面代碼所有遷移到最新技術棧架構分支上。
隨着對 PLUS 項目的重視,咱們安排了單獨研發來跟進全部的需求和排期,避免了你們要一邊支持開發,一邊時間被打斷參加各類會議。全部的需求通過評審、梳理以後,肯定哪些能夠並行開發,哪些須要串行開發。再和項目經理配合,制定出前端團隊的工做排期。這樣每一個人下週的工做都是肯定了的,分工明確,不會被臨時需求和緊急需求打亂。
此外,全部的緊急需求、新插入的需求、線上出現的問題都要再通過對接人的梳理、排查以後視需求狀況而定:
這樣,整個團隊的時間有了更好的安排,不會被項目需求牽着鼻子走,每週的工做都是安排好的,每一個人的工做都是明確的,能夠適當的調整本身工做的節奏,避免了各類緊急需求的插入。
通過以上措施,團隊成員可以快速的進入項目開發,分工明確、每一個節點作什麼事情也變的清晰。同時也提升了和其餘團隊的溝通協做,減小推諉。孟子曾曰:不以規矩,不能成方圓;不以六律,不能正五音。深覺得然!
2019 年雙十一,PLUS 正式會員數突破 1500w,迎來新的歷史時刻。一位 PLUS 會員單筆消費 46.7 萬元,成爲京東單筆消費最高的一單。咱們在感覺着團隊成績的同時,也倍感責任重大。回首 2019 年,對於 PLUS 前端團隊成員來講,是不平凡的一年。在保證完成紛至沓來的迭代需求前提下,從優化用戶體驗、提升開發效率、推動完善制度流程等方面入手,使得 PLUS 會員項目日趨完善。
此刻,窗外寒冬中呼嘯着凜冽的寒風,吹散了往日的霧霾,吹來了豔陽高照、晴空萬里。悄悄的抓住 2019 的尾巴,對即將到來的 2020 年充滿希翼。正如京東 PLUS 會員項目遇到的挑戰同樣,終究會跨過去迎來新的征程,2019再見,2020 加油!