这几天玩了玩chatGpt,感觉非常好用,至少在编程方面可以比搜索引擎提供更方便的结果,虽然它不如人类的思想那么丰富,但是用它来查东西确实很方便,我觉得AI在创新方便是不如人类的,但是在逻辑和经验记忆上,AI可以不断地被训练、优化,如果有朝一日AI可以自己去创新,去任意的思考,那么或许那个时候AI就可以取代人类了。

在手机上使用Termux运行nodejs的egg服务时可以使用dev启动但是无法使用start,会一直显示waitting...!

为什么?起初以为是因为端口的问题,因为Termux权限的问题,手机没有root所以8000以上的端口才能自由使用!

但是指定了端口运行依旧是无法启动一直是waitting...,最后发现原来是cpu核心数的问题,因为egg使用start运行需要多个进程,比如主进程和守护进程,但是在Termux上没有root权限就无法获取cpu核心数,这就导致了egg的start在启动时一直不能获取cpu核心数!

解决办法:在启动参数上指定--workers=2,这样就能正常启动了!

今天是个节日,没有什么好说的啊,晚上本来想去看烟花,结果爸妈要去看,我顿时就不想去了,不过等他们出去我又觉得都出去看看也没什么,到广场跟去年我在那里看的是一样的,不过今天的我没有像去年那样,一个人看那么久的烟花,今天主要是来看人的,来凑热闹的,那么多的人,有各种各样的人,男女老少,说是广场,其实大体上算是个小市场,里面都是些小吃和生鲜市场,小吃摊人那么多,但是喜欢吃的就那么一两个。看人倒是很有意思的,比如有很多套圈圈的人,一般是中年人在套,小孩子看着,年轻人反而套的很少,是因为中年人需要解压吗?

哎这篇日记都拖到什么时候了,现在都是2月20号了,要把这种“拖时间”转化为强大的“能力”,把特别不好的变成特别好的!

今天是农历新年,在这新的兔年里祝我钱兔无量!家人朋友身体健康!世界和平!

早上去爷爷奶奶的公墓里拜年,在这四九天里,很冷,刮着的风吹在脸上更冷,不过太阳有着它的温度,在寒冷中夹带着一丝暖意。

下午家里吃饭,父母在这把岁数依旧忙碌着厨房里的食物,今天的家宴全部由他们完成,我想帮忙,又不想帮忙,他们也不让我帮忙,我愈发的好吃懒做了。菜品当中牛肉和黄焖羊肉都非常的好吃,炖的土豆和萝卜也非常的好吃,倘若在此之前我的生活是艰苦的,饮食是简陋的,那么我今天的幸福会成倍的增加吧。

幸运的不仅是父母的爱意,还有大家庭的关心,没有催婚,没有勾心斗角,有的是理解,有的是感慨,有的是玩笑,有的是祝福和勉励,怎么看来我都是幸福的,当然还害羞的收下了长辈们的压岁钱,哎,在我这个年龄还收压岁钱,实在是不好意思了,因为我的弟弟都没有收到压岁钱,只因为他已经在上班,而我一直在家考工作,待业也好,啃老也罢,我还是比较苦闷的,至于自己的努力,没有什么好说的,我没有什么努力,那我在苦闷些什么?考试的不如意,父母的不如愿,我是变得自私了么,父母的感恩教育,吃苦教育使得我变得反感了吗?他们是感恩的一代人,吃苦的一代人,父母对我的爱是无私的,我现在苦恼的是什么?是因为像小时候一样没有给我买心仪的玩具吗?今天舅舅跟我说要注重品德,要注重道义,接下来的人生靠天靠命,但也要自己努力,不努力只能怪自己。

父母有他们的局限性,我要靠运,父母对我的爱要牢记,要讲道义,只不过即使知道他们的爱意,也会在生活中的种种小事上产生不愉快,甚至反感和敌视。用交流解决吗?用爱解决吗?还是用行动解决?似乎没有什么好的办法,有一个办法或许可行,那就是屏蔽自我个体的意识,放下自我的利益,让父母的意识进来或者说按照父母的意志填充自己,这些不愉快的感觉或许是自我的反应机制造成的,个体之间的冲突,这里应当是纯精神上的冲突,我应当尝试多跟“自己”进行沟通,多聊一聊吧,或许所有外部的事情都可以通过对自己的结构从而直接或间接的去解决。

PWA是渐进式web应用程序,其实就是类似于小程序,h5APP,UniApp那样子的程序,通过本地系统的一些接口,结合web技术从而建立的一种web本地化的应用。

安装过程

因为我是通过vue来作为web设计的框架,所以就通过vue来安装

vue create xxx[项目名字]

这是vue通用的项目创建方式,虽然与pwa没什么关系,但是这其实就是写一个前端页面,最后安装pwa的模块,在本地生成一个manifest.json的配置文件,浏览器会自己识别这种web application,然后添加到主屏幕就好,当然不仅仅是manifest.json,这个文件主要是配置web app的应用名称,图标,前景色,背景色之类的,而安装pwa的模块还会为你配置service worker这样的本地缓存功能等待。

下面安装@ionic/vue

npm install @ionic/vue

记得要cd进入项目目录,这个@ionic/vue模块是ionic这个框架结合vue设计的模块,可以契合vue进行开发,里面像vue有一样,有自己写好的好看的组件,以及ionic-vue-router,这个也是结合vue-router封装的,所以项目中必须包含vue-router

我还是用ionic framework的框架结合vue来搭建我的pwa应用吧!这个ionic框架既可以在移动端的web跨平台还是很友好的,可以通过插件编译出ios,android平台的应用,以及设计适合以pwa形式的移动端app。

npm i -g @ionic/cli

安装ionic的脚手架

ionic start xxx项目名称

创建ionic的项目,当然它也可以跟一些参数如“--vue”,表示以vue的形式创建应用,不跟参数的话,回车后会有应用前端框架以及app形式的选择,按照提示进行即可。

vue add pwa

因为ionic是适配了三大前端框架,所以我选择了结合vue进行编写,所用再通过vue的脚手架安装vue所包含的pwa模块,安装这个模块后,会在项目src的目录下生成registerServiceWorker.ts的文件,类似于综合了一些serviceWorker的生命周期函数,可以在这个文件里可以缓存一些自己自定义的数据。而项目里vue的打包静态文件都会自动缓存,无需自行管理。当打包后,会在打包根目录下生成service-worker.js文件,用来注册使用serviceWorker。

当然对于service-worker这个API里面有好几个概念理解了两三天才有点了解,所以需要记录一下。

不过需要注意一点,需要在public目录下自己新建一个manifest.json的配置文件,pwa应用主要就是看这个配置文件,里面可以配置pwa应用的icon各种大小的配置,app名称,显示样式等等,不配置的话打包后会有一个默认的manifest.json配置生成,所以应当自己去手动创建!

更新缓存过程

这个更新过程是指项目静态资源打包后更新serviceWorker的意思。

首先我在自己的探索中,发现vue的pwa模块会自动缓存vue打包后所有的静态文件,但是在assets文件夹下似乎经支持一级目录,也就是assets/icon/*.png是支持serviceWorker缓存的,而二级目录以及多级目录是不支持缓存的,多级目录下的文件均不会缓存。

在src目录下,如果你自己创建了一些目录,如自己封装的请求模块或者单独的模块引入文件的话,如src/plugin/elementUI.js又或者src/request/myaxios.js这样的封装的文件,打包后也是可以进行serviceWorker缓存的。

vue打包后会对文件生成一个hash值作为标识,当你第一次将pwa项目上传后,用户第一次浏览时会自动缓存,至此用户再次打开项目网站时就会走缓存,离线状态下也可以显示,但是它是怎么对源站点文件进行对比的我还不是很了解,可能是对比打包文件的hash值,可是我在开发者工具中的网络里并没有发现哪儿对话进行了网络访问,因为所有的资源请求都走了serviceWorker。当你第二次上传新的打包好的项目后,用户再次打开你的项目网站,serviceWorker就会对新的文件进行下载和缓存,至此就要更新了!更新什么?更新缓存,更新页面,这里问题就来了,用户访问后serviceWorker会自己更新缓存,但是页面却不会更新,即使你刷新页面也是无济于事,除非使用ctrl F5进行强制刷新,或者关闭用户打开的所有关于你项目站点的标签页,然后新建标签页输入项目地址后,新更新的页面就可以正常显示了,这样的体验是很不好的,到底是什么原因呢?

原因就在于,已经打开的标签页一直使用的是旧的serviceWorker,而serviceWorker是独立的线程存在的,当serviceWorker在用户进入旧页面并更新了新页面的缓存,而此时页面的渲染还是使用旧的serviceWorker并且处于waiting的状态,而此时你的新serviceWorker并没有激活使用,只用当你关闭了所有项目的标签页,旧的serviceWorker就是自动结束并结束waiting状态,当你下一次打开网页时,浏览器就会使用新的serviceWorker,此时你的页面就更新了,这样的体验也是非常不好的,需要手动关闭,而在手机上操作问题会更麻烦一些,有什么办法能解决呢?

这里就是比较重要且有意思的地方了,并且还帮我又了解了一些javascript的面貌。

首先在registerServiceWorker.ts文件中有一个updated()函数,当serviceWorker更新后就会触发这个函数,这个函数是被封装过的,(这里还没有但需要了解一些workbox这个东西是什么)看一看源文件就可以发现这个函数是默认传入一个ServiceWorkerRegistration对象,所以代码如下:

updated (registration) { console.log('New content is available; please refresh.') document.dispatchEvent( new CustomEvent('swUpdated', {detail: registration}) ) }

这个函数传入了registration,并且在document中添加了一个自定义事件swUpdated,以便于在我们的页面文件中进行监听是否有更新。

在App.vue或者在项目首页.vue中进行更新事件的监听以及页面的更新,代码如下:

const registration = ref(null) //用于接收registration const updateExists = ref(false) //标记更新是否存在 const refreshing = ref(false) //标记是否刷新

function updateAvailable(event) { console.log(event) registration.value = event.detail updateExists.value = true }

document.addEventListener('swUpdated', updateAvailable, {once: true}) //对自定义swUpdated事件进行监听,如果有更新就调用上面的函数对是否更新的标识进行改变。

updateAvailable函数用于改变是否更新的变量,为了执行下面刷新的函数,

function refreshApp() { updateExists.value = false if (!registration.value || !registration.value.waiting) return registration.value.waiting.postMessage({type: 'SKIP_WAITING'}) }

navigator.serviceWorker.addEventListener('controllerchange', () => { if (refreshing.value) return refreshing.value = true window.location.reload() })

可以将上面的refreshApp绑定在页面更新的按钮上,这个函数里会检查registration是否存在并且跳过registration的wating状态,即更新serviceWorker,不再使用旧的serviceWorker,进而使用新的serviceWorker,而下面的serviceWorker.addEventListener函数用于监听“controllerchange”,只要serviceWorker有变化就会执行里面的函数,页面就会进行刷新,而此时刷新使用的是新的serviceWorker,所以页面刷新后就是新的页面,至此,pwa就实现了用户自行更新,且为热更新!

哦对了,上面的函数有一个registration.value.waiting.postMessage({type: 'SKIP_WAITING'})

其中postMessage是发送消息,在registration可以监听“message”,如果有"SKIP_WAITING"进行比对,成功就可以进行self.skipwating()函数进行serviceWorker的waiting状态跳转,进而刷新页面就好,之所以可以直接写“type: 'SKIP_WAITING'”是因为pwa模块或者workbox对serviceWorker进行了封装,就不需要自己进行配置了,没有的话可以在service-worker.js中进行添加(因为用pwa模块这个文件只有打包后才会生成,所以不知道在registerServiceWorker中能不能使用)

self.addEventListener('message', (event) => { if (event.data && event.data.type === 'SKIP_WAITING') { self.skipWaiting() } })

大功告成!