PWA实践

PWA实践

引言

最近在搞基础框架,使用Docker部署到我1M带宽,1核CPU的阿里云上,在演示或者被别人打开的时候老是被吐槽加载太慢了,那么问题来了,怎么优化哪?

思考

  1. 硬件优化

我的阿里云硬件已经限制了我的带宽,扩容对我来说没必要,毕竟只是有人需要看得时候才访问,再者又不是要用流量挣钱,所以升级硬件不可能。

  1. Docker 优化

我的阿里云本来就是个喳喳机器,上面还跑着别的几个服务,每个有1-2各实例,再跑两个实例,估计连SSH都用不成了。下面是我docker-compose的配置。还有打包的镜像我用的是caddy,而且caddy也作了gzip压缩, 以下两段代码是我 docker-compose 和 caddy 的配置文件

docker-compose.yml

services:
  summit:
    image: gu****ab
    ports:
      - "80:80"
    deploy:
      mode: replicated
      replicas: 1
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
      update_config:
        parallelism: 1
        delay: 10s
      placement:
        constraints:
          - node.role == manager

Caddyfile

0.0.0.0:80
root /www
gzip
log stdout
errors stdout

/apiServer {
  gzip
  proxy / http://api.server.com/api {
    proxy_header Host {host}
    proxy_header X-Real-IP {remote}
    proxy_header X-Forwarded-Proto {scheme}
  }
}
  1. Webpack优化

Webpack的基础上优化已经达到极限了;各种文件已经经过webpack的Tree ShakingCode Splitting了,所以期待更强大的插件,同时也希望大佬推荐。

...
  entry: {
    app: ['@babel/polyfill', './src/index.tsx']
  },
  output: {
    filename: 'static/js/[name]_bundle.js',
    chunkFilename: 'static/js/[name]_bundle.js',
    path: path.resolve(__dirname, './build/'),
    publicPath: publicUrl
  },
  ...
  optimization: {
    splitChunks: {
      chunks: 'all',
      minSize: 30000,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      name: true,
      cacheGroups: {
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true,
          name: 'default'
        },
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10,
          name: 'vendors'
        }
      }
    },
    runtimeChunk: {
      name: 'runtime'
    }
  },
...
new WebpackParallelUglifyPlugin({
      uglifyES: {
        mangle: false,
        output: {
          beautify: false,
          comments: false
        },
        compress: {
          warnings: false,
          drop_console: true,
          collapse_vars: true,
          reduce_vars: true
        }
      }
    }),

size

  1. PWA--渐进式应用程序

年前的时候写过一篇PWA的文章,有兴趣的可以移步PWA基础知识整理及实践,在此抄一遍PWA的特性

PWA 的主要特点包括下面三点:
可靠 - 即使在不稳定的网络环境下,也能瞬间加载并展现
体验 - 快速响应,并且有平滑的动画响应用户的操作
粘性 - 像设备上的原生应用,具有沉浸式的用户体验,用户可以添加到桌面

有了PWA,能快速加载,还能离线使用,还有什么问题呢?想到了么,首屏加载!
的确,首屏加载依然是个问题,看了一下打包出来的文件的大小,是不是吓坏了? 但是不要怕,经过gzip压缩,到前端就不到1.5M了,那么接下来的问题就是第一次浏览比较慢,只能流失一部分用户了。那就开始实践吧。

分析

我们用的式ReactTypeScript, 而且我们用的是webpack, webpack打包出来的结果因为带了hash,所以每次结果都不一样,再者Service Worker的缓存列表是不支持正则表达式的,只能每个文件都写具体的文件名, 如果我们自己写一个service-worker.js,那我Server Worker的缓存列表是不可控的,所以只能借助第三方工具包,在npmjs.com 上搜了一下service worker,主流有两种,而sw-precache-webpack-plugin是第一个,按照我搜索第一的惯例,我肯定用sw-precache-webpack-plugin, 这个插件用起来还可以,配置也不是很多,在webpack里引入,然后加入plugin中,可以不写配置,最后在template.html中对service worker进行注册就可以。然而看到打包出来的结果我接受了

["/dist/style/4.css", "566bec76673f96860938dc6c4558d01a"],
    ["/dist/style/app.css", "f82983901e4266328c1af75d12ae1d88"],
    ["/dist/style/vendors.css", "dc3df81b3bb041761595338061eb28aa"],
    ["/home/c4/Desktop/Project/xxxxx/build/config.js", "b0ebcf61d580987a8b3b075bd6aeff6a"],
    ["/home/c4/Desktop/Project/xxxxx/build/index.html", "ffb440e6c16a845e9d017141cfd96970"]
  ],
  cacheName = "sw-precache-v3-sw-precache-webpack-plugin-" + (self.registration ? self.registration.scope : ""),
  ignoreUrlParametersMatching = [/^utm_/],
  addDirectoryIndex = function (e, a) {

有问题那就解决问题。我想了各种方法,各种谷歌,然而没有一个是成功的,最后无奈只能在这个库中开了一个issuse。最后说明一下, 这个问题是webpack中用了html-webpack-plugin 和 copy-webpack-plugin 造成的,如果你用了这两个库还要用sw-precache-webpack-plugin, 那就要小心了。

接下来就是第二个库workbox-webpack-plugin, 出自谷歌大厂,应该不会有问题,那就动手呗。

动手

官方文档写的太详细了,以至于我真的读不下去了。

  1. 安装
$ yarn add -D workbox-webpack-plugin
  1. webpack配置

当然这些配置实在生产环境中了哦。

...
const {GenerateSW} = require('workbox-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
....
module.exports = {
  ...

  plugins: [
    ...
    new CopyWebpackPlugin([{
      from: './public/config.js',
      to: path.resolve(__dirname, 'build'),
      toType: 'dir'
    }, {
      from: './public/manifest.json',
      to: path.resolve(__dirname, 'build'),
      toType: 'dir'
    }, {
      from: './public/icon.png',
      to: path.resolve(__dirname, 'build'),
      toType: 'dir'
    }, {
      from: './public/favicon.ico',
      to: path.resolve(__dirname, 'build'),
      toType: 'dir'
    }]),
    new GenerateSW({
      importWorkboxFrom: 'local', // 一定要用local,除非你的用户可以FQ
      skipWaiting: true,
      clientsClaim: true
    })
  ]
};

看结果

因为是内部项目就不录视频了,下面这张截图是我在浏览器中offline后,重新打开页面的效果。个人体验到,第二次之后打开,速度确实是不一般的快。

serviceworker

还有一张实在不想拿出来的图, lightHouse评测的结果。

lightHouse

总结

还是那句老话,前端坑太深了。回到正题,性能优化还有其他各种方案,以我现在的经历,只能想到这些解决方案。

路漫漫其修远兮 吾将上下而求索

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值