内容简介:在上一篇文章这是一个移动端的pwa应用,使用react,typescript,react-redux,react-router,workbox 基于create-react-app 开发。可以添加到主屏幕,可以断网条件下正常打开和访问数据。项目地址:typescript是JavaScript的超级,一方面在typescript中我们可以使用最新的特性,另一方面typescript给我们带来了类型系统,可以让我们写出健壮的代码,避免一些潜在的运行时错误。在create-react-app中使用typescr
在上一篇文章 记一次基于react、cra2、typescript的pwa项目由开发到部署(一) 中,我们了解到了create-react-app 给我们提供了哪些pwa支持,也了解到了有哪些不足。虽然create-react-app会帮我们自动生成一个service-worker.js 去缓存我们的app shell,但是并没有提供让开发者定制service worker的方法,除非我们eject项目,这篇文章继续往下讲,把在这个项目中学到的东西分享给大家。
项目回顾
这是一个移动端的pwa应用,使用react,typescript,react-redux,react-router,workbox 基于create-react-app 开发。可以添加到主屏幕,可以断网条件下正常打开和访问数据。项目地址: browseExpbyReact
使用typescript
typescript是JavaScript的超级,一方面在typescript中我们可以使用最新的特性,另一方面typescript给我们带来了类型系统,可以让我们写出健壮的代码,避免一些潜在的运行时错误。在create-react-app中使用typescript,官网推荐我们使用的是 create-react-app的ts版本 ,他会帮你配置好typescript的相关配置,并使用react-script-ts代替react-script来驱动项目。但是这个版本的更新会稍稍滞后于原版,而且也不利于我们扩展脚手架的配置,所以这里不推荐使用。我们使用 react-app-rewired 来进行配置。
react-app-rewired
在create-react-app中修改默认配置有两种常用的方法,
- 一种是 eject 项目,eject会把我们的脚手架中的配置暴露出来,然后我们就可以去修改了,但是这是一个不可逆的过程,而且讲配置暴露出来也是一个不优雅的做法,所以不推荐。
- 第二种就是利用 react-app-rewired 去修改我们的配置,他可以让我们在不eject项目的前提下修改我们的配置。比如配置typescript,我们可以找到对应的插件 react-app-rewire-typescript 进行配置。具体可参考本项目
利用workbox 定制自己的service worker
这里到了本文的重点:如何在create-react-app中定制自己的service-worker.js。目前的cra引用了Workbox webpack plugin 代替了先前的 sw-precache-webpack-plugin。我们可以借助 react-app-rewired 去改写默认的Workbox webpack plugin 配置。主要步骤:
- 在 react-app-rewired 的配置文件 config.overrides.js 中修改 Workbox webpack plugin的配置
- 在public文件目录下建立自己的service-worker配置文件
首先在 config.overrides.js 中配置,替换默认的workbox-webpack-plugin配置:
/* config-overrides.js */ // typescript的配置插件 const rewireTypescript = require('react-app-rewire-typescript'); const workboxPlugin = require('workbox-webpack-plugin') const path = require('path') module.exports = { webpack: function (config, env) { // typescript的配置插件 config = rewireTypescript(config, env); if (env === 'production') { // 在 ‘production’ 模式下加入自己的配置 const workboxConfigProd = { swSrc: path.join(__dirname, 'public', 'cus-service-worker.js'), swDest: 'cus-service-worker.js', importWorkboxFrom: 'disabled' } // 删除默认的WorkboxWebpackPlugin配置 config = removePreWorkboxWebpackPluginConfig(config) // 加入我们的配置 config.plugins.push(new workboxPlugin.InjectManifest(workboxConfigProd)) } return config } } // 此函数用来找出 默认配置中的 WorkboxWebpackPlugin, 并把它删除 function removePreWorkboxWebpackPluginConfig (config) { const preWorkboxPluginIndex = config.plugins.findIndex((element) => { return Object.getPrototypeOf(element).constructor.name === 'GenerateSW' }) if (preWorkboxPluginIndex !== -1) { config.plugins.splice(preWorkboxPluginIndex, 1) } return config } 复制代码
这部分的配置大概意思就是,当环境为生成环境时,找出webpack中关于workbox-webpack-plugin的配置,把它删掉,然后用自己的配置替代它。
这里解释一下 removePreWorkboxWebpackPluginConfig 这个函数。我们可以自己用create-react-app新建一个无用的项目,然后eject它,那么我们可以在暴露出来的config文件夹下的 webpack.config.prod.js 中看到关于 workbox-webpack-plugin 的配置
new WorkboxWebpackPlugin.GenerateSW({ clientsClaim: true, exclude: [/\.map$/, /asset-manifest\.json$/], importWorkboxFrom: 'cdn', navigateFallback: publicUrl + '/index.html', navigateFallbackBlacklist: [ // Exclude URLs starting with /_, as they're likely an API call new RegExp('^/_'), // Exclude URLs containing a dot, as they're likely a resource in // public/ and not a SPA route new RegExp('/[^/]+\\.[^/]+$'), ], }), 复制代码
所以我们可以通过下面这段代码找到这段配置的位置:
// 对plugins数组调用findIndex方法,找到构造函数的name属性为‘GenerateSW’的成员 const preWorkboxPluginIndex = config.plugins.findIndex((element) => { return Object.getPrototypeOf(element).constructor.name === 'GenerateSW' }) // 删除这个成员 if (preWorkboxPluginIndex !== -1) { config.plugins.splice(preWorkboxPluginIndex, 1) } 复制代码
替换掉workbox-webpack-plugin的配置后,根据自己的配置在public目录下新建cus-service-worker.js文件,这个文件会代替默认生成的service-worker.js文件,我们就可以通过配置cus-service-worker.js来定制自己的pwa配置了,而且cus-service-worker.js 里的内容也是有讲究的,以本项目为例:
// 引入workbox全局变量 importScripts('https://storage.googleapis.com/workbox-cdn/releases/3.4.1/workbox-sw.js'); if (workbox) { console.log(`Yay! Workbox is loaded :tada:`); } else { console.log(`Boo! Workbox didn't load :grimacing:`); } // set the prefix and suffix of our sw's name workbox.core.setCacheNameDetails({ prefix: 'browse-exp', suffix: 'v1.0.0', }); // have our sw update and control a web page as soon as possible. workbox.skipWaiting(); workbox.clientsClaim(); // 将静态资源进行预缓存 self.__precacheManifest = [].concat(self.__precacheManifest || []); workbox.precaching.suppressWarnings(); workbox.precaching.precacheAndRoute(self.__precacheManifest, {}); // 定制自己的需求 // cache our data, and use networkFirst strategy. workbox.routing.registerRoute( new RegExp('.*experiments\?.*'), workbox.strategies.networkFirst() ); workbox.routing.registerRoute( new RegExp('.*experiments/\\d'), workbox.strategies.networkFirst() ) workbox.routing.registerRoute( new RegExp('.*experiment_types.*'), workbox.strategies.networkFirst() ) 复制代码
首先通过importScripts 引入workbox全局变量。在打包的时候,脚手架会为我们生成一个 precache-manifest列表,里面会列举一系列的静态文件,我们可以通过 self.__precacheManifest 拿到这个列表, 所以我们需要通过一下语句预缓存这些静态资源:
self.__precacheManifest = [].concat(self.__precacheManifest || []); workbox.precaching.suppressWarnings(); workbox.precaching.precacheAndRoute(self.__precacheManifest, {}); 复制代码
然后就是为了尽快的让我们的service worker控制页面,我们可以在开头加入一下语句:
// 跳过等待 workbox.skipWaiting(); // 控制客户端 workbox.clientsClaim(); 复制代码
剩下的部分自己就可以按自己的需求进行发挥了,像要什么功能就配置什么功能,这里的话我为自己获取数据的路由进行了缓存,采用的是 networkFirst 策略,什么是networkFirst策略呢?就是首先会进行网络请求,如果失败的话再使用缓存中的数据。
当我们打包项目的时候,就会发现再build文件下,会生成一个cus-service-worker.js文件,并且再开头多了一句:
importScripts("/precache-manifest.cd8115bc0ff644d6d74bec08ffcbdeb4.js"); 复制代码
这就是我们可以通过 self.__precacheManifest 拿到预缓存列表的原因。
到目前为止:我们已经可以定制自己的service-worker.js了。
manifest.json
manifest.json可以让我们的web app添加到桌面,再create-react-app中配置manifest非常简单,直接再public目录下的manifest.json配置就可以了,关于什么么配置项,可以到这里谷歌官网教程查看,另外manifest.json的配置不会马上生效,需要在https协议下,多次进入该网页的时候才会弹出添加到桌面的提示。
总结:
- 利用 react-app-rewired 改写我们的配置
- 在 config.overrides.js 中替换默认的 WorkboxWebpackPlugin 的配置
- 在 public 目录下编写自己的pwa配置
到这里我们可以在create-react-app生成的脚手架中定制自己的pwa配置了,在 下一篇文章 中,我会继续讲解:
- 如何部署将该项目部署到nginx服务器上。
- 为它配置证书,让它运行在https协议上。
- 体验该pwa项目。
感兴趣的同学可以扫描下面二维码体验项目:
note:
- 建议用uc浏览器打开,因为uc浏览器对pwa的支持较好。
- "添加到桌面的提示" 需要短时间多次进入web app 才会触发
项目地址: browseExpByReact 如果感兴趣,可以对比着基于vue的实现来看: browseExpByVue
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- linux 部署golang 项目(直接部署和基于nginx部署)
- 【Vue项目总结】项目nginx部署
- CentOS 部署 flask项目
- Docker 部署Python项目
- 【前端打包部署】谈一谈我在SPA项目打包=>部署的处理
- 「实战篇」开源项目docker化运维部署-后端java部署(七)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。