美文网首页
前端性能优化 - CDN引入分析及实践

前端性能优化 - CDN引入分析及实践

作者: 叶叶叶同学 | 来源:发表于2021-04-29 15:56 被阅读0次

    在前端项目里引入CDN技术以达到加速网页加载的目的

    create-react-app为例,

    // config-overrides.js
    const addCustomize = () => (config) => {
     config.plugins.push(
            new HtmlWebpackExternalsPlugin({
              externals: [
                {
                  // 引入的模块
                  module: "react",
                  // cdn的地址
                  entry: "https://cdn.bootcdn.net/ajax/libs/react/16.13.1/umd/react.production.min.js"
                  // 挂载到了window上的名称
                  // window.jQuery就可以全局使用
                  global: "React",
                }
              ],
            })
          );
      return config;
    };
    
    module.exports = override(
        ...
        addCustomize(),
    )
    

    当然,需要引入BundleAnalyzerPlugin进行编译打包后体积查看

    // config-overrides.js
    const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
    
    const addCustomize = () => (config) => {
        ...
        config.plugins.push(
          new BundleAnalyzerPlugin({
            analyzerMode: "static", //输出静态报告文件report.html,而不是启动一个web服务
          })
        );
       ....
    }
    
    

    笔者莫得私有CDN,于是乎想着试试用ng实现类似的引入方式。

    即: ng暴露linux某个文件夹,可以远程读取里面的文件,那么CDN的文件放在上面,且设置对应长时间的缓存策略,达到只读一次之后就不必再次请求获取资源的目的,原理上除了加速,使用、读取是跟CDN类似的,在此尝试读取本机的资源

    搞起

    配置ng

    location /private_static {
             alias /home/private_static/;
             expires 180d; ## 长时间的缓存策略
             add_header Cache-Control "public";
             add_header Access-Control-Allow-Origin *;  ## 跨域设置
             add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
             add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
             autoindex on; ## 开启远程读取模式
           }
    

    然后一个个把umd类型的包放进去即可

    drwxr-xr-x 3 root root 4096 Apr 29 10:05 antd
    drwxr-xr-x 3 root root 4096 Apr 29 10:04 antd-design-icons
    drwxr-xr-x 3 root root 4096 Apr 29 10:04 antd-mobile
    drwxr-xr-x 2 root root 4096 Apr 29 09:51 geolocation
    drwxr-xr-x 3 root root 4096 Apr 29 10:09 react
    drwxr-xr-x 3 root root 4096 Apr 29 11:57 react-activation
    drwxr-xr-x 3 root root 4096 Apr 29 10:07 react-dom
    drwxr-xr-x 3 root root 4096 Apr 29 10:06 react-is
    drwxr-xr-x 3 root root 4096 Apr 29 10:06 react-router-dom
    drwxr-xr-x 3 root root 4096 Apr 29 10:06 styled-components
    drwxr-xr-x 3 root root 4096 Apr 29 10:03 vconsole
    

    其一例子如下:

    // config-overrides.js
     config.plugins.push(
            new HtmlWebpackExternalsPlugin({
              externals: [
                {
                  // 引入的模块
                  module: "react",
                  // cdn的地址
                 entry: "https://www.yingtai.tech/private_static/react/16.13.1/react.production.min.js",
                  // 挂载到了window上的名称
                  // window.jQuery就可以全局使用
                  global: "React",
                }
              ],
            })
          );
    

    笔者尝试将N多个使用到的依赖包都改为CDN读取,前后打包对比:

    未使用CDN模式:

    parsed size

    大部分包使用CDN模式(严格来说,ng如此配置,除了加速,其他跟CDN一样):


    CDN parsed size

    打包后体积小了近170+kb,较原先的包小了近23%。顿时有点开心,优化了一大截

    但是真的优化了吗?

    于是放上服务器对比前后首次加载速度:

    未使用CDN模式:


    image.png

    约在1.9s~2.1s之间

    (自己的服务器,带宽较低,同样的包在公司测试服务器能有900ms~1.01s的速度,具体优化之前有文章提及如何优化的,在此不做赘述)

    大部分包使用CDN模式后:


    image.png

    包是小了,但是首次渲染时间竟然到8s了,excuse me ? 没优化都比优化快多了好嘛!

    即使是ng,没有CDN加速,也不至于吧

    分析原因,发现如果每个依赖包都用CDN模式,会加大网络request请求数量,时间就损耗在这里了,有些甚至才几十kb的,加载速度也跟几百kb相差无几,这就亏大了

    So接下来的策略应该是:

    通过BundleAnalyzerPlugin分析,哪些包特大,才采用CDN模式

    image.png

    那么就单对这个包进行CDN:

    image.png

    也小了100+kb,包体积10%左右的优化

    image.png

    速度也趋近于2s左右

    只优化了一个大包,原先的加载速度应该是在2.2s-2.3s之间,快了0.2s,加载速度提升9-10%左右,且如果使用加速后的CDN而非这种ng模拟的形式,应该会更快

    但最重要的在这里:

    如果是单域名,多个子域名伺服多个应用,那么采用了这种CDN形式,能让各个应用体积都减少10%,且节省已加载的共用包的加载时间!

    这就很可观了!

    比如,https://yingtai.tech/有多个子域名,伺服多个应用:

    https://yingtai.tech/first_app/
    https://yingtai.tech/second_app/
    https://yingtai.tech/third_app/
    ...
    N个应用都用到了对应的react,react-dom包,那么这N个应用各自可以减少10%的打包体积。
    同时:如果用户访问了first_app,然后访问second_app,由于设置了对应react,react-dom包的访问策略,在访问frist_app时,已经将公用包储存在本地,当访问second_app甚至其他类似的app情况下,会读取共用包本地缓存,那么当首次访问second_app,只需要加载second_app非共用的资源包即可

    只要访问过该域名下的某个应用一次,那么其访问该域名下的应用的首次加载时间将会对应减少

    按上面例子来说,假设访问a、b、c三个应用,三个应用共用一个包E,
    a应用首次访问耗时2.2s,此时去访问b或者c应用,同等网络情况下,必然比2.2s耗时小

    以另一个项目为例子:

    未CDN前:


    image.png

    加载速度:(带宽大点的服务器,确实快很多!)


    image.png
    CDN后:
    image.png

    加载速度:


    image.png

    之前是900ms ~ 1.1s左右,现在基本可以800ms~900ms,包体积小100kb+

    当然最看重的还是,统一域名下的其他应用,单烦用到相关的包,都能用本地缓存,节省首次加载时间

    附用到的附带命令:

    linux下载

    curl -O <对应的url>
    

    linux移动文件

    mv <source file> <target location>
    

    相关文章

      网友评论

          本文标题:前端性能优化 - CDN引入分析及实践

          本文链接:https://www.haomeiwen.com/subject/cmnirltx.html