最近在做一个基于mobile app的漫画的项目,面向印尼市场。

网址是https://id.mangaya.mobi

上线后,基本测试没有问题,打开也挺顺畅。但是google analytics却反馈加载平均19s

OMG~~于是开展了一系列的探索。。

首先说说技术栈,用的是create-react-app,redux,react-router,webpack4,babel7.

我们知道网页的加载流程大致如下:

那么优化网页的加载速度,最本质的方式就是,1.减少请求数量 2.缩小请求体积大小。

减少请求数量

  1. 用base64减少不必要的网络请求,实际上create-react-app已经自动帮我们做了。

  1. 引入文件使用React.Lazy

  1. 图片延迟加载,使用react-lazyload,非常方便。

缩小请求体积大小

  1. 后台返回的图片使用webp格式,缩小体积。但是由于webp目前只被安卓支持,所以我们目前的方案是后端获取请求的user-agent信息,判断如果是ios的话,就返回jpg格式的图片,如果是安卓的话,就返回webp格式。这主要使用在banner图。

  2. webpack 处理

  • 2.1 build的时候去掉map文件,减少不必要的文件以及防止被查看源码

  • 2.2 压缩css和js,实际上create-react-app已经自动帮我们做了。uglifyjs-webpack-plugin使用的uglify-es已经不再被维护,取而代之的是一个名为terser的分支。

  • 2.3 默认splitChunk是chunks: 'all',但是这样会导致生成一个很大的vendor文件,可以改一下,将node文件抽离出来。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    splitChunks: {
    // chunks: 'all',
    chunks: "all",
    maxInitialRequests: Infinity,
    minSize: 0,
    cacheGroups: {
    vendor: {
    test: /[\\/]node_modules[\\/]/,
    name(module) {
    // get the name. E.g. node_modules/packageName/not/this/part.js
    // or node_modules/packageName
    const packageName = module.context.match(
    /[\\/]node_modules[\\/](.*?)([\\/]|$)/
    )[1];

    // npm package names are URL-safe, but some servers don't like @ symbols
    return `npm.${packageName.replace("@", "")}`;
    }
    }
    },
    name: false
    },

这样虽然总的项目大小变大了,但是由于vendor文件被拆分成多个文件,根据http1.1或者http2的协议,浏览器资源获取是可以多个并行的,配合cdn,这样请求资源,反而更快。

  • 2.4 Babel polyfill的按需加载,直接在package.json配置就好了,由于需要支持的机子比较低端,所以设定为支持>0.02%的机型。可参考
    1
    2
    3
    4
    5
    6
    "browserslist": [
    ">0.02%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
    ]
  1. gzip压缩
    如果浏览器支持gzip压缩,在发送请求的时候,请求头中会带有
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    ![](https://user-gold-cdn.xitu.io/2019/2/12/168e0f8101ebac09?w=740&h=399&f=png&s=69812)

    ## 资源cdn加速
    将静态服务器改成印尼的服务器,明显dns以及静态资源的传输加快。最后就是cdn加速静态资源了,我把npm包的js都放到cdn上了,之后还可以配置多路cdn等策略。

    4.静态资源缓存
    加入pwa的service worker

    5.字体
    由于字体一般比较大,使用 font-display: swap;可以先让用户看到本地字体显示出内容来先,等字体加载下来了,再进行替换。

@font-face {
font-family: ‘Arvo’;
font-display: swap;
src: local(‘Arvo’), url(https://fonts.gstatic.com/s/arvo/v9/rC7kKhY-eUDY-ucISTIf5PesZW2xOQ-xsNqO47m55DA.woff2) format(‘woff2’);
}
`
详细可查看font-display

总结

经过一段时间的努力,成功将首次加载时间从19秒变成10秒以下!仍需要继续。。。

同时我们还招募了志愿者帮我们测试嘻嘻嘻

当然这只是首次的加载的时间问题,后续还有观看漫画的优化工作,以及支持http2.0,然后将vendor文件拆分成多个js文件加速加载等。