PWA实践
PWA实践
引言
最近在搞基础框架,使用Docker部署到我1M带宽,1核CPU的阿里云上,在演示或者被别人打开的时候老是被吐槽加载太慢了,那么问题来了,怎么优化哪?
思考
- 硬件优化
我的阿里云硬件已经限制了我的带宽,扩容对我来说没必要,毕竟只是有人需要看得时候才访问,再者又不是要用流量挣钱,所以升级硬件不可能。
- 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} } }
- Webpack优化
在Webpack的基础上优化已经达到极限了;各种文件已经经过webpack的Tree Shaking 和 Code 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 } } }),
- PWA--渐进式应用程序
年前的时候写过一篇PWA的文章,有兴趣的可以移步PWA基础知识整理及实践,在此抄一遍PWA的特性
PWA 的主要特点包括下面三点:
可靠 - 即使在不稳定的网络环境下,也能瞬间加载并展现
体验 - 快速响应,并且有平滑的动画响应用户的操作
粘性 - 像设备上的原生应用,具有沉浸式的用户体验,用户可以添加到桌面
有了PWA,能快速加载,还能离线使用,还有什么问题呢?想到了么,首屏加载!
的确,首屏加载依然是个问题,看了一下打包出来的文件的大小,是不是吓坏了? 但是不要怕,经过gzip压缩,到前端就不到1.5M了,那么接下来的问题就是第一次浏览比较慢,只能流失一部分用户了。那就开始实践吧。
分析
我们用的式React 和 TypeScript, 而且我们用的是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, 出自谷歌大厂,应该不会有问题,那就动手呗。
动手
官方文档写的太详细了,以至于我真的读不下去了。
- 安装
$ yarn add -D workbox-webpack-plugin
- 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后,重新打开页面的效果。个人体验到,第二次之后打开,速度确实是不一般的快。
还有一张实在不想拿出来的图, lightHouse评测的结果。
总结
还是那句老话,前端坑太深了。回到正题,性能优化还有其他各种方案,以我现在的经历,只能想到这些解决方案。
路漫漫其修远兮 吾将上下而求索

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
阿里云容器Kubernetes监控(五) - 离线存储与归档Kubernetes事件
前言 在上一篇文章中,向大家介绍了如何通过eventer将Kubernetes中的事件告警到钉钉群中,那么如何将这些非常有价值的事件进行离线存储与归档呢? 目前eventer支持elasticsearch、influxdb、kafka、sls四种离线存储的链路。具体的配置方式可以参考如下文档。今天主要讲解如何通过SLS归档Kubernetes的事件。 操作方式 1.登陆SLS控制台并创建project与logstore。 2.通过容器服务部署中的使用模板创建下发eventer apiVersion: extensions/v1beta1 kind: Deployment metadata: name: kube-eventer namespace: kube-system spec: replicas: 1
- 下一篇
hadoop,spark,Zookeeper,,, 这些名字都是怎么来的呢?
Apache 首先我们要明白,Apache 是一个 http 服务器,而我们熟悉的另一种说法"Apache Hadoop"中的 Apache 则指的是 Apache 软件基金会。"Apache"是 Apache 软件基金会中的一个项目。 关于其名字,流传最广的解释是(也是最显而易见的):这个名字来自于一个事实:当Apache在1995年初开发的时候,它是由当时最流行的HTTP服务器NCSA HTTPd 1.3的代码修改而成的,因此是“一个修补的(a patchy)”服务器。 然而,在Apache服务器官方网站的FAQ中是这么解释的:“Apache这个名字是为了纪念名为Apache的美洲原住民印第安人的一支,众所周知他们拥有高超的作战策略和无穷的耐性。”贝伦多夫说:“我选择阿帕奇这个名字是取其积极含义。阿帕奇族是最后一个屈服于美国政府的民族。当时我们担心大公司迟早会参与竞争并‘教化’这块最早的网络之地,所以在我看来,阿帕奇是个很好的名称,也有人说这个词一语双关-因为正如Apache(与"a patchy"谐音)的名字所表明的那样,他们确实是在给服务器打补丁。” Hadoop 说起 had...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- 设置Eclipse缩进为4个空格,增强代码规范
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS6,CentOS7官方镜像安装Oracle11G
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2全家桶,快速入门学习开发网站教程
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装