自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

云音樂2023年報(bào)前端大揭秘

開發(fā) 前端
日活和分享率很大程度取決于年報(bào)的產(chǎn)品創(chuàng)意是否足夠新穎。產(chǎn)品創(chuàng)意需要將用戶的聽歌數(shù)據(jù)以字體、圖片、動(dòng)效、音頻、視頻等多種方式準(zhǔn)確地展示給用戶,從而引發(fā)用戶的共鳴。

前言

每年的云音樂年度聽歌報(bào)告,就像一個(gè)靠譜的老朋友,總會(huì)在忙碌一年的時(shí)光盡頭里叩響記憶的大門。

  • 如果你曾錯(cuò)過了彼時(shí)的年報(bào),不妨現(xiàn)在就拿起手機(jī)掃描上圖的二維碼,與往期的精彩視聽來一場(chǎng)不期而遇的邂逅;
  • 如果你為年報(bào)中精巧而溫馨的動(dòng)畫而深深著迷,請(qǐng)直接移步至本文的姊妹篇:「云音樂2023年報(bào)動(dòng)效大揭秘」一探究竟;
  • 如果你恰好想了解年報(bào)中前端開發(fā)承擔(dān)了什么樣的角色、積累了哪些最佳實(shí)踐 ——那么巧了,本文將從性能體驗(yàn)、質(zhì)量管理、工程效率和一些筆者底層思考,幫助你逐步揭開年報(bào)的神秘面紗

性能體驗(yàn)

首次訪問年報(bào)活動(dòng)為例,好的用戶體驗(yàn)主要包括以下幾個(gè)方面:

  • 頁面能秒級(jí)打開,頁面到達(dá)率高、流失少;
  • 頁面間轉(zhuǎn)場(chǎng)展示流暢,不會(huì)出現(xiàn)卡頓;
  • 文本和圖片內(nèi)容在任何設(shè)備上都能完整展示,不出現(xiàn)缺失或者加載閃爍情況;
  • 音頻或視頻啟播速度快,播放過程中不發(fā)生錯(cuò)亂或者卡頓情況;
  • 頁面內(nèi)的動(dòng)效展示流暢,不會(huì)出現(xiàn)卡頓;

圖片圖片

簡而言之,體驗(yàn)優(yōu)涉及以下幾個(gè)方面:

1、頁面導(dǎo)航:包括首屏秒開,頁面轉(zhuǎn)場(chǎng)等

2、資源管理:包括圖片、視頻、音頻和字體包等

3、頁面適配:包括文本適配、動(dòng)效適配和機(jī)型適配等

首屏秒開

首屏秒開是指用戶從點(diǎn)擊鏈接開始到展示頁面內(nèi)容大約在1s左右完成。整個(gè)過程經(jīng)歷如圖所示:

容器初始化 -> CDN -> TCP 建連 -> html/js/css 加載解析 -> DOM / CSSOM 解析 -> 渲染布局 -> 繪制

圖片圖片

對(duì)于前端開發(fā)來說,優(yōu)化難度是從右到左,越到左邊就越需要跨團(tuán)隊(duì)合作來完成??梢院唵蔚姆治隹偨Y(jié):

  • 在渲染/繪制階段,可以隔離狀態(tài)變化頻繁的組件,減少無效狀態(tài)引起的繪制。盡量選擇由 GPU 渲染的 CSS3 來實(shí)現(xiàn)動(dòng)效。邏輯實(shí)現(xiàn)的動(dòng)效建議使用GSAP。
  • 在 DOM / CSSDOM 解析階段,可以減少 DOM 的嵌套深度,減少使用 JavaScript 直接修改元素樣式,減少不必要的 CSS,減少使用 CSS 選擇器等。
  • 在 HTML / JS / CSS 加載解析階段,可以通過構(gòu)件工具對(duì)文件進(jìn)行壓縮。利用離線包能力,將這些資源提前下載到本地。
  • 在 CDN、TCP 建連階段,更多依賴 App 網(wǎng)絡(luò)庫底層的優(yōu)化,如使用 HTPP/2 減少 TCP 連接數(shù)。
  • 在容器初始化階段,為了達(dá)到極致的打開速度,可以將 H5 容器進(jìn)行預(yù)初始化。也可以建立容器復(fù)用池,減少容器創(chuàng)建的耗時(shí)。

頁面管理

頁面路由

為了有效管控年報(bào)中多個(gè)視圖的高效展示和切換,采用了 SPA[1] 的形式對(duì)H5進(jìn)行組織,同時(shí)為頁面路由提供了路由表的配置。

路由表簡單理解是各個(gè)子頁面路由對(duì)象的集合,這個(gè)集合可以是全局?jǐn)?shù)組對(duì)象,本地文件,或者服務(wù)端下發(fā)的配置。集合內(nèi)的順序決定了用戶看到報(bào)告頁順序。這樣也可以根據(jù)產(chǎn)品的述求,靈活調(diào)整集合內(nèi)的順序,這樣就能動(dòng)態(tài)調(diào)整頁面順序了。

各個(gè)子頁面路由對(duì)象的屬性具體如下。建議不用傳統(tǒng)的 path,因?yàn)樽禹撁鏀?shù)量多,且名稱很難記憶,可以使用 routerIndex,這是子頁面在交互稿中的位置代號(hào),方便開發(fā)和調(diào)試。其中 ignoreSwipe 是使用在下節(jié)手勢(shì)處理中「子容器接管父容器手勢(shì)」的場(chǎng)景。

export interface PageProps {
    model: unknown;
    position?: number; // 頁面埋點(diǎn)使用
}

export interface PageRouteProps {
    c: ComponentType<PageProps>;
    cId: string; // 當(dāng)前頁面唯一id
    routerIndex: number | string; // 路由索引
    ignoreSwipe?: boolean; // 是否忽略滑動(dòng),默認(rèn)false
}

手勢(shì)處理

年報(bào)項(xiàng)目中用戶可以通過點(diǎn)擊、左右滑動(dòng)、上下滑動(dòng)來切換頁面。為了防止手勢(shì)沖突,全局只有一個(gè)父容器,各個(gè)報(bào)告頁面是子容器;一些手勢(shì)頻控、頁面狀態(tài)變化等通用邏輯統(tǒng)一在父容器中實(shí)現(xiàn)。只在父容器中使用 hammerjs 做手勢(shì)監(jiān)聽,子容器不再負(fù)責(zé)頁面切換的手勢(shì)監(jiān)聽,關(guān)鍵代碼如下。

hammer = new Hammer(reportRef.current);
 hammer.get('swipe').set({ direction: Hammer.DIRECTION_ALL });
 hammer.on('swipeleft', onNextPageWrap);
 hammer.on('swiperight', onPrePageWrap);
 hammer.on('swipeup', onNextPage);
 hammer.on('swipedown', onPrePage);

對(duì)于子容器,可能會(huì)有以下幾種特殊情況:

情況一:如果子容器需要感知用戶手勢(shì)事件,可以監(jiān)聽父容器發(fā)出的自定義事件。

// 【翻頁】動(dòng)效:下一頁
export const ON_PAGE_NEXT = 'ON_PAGE_NEXT';

// 【翻頁】動(dòng)效:上一頁
export const ON_PAGE_PREV = 'ON_PAGE_PREV';

情況二:如果子容器需要完全接管父容器的手勢(shì)監(jiān)聽事件,例如年度歌手相關(guān)的所有頁面。首先需要在路由表中將 ignoreSwipe=ture 設(shè)置忽略手勢(shì),然后在監(jiān)聽父容器發(fā)出的通知,進(jìn)行自定義的事件處理。最后當(dāng)子容器接管結(jié)束后,需要根據(jù)需要再次觸發(fā)父容器的切換事件。關(guān)鍵代碼如下:

const onNextPage = useCallback(
    (nextAction) => {
        if (currentPage >= len - 1) {
            nextAction(); // 結(jié)束接管,再次觸發(fā)父容器的切換事件
            return;
        }
        
        setCurrentPage(currentPage + 1);
    },
    [currentPage, len]
);

useEffect(() => {
        bus.on(ON_PAGE_NEXT, onNextPage);

        return () => {
            bus.off(ON_PAGE_NEXT, onNextPage);
        };
    }, [onNextPage, onPrePage]);

情況三:如果子容器存在特定區(qū)域需要響應(yīng)特點(diǎn)手勢(shì),例如歌手來信頁面左右切換是查看歌手來信。這時(shí)候需要子容器調(diào)用stopPropagation主動(dòng)阻止手勢(shì)向父容器傳遞。

轉(zhuǎn)場(chǎng)實(shí)現(xiàn)

在路由表和手勢(shì)處理準(zhǔn)備就緒后,最后來看看頁面之間轉(zhuǎn)場(chǎng)的實(shí)現(xiàn)。年報(bào)頁面的轉(zhuǎn)場(chǎng)效果使用React官方實(shí)現(xiàn)的 react-transition-group 組件。由于篇幅限制,這里不詳細(xì)介紹react-transition-group 組件的底層原理。結(jié)合路由表順序和當(dāng)前頁面位置,通過 z-index 和 match 來控制子頁面的層級(jí)和顯示隱藏。使用 CSSTransition 實(shí)現(xiàn)頁面間的進(jìn)場(chǎng)和退場(chǎng)CSS動(dòng)畫。關(guān)鍵代碼如下:

(pages || []).map((item, index) => {
    // zIndex 和 match是關(guān)鍵代碼
    const zIndex = (pages.length - index) * 100;
    const match = index === currentIdx;
    return (
        <div
            key={item.cId}
            style={{
                zIndex,
                pointerEvents: match ? 'auto' : 'none',
                overflow: 'hidden',
            }}>
                <CSSTransition
                    in={match}
                    timeout={100}
                    ...
                    appear
                    unmountOnExit>
                    <item.c
                        model={item.model}
                        positinotallow={index} />
                </CSSTransition>
          </div>        
    );
})

但是以上的頁面轉(zhuǎn)場(chǎng)存在一個(gè)問題,即頁面之間只能存在一種轉(zhuǎn)場(chǎng)方式。如何自定義頁面之間的轉(zhuǎn)場(chǎng)效果?基本思路是各自頁面維護(hù)自己的轉(zhuǎn)場(chǎng)效果;大部分頁面只需將轉(zhuǎn)場(chǎng)信息配置到路由表中;小部分頁面可以通過頁面上下文獲得上一個(gè)或者下一個(gè)頁面的信息,動(dòng)態(tài)決定如何進(jìn)場(chǎng)或者退場(chǎng)?;谠撍悸?,改造路由表對(duì)象,新增一個(gè) TransitionParams 協(xié)議,并且提供漸隱漸顯的默認(rèn)轉(zhuǎn)場(chǎng)實(shí)現(xiàn)。關(guān)鍵代碼如下:

export type TransitionParams = {
    timeout: number | { appear?: number | undefined; enter?: number | undefined; exit?: number | undefined };
    classNames: CSSTransitionClassNames;
};

export interface PageRouteProps {
    c: ComponentType<PageProps>;
    cId: string; // 當(dāng)前頁面唯一id
    routerIndex: number; // 路由索引
    transition: TransitionParams; //默認(rèn)是漸隱漸顯的轉(zhuǎn)場(chǎng)效果
    ignoreSwipe?: boolean; // 是否忽略滑動(dòng),默認(rèn)false
}

CSSTransition 配合改造后的關(guān)鍵代碼如下:

<CSSTransition
    in={match}
    timeout={item.transition.timeout}
    // 關(guān)鍵代碼
    classNames={item.transition.classNames}
    appear
    unmountOnExit>
        <item.c model={item.model} positinotallow={index} />
</CSSTransition>

資源管理

資源管理主要任務(wù)是將網(wǎng)絡(luò)資源下載到本地,最終將本地資源加載到內(nèi)存,以便程序可以使用這些資源。優(yōu)化資源管理可以有效提高年報(bào)用戶體驗(yàn)。通常開發(fā)者會(huì)通過壓縮資源的大小,并通過內(nèi)容分發(fā)網(wǎng)絡(luò)(CDN)加快資源的下載速度。但是除了這些還有其他通用的方法呢?

在介紹具體優(yōu)化手段前,先來看以下關(guān)鍵字,這些是性能優(yōu)化的通用方法。

  • 提前 preload:提前準(zhǔn)備必要的資源,提升加載速度
  • 同步 sync:串行執(zhí)行當(dāng)前任務(wù),確保執(zhí)行任務(wù)的優(yōu)先級(jí)
  • 異步 async:工作線程異步執(zhí)行,處理比較耗時(shí)的操作,不阻塞主線程
  • 懶加載 lazy:又稱按需加載,不浪費(fèi)請(qǐng)求
  • 緩存 cache:將資源緩存到內(nèi)存或者磁盤本地,減少不必要的網(wǎng)絡(luò)請(qǐng)求
  • 延遲 defer:不立即執(zhí)行任務(wù),延遲執(zhí)行

總結(jié)如下圖:

圖片圖片

接下來,將從圖片、視頻、字體包等各個(gè)資源,進(jìn)一步解析如何結(jié)合上述關(guān)鍵詞進(jìn)行優(yōu)化。

圖片

關(guān)鍵字:提前 preload、懶加載 lazy、緩存 cache

圖片資源占整個(gè)年報(bào)項(xiàng)目資源中的比例是最高的,大概 70% 左右。所以圖片展示速度是否足夠快和內(nèi)容是否完整都會(huì)直接影響用戶體驗(yàn)。

優(yōu)先將圖片資源使用 tinypng 進(jìn)行手動(dòng)壓縮,在不失真的情況下,保證圖片大小足夠小。其次正確選擇圖片格式能有效減少圖片大小。其中圖片格式很多,主流的有:

  • SVG 是基于XML的矢量圖片格式,不失真無限放大。支持動(dòng)畫。
  • JPEG 是有損壓縮,不支持透明度或者動(dòng)畫。
  • PNG 是無損壓縮,支持透明度。APNG 是 PNG 的擴(kuò)展,支持動(dòng)胡奧。
  • WebP 是無損和有損壓縮,支持動(dòng)畫或者透明度。
  • GIF 是位圖圖片格式,支持動(dòng)畫。

不同圖片格式在不同場(chǎng)景上使用。格式?jīng)]選準(zhǔn)確,會(huì)導(dǎo)致資源浪的費(fèi)。如在「年度總覽」一頁中,海浪??背景是一張PNG格式,大小為 1.7MB。但是該場(chǎng)景不需要透明,選擇JPEG后大小為 96kb。總結(jié)如下是選擇圖片格式的流程圖。

圖片圖片

小圖標(biāo)或 logo 可以使用 SVG。其它能用 WebP 盡量使用 WebP。對(duì)于 WebP 的兼容性問題,可以通過業(yè)務(wù)封裝的圖片組件進(jìn)行處理,不能使用 WebP 則兜底變成 PNG ,因?yàn)?PNG 兼容性最好。GIF 盡量不適用。對(duì)于超過特定大小的動(dòng)圖,建議使用CSS動(dòng)效或者視頻替代。

在已經(jīng)壓縮圖片和選擇正確的圖片格式的前提下,會(huì)在當(dāng)前報(bào)告頁面提前 preload 預(yù)加載下一頁面的圖片資源,并將圖片緩存cache在本地。

預(yù)下載的方式有多種,可以自動(dòng)全量下載,也可以手動(dòng)按需下載。

自動(dòng)全量下載,可以基于上文 CSSTransition 的 in 參數(shù)。不只是匹配當(dāng)前頁面進(jìn)行渲染,也提前渲染下一頁。自動(dòng)下載的方案存在缺點(diǎn)比較明顯,如:不能按需下載;頁面的生命周期和用戶感知不一致,導(dǎo)致一些邏輯提前執(zhí)行如頁面曝光埋點(diǎn)。

let matchIndex = -1;

(pages || []).map((item, index) => {
    const zIndex = (pages.length - index) * 100;
    const match = index === currentIdx;
    if (match) {
        matchIndex = index;
    }

    return (
        <div
            key={item.cId}
            style={{
                zIndex,
                pointerEvents: match ? 'auto' : 'none',
                overflow: 'hidden',
            }}>
                <CSSTransition
                    // in 這里是關(guān)鍵代碼
                    in={match || (index ===  matchIndex + 1)}
                    timeout={item.transition.timeout}
                    classNames={item.transition.classNames}
                    appear
                    unmountOnExit>
                    <item.c model={item.model} positinotallow={index} />
                </CSSTransition>
          </div>        
    );
})

相較自動(dòng)下載,手動(dòng)按需下載更加可控。手動(dòng)按需下載那些圖片可以選擇更接近用戶體感的 LCP(Largest Contentful Paint)原則。因?yàn)樵跇I(yè)務(wù)頁面加載階段,命中 LCP 的元素可能會(huì)發(fā)生變化,所以這里主觀選擇可能命中 LCP 的圖片元素進(jìn)行預(yù)下載。如下圖,最終選擇A、B、C、D這個(gè)四張圖片進(jìn)行預(yù)加載。

圖片圖片

手動(dòng)下載的方法有多種??梢曰谌綆?nbsp;pxloader 進(jìn)行再一次封裝。如果將 React 升級(jí)到19后,系統(tǒng)默認(rèn)提供了 preload API,更多API詳情見此鏈接[2]。

import { preload } from 'react-dom'

// 下載字體包
preload('https://.../path/to/font.woff', { as: 'font' })

// 下載樣式表
preload('https://.../path/to/stylesheet.css', { as: 'style' })

// 下載不知道的文件類型
prefetchDNS('https://...')

手動(dòng)下載的時(shí)機(jī)可以監(jiān)聽頁面切換,根據(jù)當(dāng)前頁面信息在路由表中獲取到下一個(gè)需要預(yù)加載的頁面信息。最終手動(dòng)下載的偽代碼如下:

const preload = new PreLoader();

const usePreLoader = ({ pages, currentIdx }: PreLoadSourceProps): void => {
    useEffect(() => {
        const preLoadIndex = currentIdx + 1; // 提前預(yù)加載
        const item = pages[preLoadIndex];

        if (item.cId === YearOverviewIdentifier) {
            preload.add([A, B]);
            preload.start();
        }

        ...

    }, [currentIdx, pages, reportInfo]);
};

視頻

關(guān)鍵字:提前preload、同步sync

和圖片同樣的思路,先明確視頻的尺寸,不同尺寸大小的視頻資源大小也不一樣。在視頻尺寸正確的前提下,在做視頻體驗(yàn)優(yōu)化才能事半功倍。在項(xiàng)目初期準(zhǔn)備 6 種視頻,相同視頻內(nèi)容,網(wǎng)絡(luò)環(huán)境下,用不同系統(tǒng)的機(jī)型進(jìn)行壓測(cè)。這 6 種視頻,分別是:

  • 寬1242、高2688、FPS50
  • 寬1242、高2688、FPS25
  • 寬1080、高2388、FPS50
  • 寬1080、高2388、FPS25
  • 寬720、高1625、FPS50
  • 寬720、高1625、FPS25

壓測(cè)得出的實(shí)驗(yàn)結(jié)論是:

  • 安卓 10-13,分辨率高于 2400 的 6 種視頻大小都能體驗(yàn),但寬1242 & 高2688 尺寸的視頻基本上會(huì)有卡頓;
  • 安卓 10-13,分辨率低于 2400,寬1242 & 高2688 該尺寸的視頻無法進(jìn)行體驗(yàn);
  • 安卓 10 以下的,只能體驗(yàn)寬720 & 高1624 該尺寸下的視頻。
  • iOS 系統(tǒng) 13-16,體驗(yàn)都正常,iOS12 系統(tǒng),寬1242 & 高2688 & FPS50 和寬1080 & 高2338 & FPS50無法進(jìn)行體驗(yàn)。

最后根據(jù)實(shí)驗(yàn)結(jié)論,結(jié)合視頻效果和資源大小的考慮,最終采用三種尺寸的視頻,分別是:

  • 寬1080、高2388、FPS50,命名為 w1080FPS50
  • 寬720、高1625、FPS50,命名為 w720FPS50
  • 寬720、高1625、FPS25,命名為 w720FPS25

總結(jié)如下是選擇視頻尺寸大小的流程圖。w1080FPS50 體驗(yàn)最優(yōu),w720FPS25 兼容性最好。開發(fā)可以根據(jù)不同的機(jī)型、系統(tǒng)選擇合適的視頻。

圖片圖片

為了讓用戶在點(diǎn)擊封面頁面的開始按鈕后能流暢觀看視頻,選擇在封面頁面渲染完成后,同步 sync 添加視頻頁面。通過 zIndex 將其隱藏在封面頁后面,利用用戶游覽封面頁的間隙,提前 preload 創(chuàng)建 video 組件。同時(shí),設(shè)置<video>的 preload='auto',讓游覽器結(jié)合網(wǎng)絡(luò)等自身?xiàng)l件自動(dòng)決策是否預(yù)加載視頻。

即使選擇好合適的視頻資源后,也需要兜底處理一些播放的異常情況,防止播放失敗影響體驗(yàn)。可以監(jiān)聽onWaiting回調(diào),如果在規(guī)定時(shí)間內(nèi)如果沒有再次觸發(fā)onPlay回調(diào),會(huì)直接手動(dòng)執(zhí)行onEnd回調(diào)的事件。也可以在onCanPlay回調(diào)中啟動(dòng)視頻超時(shí)定時(shí)器,在規(guī)定范圍內(nèi)系統(tǒng)沒有自動(dòng)觸發(fā)到onEnd回調(diào),那也會(huì)直接手動(dòng)執(zhí)行onEnd回調(diào)的事件。

音頻、字體包

關(guān)鍵字:延遲defer,懶加載lazy

音頻在工程中通常有兩種播放能力:WebAudio H5 原生播放能力和通過RPC方式調(diào)用客戶端原生播放能力。

在站內(nèi)場(chǎng)景中,通常推薦使用客戶端 RPC 提供的播放能力,因?yàn)樗梢詮?fù)用端上播放的基礎(chǔ)能力,如播放音質(zhì)、啟播時(shí)長等都有優(yōu)化。如果站內(nèi)想要繞過某些播放權(quán)限,會(huì)選擇 H5 原生播放能力。而在站外,只能使用H5原生播放能力。為了簡化開發(fā)接入,封裝 audioManager 業(yè)務(wù)組件,提供統(tǒng)一的API接口,抹平站內(nèi)、站外的兼容性問題。

對(duì)于字體包,通常會(huì)懶加載 lazy 選擇視覺設(shè)計(jì)中使用到的字體包。針對(duì)固定文案的情況下,使用工具裁剪掉多余的字體,從而達(dá)到最小字體包。也會(huì)在 header 中延遲 defer 下載字體包的資源,以避免阻塞封面頁的渲染。在封面頁面不使用特殊字體包的前提下,可以在封面頁面設(shè)置不可見的<p>標(biāo)簽,靜默下載字體包,從而讓后續(xù)報(bào)告頁面里的特殊字體不出現(xiàn)跳變。

小結(jié)

可以組合使用不同的優(yōu)化手段來提高性能,但切記物極必反。例如在年報(bào)項(xiàng)目開發(fā)過程中,為了實(shí)現(xiàn)歌手子頁面轉(zhuǎn)場(chǎng)的效果,會(huì)將 6 個(gè)子頁面提前加載。在開發(fā)早期,各個(gè)頁面渲染復(fù)雜度低,不會(huì)出現(xiàn)問題。但在后續(xù)為了提高視覺效果,加入了各種噪點(diǎn)、混合、粒子效果后,在低端機(jī)設(shè)備上,該模塊在切換時(shí)容易出現(xiàn)白屏現(xiàn)象。最后定位是子頁面提前預(yù)加載過多,內(nèi)存占用大,使得端上收到 OOM 警告,回收 H5 容器,從而導(dǎo)致了白屏。最后,采用懶加載 lazy 加載,同一時(shí)間最多顯示 3 個(gè)頁面,這樣既保證子頁面轉(zhuǎn)場(chǎng)的流暢,也保證了功能的正常使用。

頁面適配

用戶手機(jī)機(jī)型千變?nèi)f化,頁面適配是必須要面對(duì)的問題。開發(fā)之前先明確兩個(gè)關(guān)鍵的點(diǎn):站內(nèi)是否支持全屏;站外是否需要支持。明確后結(jié)合工程現(xiàn)狀,將需要適配的重點(diǎn)機(jī)型進(jìn)行枚舉,并歸納總結(jié),以 iPhone 機(jī)型為例如下:

圖片圖片

如果只適配站內(nèi)全屏/非全屏,建議將適配的機(jī)型寬高比控制在 2 個(gè)以內(nèi)。舉例年報(bào)只支持站內(nèi)全屏,如下圖第二列所示,可以將站內(nèi)適配劃分成 2 檔,通過媒體查詢,所以只需支持寬高比大于等于 375 / 667,適配范圍支持站內(nèi)寬屏或者小屏的機(jī)型。針對(duì)特殊頁面,還可以配 合max-height 再做微調(diào)。

@media screen and (min-aspect-ratio: 375 / 667) {
    // 大于等于 0.5622
    // 適配范圍:站內(nèi)寬屏、特殊小屏的機(jī)型
}

@media screen and (max-height: 750px) {
}

如果需要適配站外,建議將適配的機(jī)型寬高比控制在 4 個(gè)以內(nèi)。如下圖第三列所示,分析歷史站外流量分布,重點(diǎn)支持微信、微博等 App??梢詫⒄緝?nèi)、外適配劃分成四檔。第一檔需支持寬高比大于等于 400 / 815 且小于 375 / 667,適配范圍支持15pro、12promax、15promax、vivo s9 等站外+大屏。第二檔需支持寬高比大于等于 375 / 667 且小于 375 / 603,適配范圍支持 8p、SE 等站內(nèi)+寬屏、小屏。第三檔需支持寬高比大于等于 375 / 603,適配范圍支持8p、SE 等站外、寬屏+小屏。

@media screen and (min-aspect-ratio: 400 / 815) and (max-aspect-ratio: 374 / 667) {
    // 大于等于 0.4907,小于等于 0.5607
    // 適配范圍:15pro、12promax、15promax、vivo s9 等 站外+大屏
}

@media screen and (min-aspect-ratio: 375 / 667) and (max-aspect-ratio: 374 / 603) {
    // 大于等于 0.5622,小于0.6218
    // 適配范圍:8p、SE 等 站內(nèi)+寬屏、小屏  
}

@media screen and (min-aspect-ratio: 375 / 603) {
    // 大于等于 0.6218
    // 適配范圍:8p、SE 等 站外、寬屏+小屏 
}

質(zhì)量監(jiān)控

面向年報(bào)這種大型活動(dòng),針對(duì)質(zhì)量問題的感知不能僅被動(dòng)通過用戶反饋問題,更重要的是需要一套完善的監(jiān)控系統(tǒng)自動(dòng)發(fā)現(xiàn)問題。通過這套系統(tǒng)也能夠有效評(píng)估出線上運(yùn)行的狀態(tài),最后用數(shù)據(jù)來驗(yàn)證“質(zhì)量優(yōu)”這個(gè)技術(shù)指標(biāo)。

對(duì)于開發(fā)者而言,質(zhì)量優(yōu)的背后實(shí)質(zhì)是高可用。需要對(duì)各種異常結(jié)果進(jìn)行兜底,來保證用戶完整體驗(yàn)完年報(bào)活動(dòng)。簡而言之,質(zhì)量優(yōu)涉及以下幾個(gè)方面:

1、異常監(jiān)控:包括 crash 平臺(tái)、實(shí)時(shí)數(shù)據(jù)監(jiān)控平臺(tái),離線日志回?fù)破脚_(tái)等

2、功能降級(jí):包括 AB 配置中心,上線 SOP 白皮書,活動(dòng)研發(fā)平臺(tái)等

3、數(shù)據(jù)準(zhǔn)確:包括異常數(shù)據(jù)兜底,敏感數(shù)據(jù)過濾,埋點(diǎn)數(shù)據(jù)等

異常監(jiān)控

除了必備的異常 crash 監(jiān)控平臺(tái),還需要根據(jù)年報(bào)活動(dòng)的特性來構(gòu)建一個(gè)更全面的監(jiān)控體系。主要包括分享率監(jiān)控、視頻卡頓監(jiān)控、音頻啟播失敗監(jiān)控、接口異常監(jiān)控等。由于監(jiān)控的多樣性,需要根據(jù)不同的場(chǎng)景采用不同的監(jiān)控策略。例如,如果想觀察分享點(diǎn)擊率,需要實(shí)時(shí)上報(bào)監(jiān)控?cái)?shù)據(jù);如果需要排查頁面白屏問題,需要收集用戶本地的離線數(shù)據(jù)。由于年報(bào)日活高,樣本數(shù)據(jù)量大,需要考慮是否需要采樣上報(bào)。建議實(shí)時(shí)數(shù)據(jù)采用一定的采樣率,而離線數(shù)據(jù)則采全量上報(bào)。

監(jiān)控的思路是:現(xiàn)狀分析,指標(biāo)建設(shè),監(jiān)控埋點(diǎn),指標(biāo)分析,方案優(yōu)化,AB 實(shí)驗(yàn),驗(yàn)證收益。PACD 的方式持續(xù)改進(jìn),直到問題被解決。

以分享率監(jiān)控為例?;顒?dòng)分享率要達(dá)到xx%是年報(bào)關(guān)鍵指標(biāo)。分析工程中現(xiàn)狀后,制定如下圖的監(jiān)控指標(biāo)。

圖片圖片

結(jié)合線上埋點(diǎn)數(shù)據(jù),能夠清晰發(fā)現(xiàn)圖片生成耗時(shí)和圖片生成成功率對(duì)圖片分享成功率有正向影響。因此,后續(xù)開發(fā)的重點(diǎn)就是如何降低圖片耗時(shí)生成和提高圖片生成的成功率。

功能降級(jí)

監(jiān)控的本質(zhì)是及時(shí)發(fā)現(xiàn)問題并快速止損。在面對(duì)突發(fā)情況時(shí),通過線上配置快速關(guān)閉某些非核心功能,以確保核心功能的正常進(jìn)行。在開發(fā)中過程中,可以將降級(jí)開關(guān)集中配置在一個(gè)能進(jìn)行可視化的活動(dòng)研發(fā)平臺(tái)內(nèi)統(tǒng)一管理,如下圖。在上線前,需要將這些開關(guān)納入上線前的標(biāo)準(zhǔn)操作流程(SOP)中。

圖片圖片

下圖是年報(bào)的監(jiān)控大盤。對(duì)可能嚴(yán)重影響用戶體驗(yàn)的功能,如白屏、視頻和音頻進(jìn)行了重點(diǎn)監(jiān)控,同時(shí)也對(duì)關(guān)鍵業(yè)務(wù)模塊,如報(bào)告頁面和歌手來信進(jìn)行了監(jiān)控。這些監(jiān)控在年報(bào)活動(dòng)也發(fā)揮了重要的作用。例如,通過對(duì)報(bào)告頁面接口的監(jiān)控,發(fā)現(xiàn)由于 cookie 丟失導(dǎo)致用戶進(jìn)入不了年報(bào)的問題;通過對(duì)音頻播放的監(jiān)控,明確了站內(nèi)需要支持音視頻的自動(dòng)播放。

數(shù)據(jù)準(zhǔn)確

最后數(shù)據(jù)準(zhǔn)確性也是質(zhì)量優(yōu)的重要組成部分。其中需要關(guān)注兩個(gè)方面。首先,需要確保用戶界面的數(shù)據(jù)準(zhǔn)確無誤,這包括對(duì)服務(wù)端可能出現(xiàn)的異常情況進(jìn)行兜底處理,例如服務(wù)端下發(fā)數(shù)據(jù)失敗或者下發(fā)敏感數(shù)據(jù)等情況需。其次,要確保上報(bào)后臺(tái)的埋點(diǎn)數(shù)據(jù)不會(huì)漏報(bào)、重復(fù)報(bào)或者缺失關(guān)鍵信息。這些埋點(diǎn)數(shù)據(jù)的準(zhǔn)確性直接影響策劃和開發(fā)的實(shí)時(shí)決策。

工程效率

除了體驗(yàn)好、質(zhì)量優(yōu),效率高也是開發(fā)一直追求的命題。

對(duì)于策劃或者視覺來說,需求的頻繁變更是項(xiàng)目最大的風(fēng)險(xiǎn)。這要求開發(fā)團(tuán)隊(duì)能夠預(yù)見并總結(jié)可能出現(xiàn)變更的情況。例如,頁面順序會(huì)根據(jù)內(nèi)測(cè)用戶的反饋進(jìn)行調(diào)整,頁面數(shù)量可能會(huì)根據(jù)線上頁面的流失率進(jìn)行刪除。在例如,視覺要求頁面之間有統(tǒng)一的轉(zhuǎn)場(chǎng)效果,但是針對(duì)某些特殊頁面,要求工程應(yīng)該能夠支持自定義的轉(zhuǎn)場(chǎng)效果。

對(duì)于 QA 或者客服來說,當(dāng)用戶反饋問題時(shí),他們應(yīng)能夠通過快捷方式查看該用戶的年報(bào)。同時(shí),由于年報(bào)通常包含 30+ 頁面,他們希望能有一種快速定位到特定頁面的方法。通過這種方式,他們可以自助定位并解決部分線上客訴。在排除了用戶自身、數(shù)倉或者服務(wù)端的問題后,再將問題提到前端。

對(duì)于開發(fā)者來說,期望有一套開箱即用的基礎(chǔ)組件,如圖片、視頻、音頻等?;蛘吣軌蛟陧?xiàng)目創(chuàng)建初期,就能有一個(gè)包含基礎(chǔ)交互、數(shù)據(jù)模型和常用基礎(chǔ)組件的年報(bào)模板。更進(jìn)一步是,希望在開發(fā)過程使用使用D2C的插件,通過視覺稿直接生成代碼。更終極的狀態(tài)是,策劃和運(yùn)營通過搭建平臺(tái)能自助地構(gòu)建出年報(bào)項(xiàng)目。

圖片圖片

簡而言之,效率高涉及以下幾個(gè)方面:

1、頁面導(dǎo)航:包括頁面自動(dòng)曝光、支持動(dòng)態(tài)路由等

2、功能調(diào)試:包括年報(bào)快捷查看,頁面快速定位等

3、工程基建:包括通用組件/能力,年報(bào)模板,D2C 插件,搭建平臺(tái)等

為了實(shí)現(xiàn)各個(gè)活動(dòng)之間的能力復(fù)用,可以將活動(dòng)成果都會(huì)統(tǒng)一沉淀到活動(dòng)研發(fā)平臺(tái)。

這個(gè)平臺(tái)覆蓋了活動(dòng)的完整生命周期,包括開發(fā)前期需要參考的技術(shù)方案,UI組件,通用能力,活動(dòng)模板,開發(fā)中期需要的功能開關(guān)、分享內(nèi)容等配置,以及開發(fā)后期需要用到保障SOP和監(jiān)控告警等。

圖片圖片

后續(xù)在年報(bào)項(xiàng)目的初期階段,計(jì)劃通過活動(dòng)研發(fā)平臺(tái)的年報(bào)模板工程,快速搭建出年報(bào)的項(xiàng)目?;谶@個(gè)初始化工程,數(shù)據(jù)開發(fā)團(tuán)隊(duì)能盡早進(jìn)行的自測(cè)稽查。

深度思考

最終年報(bào)項(xiàng)目按照預(yù)期順利拿到業(yè)務(wù)結(jié)果。再次回顧立項(xiàng)初期,開發(fā)并不是簡單被動(dòng)接收目標(biāo),簡單的將需求實(shí)現(xiàn)??梢詮臉I(yè)務(wù)和技術(shù)關(guān)系分析出發(fā),定性、定量分析項(xiàng)目目標(biāo)是否能夠達(dá)成。

關(guān)系分析

業(yè)務(wù)和技術(shù)的關(guān)系可以劃分為三大類別:業(yè)務(wù)驅(qū)動(dòng)技術(shù)、技術(shù)保障業(yè)務(wù)、技術(shù)引領(lǐng)業(yè)務(wù)。

業(yè)務(wù)驅(qū)動(dòng)技術(shù)的一個(gè)典型例子是2020年報(bào)[3]中的DIY音樂人物形象。這是開發(fā)第一次在大型項(xiàng)目中使用 three.js。項(xiàng)目的初期,需要做大量的技術(shù)調(diào)研,并需要快速解決一些從未碰過的難題。項(xiàng)目的過程中,由于技術(shù)局限性,策劃不得不妥協(xié),對(duì)需求進(jìn)行調(diào)整。在業(yè)務(wù)驅(qū)動(dòng)技術(shù)的情況下,大部分情況是未知的,這會(huì)使得開發(fā)處于高度緊張的狀態(tài),也可能導(dǎo)致技術(shù)動(dòng)作的變型。

技術(shù)引領(lǐng)業(yè)務(wù)的一個(gè)典型例子是性格POP[4]。在這個(gè)項(xiàng)目中,開發(fā)主導(dǎo)了整過程,他們基于矩形樹圖算法實(shí)現(xiàn)一個(gè)無縫擠壓的動(dòng)效。策劃團(tuán)隊(duì)根據(jù)這個(gè)特定的動(dòng)效,定制業(yè)務(wù)需求。在技術(shù)引領(lǐng)業(yè)務(wù)的情況下,由于整個(gè)過程因?yàn)槎际且阎?,開發(fā)都是胸有成竹的狀態(tài),這通常會(huì)使業(yè)務(wù)的收益超出預(yù)期。

大部分的需求都是屬于技術(shù)保障業(yè)務(wù)的情況。這要求開發(fā)對(duì)當(dāng)前的工程能力有清晰的認(rèn)知,并協(xié)助策劃做出最合理的決策。開發(fā)需要科學(xué)分析業(yè)務(wù)目標(biāo)是否能達(dá)成,可以有效地管理策劃的心理預(yù)期。

圖片圖片

需要多積累技術(shù)知識(shí),減少業(yè)務(wù)驅(qū)動(dòng)技術(shù)的被動(dòng)情況出現(xiàn)。同時(shí)也需要提升對(duì)業(yè)務(wù)的敏銳度,讓技術(shù)引領(lǐng)業(yè)務(wù)的發(fā)展。最后將知識(shí)和經(jīng)驗(yàn)沉淀,從而更好保障業(yè)務(wù)的需求。

定量分析

2023年報(bào)就是典型的技術(shù)保障業(yè)務(wù)的場(chǎng)景。在業(yè)務(wù)立項(xiàng)初期,產(chǎn)品目標(biāo)是日活xx千萬,活動(dòng)分享率 xx%。

圖片圖片

項(xiàng)目初期項(xiàng)目負(fù)責(zé)人不應(yīng)埋頭搬磚,需要先通過現(xiàn)有數(shù)據(jù),理性分析業(yè)務(wù)目標(biāo)是否能達(dá)成。

圖片圖片

分析顯示,目前 Android 和 iOS 雙端的日活累計(jì)是X千萬。這個(gè)數(shù)字實(shí)際設(shè)定了年報(bào)日活躍用戶的上限。如果這個(gè)上限都不能滿足業(yè)務(wù)目標(biāo),那開發(fā)需要尋找更多的推廣渠道。除了現(xiàn)有的移動(dòng)端設(shè)備,可以考慮其他有多終端設(shè)備,如PC、iPad和TV,還可以考慮支持例如微信等站外渠道。這樣開發(fā)階段,需要重點(diǎn)考慮如何適配這些不同的用戶界面。

在確定投放渠道之后,可以進(jìn)一步分析每個(gè)渠道內(nèi)的投放位置。例如,在移動(dòng)端通常會(huì)選擇在首頁首幀 banner、首頁彈窗、以及其他高日活的頁面進(jìn)行投放。細(xì)化分析每個(gè)位置的用戶點(diǎn)擊率,最終能初步預(yù)估活動(dòng)的日活。在投放位置有限情況,如果這個(gè)預(yù)估值無法達(dá)到業(yè)務(wù)目標(biāo),那么需要額外開發(fā)其它點(diǎn)擊率較高的位置,如啟動(dòng)開屏位,供策劃選擇。

在不同角色中,對(duì)分享率這個(gè)指標(biāo)的定義可能會(huì)有所不同。因此,在項(xiàng)目啟動(dòng)的前期,開發(fā)需要和策劃達(dá)成一致,明確如何統(tǒng)計(jì)活動(dòng)的分享率。在明確統(tǒng)計(jì)口徑后,分析現(xiàn)有的分享行為,包括圖片分享、鏈接分享、口令分享和截屏分享。需要注意,截屏分享是最容易忽略統(tǒng)計(jì)的一種分享行為。接下來,分析不同分享行的流程。如下圖所示列出了不同分享行為所需要經(jīng)過的路徑。

圖片圖片

在這些路徑下進(jìn)行數(shù)據(jù)埋點(diǎn),以便能夠觀察和分析影響分享率的漏斗。通過結(jié)合對(duì)漏斗的專項(xiàng)治理和過往活動(dòng)的數(shù)據(jù),最終也能準(zhǔn)確預(yù)估年報(bào)的數(shù)據(jù)。

圖片圖片

定性分析

日活和分享率很大程度取決于年報(bào)的產(chǎn)品創(chuàng)意是否足夠新穎。產(chǎn)品創(chuàng)意需要將用戶的聽歌數(shù)據(jù)以字體、圖片、動(dòng)效、音頻、視頻等多種方式準(zhǔn)確地展示給用戶,從而引發(fā)用戶的共鳴。而作為開發(fā)者,需要以流暢、準(zhǔn)確、且高效的方式將這些多元的媒體內(nèi)容傳達(dá)給到用戶。

案例一:得益于今年年報(bào)對(duì)體驗(yàn)和質(zhì)量的高要求,上線后 5 日總客訴量比往年減少了 41%,收獲了大批用戶好評(píng)。

圖片圖片

案例二:首頁banner投放,從用戶點(diǎn)擊到 H5 頁面打開,頁面達(dá)到率 Android 端只有93%左右。假設(shè)將頁面到達(dá)率從 93% 優(yōu)化到 97% 以上,對(duì)年報(bào)帶來收益大概是是新增上百萬的日活用戶。

因此,好的用戶體驗(yàn)和高的產(chǎn)品質(zhì)量能夠有效地促進(jìn)年報(bào)的分享,從而進(jìn)一步提升日活躍用戶數(shù)量。

總結(jié)

一款深入人心的作品,不僅要有優(yōu)質(zhì)的產(chǎn)品內(nèi)容支撐,有效的技術(shù)優(yōu)化和保障也不可或缺,具體總結(jié)如下圖:

圖片圖片

最后本文從2023年度報(bào)告中的性能體驗(yàn)、質(zhì)量監(jiān)控和工程效率等方面出發(fā),介紹了筆者在年報(bào)項(xiàng)目經(jīng)歷中的一些探索和經(jīng)驗(yàn)。

參考資料

[1]SPA: https://developer.mozilla.org/en-US/docs/Glossary/SPA

[2]更多API詳情見此鏈接: https://react.dev/reference/react-dom#resource-preloading-apis

[3]2020年報(bào): https://st.music.163.com/c/year2020

[4]性格POP: https://sg.music.163.com/jia/begin/show

責(zé)任編輯:武曉燕 來源: 網(wǎng)易云音樂技術(shù)團(tuán)隊(duì)
相關(guān)推薦

2023-10-12 16:11:34

2023-07-05 14:48:32

2023-01-03 10:04:45

云計(jì)算邊緣計(jì)算

2020-04-01 10:33:39

華為

2011-04-21 09:55:29

華為年報(bào)

2024-01-05 16:32:50

2023-07-28 11:47:12

2022-11-09 13:27:10

云計(jì)算邊緣計(jì)算云安全

2023-10-11 11:07:19

人工智能云計(jì)算

2022-11-18 10:20:10

云計(jì)算Kubernetes

2012-02-13 14:33:53

筆記本評(píng)測(cè)

2020-04-02 10:24:02

華為

2014-03-31 17:47:14

華為年報(bào)華為ICT

2023-10-18 07:11:15

企業(yè)云云成本數(shù)字化

2023-05-19 15:03:58

云計(jì)算云戰(zhàn)略

2023-11-06 10:59:20

云計(jì)算IT行業(yè)

2022-12-30 11:10:45

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)