PWA实践

简介: 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

总结

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

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

目录
相关文章
|
1月前
|
Rust 前端开发 开发者
探索前端技术发展趋势:从WebAssembly到PWA
【2月更文挑战第10天】随着互联网的快速发展,前端技术也在不断演进。本文将从WebAssembly和渐进式Web应用(PWA)两个方面探讨前端技术的发展趋势,分析它们对于前端开发的影响和未来发展潜力。
|
7月前
|
供应链 JavaScript 前端开发
业界三款主流的 PWA Storefront 概述
业界三款主流的 PWA Storefront 概述
138 0
|
7月前
|
JSON 缓存 搜索推荐
Progressive Web Apps(PWA):未来网络体验的崭新纪元
在当今数字化的世界中,Progressive Web Apps(PWA)已经成为了Web开发的一项重要趋势。PWA是一种结合了Web和原生应用程序优点的新型Web应用,它们提供了高性能、离线访问和优秀的用户体验。本博客将深入探讨PWA的概念、特点以及为什么它们对未来网络体验如此重要。
67 0
|
13天前
|
小程序 前端开发 JavaScript
微信小程序全栈开发中的PWA技术应用
【4月更文挑战第12天】本文探讨了微信小程序全栈开发中PWA技术的应用,PWA结合Web的开放性和原生应用的性能,提供离线访问、后台运行、桌面图标和原生体验。开发者可利用Service Worker实现离线访问,Worker处理后台运行,Web App Manifest添加桌面图标,CSS和JavaScript提升原生体验。实践中需注意兼容性、性能优化和用户体验。PWA技术能提升小程序的性能和用户体验,助力开发者打造优质小程序。
|
7天前
|
前端开发 JavaScript 开发工具
新一代前端开发工具:探索WebAssembly在前端领域的应用
本文将介绍WebAssembly在前端开发领域的应用,探讨其在提升前端性能、扩展开发语言选择、优化代码大小等方面的优势。通过深入分析WebAssembly的特性和优势,以及实际案例展示,帮助读者更好地理解和应用这一新一代前端开发工具。
|
1月前
|
编解码 前端开发 JavaScript
前端发展趋势:WebAssembly、PWA 和响应式设计
前端发展趋势:WebAssembly、PWA 和响应式设计
|
7月前
|
传感器 Web App开发 缓存
PWA 技术诞生的前世今生漫谈
PWA 技术诞生的前世今生漫谈
58 0
|
6月前
|
JSON 数据格式
关于 PWA 应用的可安装性
关于 PWA 应用的可安装性
30 0
|
7月前
|
存储 缓存 JSON
PWA 应用和原生应用的一些区别
PWA 应用和原生应用的一些区别
42 0
|
9月前
|
缓存 前端开发 API
前端的未来在哪里之PWA
PWA(Progressive Web App)作为一种新的前端开发技术,已经成为了前端开发的新趋势。它可以让应用程序在没有网络连接的情况下也可以正常运行,提高了用户的体验。
114 0