分类 文章 下的文章

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

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

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

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

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() } })

大功告成!

PHP中的正则表达式使用的是Perl正则的标准,所以PHP中的正则表达式前后要加斜杠/,在后面的斜杠加i,如

/^[wx80-xff]$/i

则表示忽略大小写,如果后面是u,比如

/^[\x{4e00}-\x{9fa5}]+$/u

则表示是unicode(utf-8)编码解析,上面的表达式将匹配所有的中文字符串。

JavaScript中可以使用

/^[a-zA-Z0-9_\\-@.\u4e00\\-\u9fa5]+$/

注意减号-在“[]”中有时不连接如0-9这样的形式的话可能需要进行转义如“\-”

同时要注意一下,js中匹配正则和小程序中使用正则有些区别,小程序中会将正则表达式进行转义,所以不同环境要自己多试一试。

 

  1. 提高vistual studio installer的下载速度

打开站长之家的dns测试https://tool.chinaz.com/dns

download.visualstudio.microsoft.com查询地址找到好用一点的DNS,之后在etc/hosts文件中添加

113.96.140.104 download.visualstudio.microsoft.com

速度就会有所提升了,这个网上一搜有很多,不知道我在这里又记录一遍有没有意义。

composer的安装

在windows下只需要下载并允许composer的安装程序即可。

修改国内镜像

打开windows的powershell,执行以下命令,全局修改,将镜像修改为阿里云:

composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

创建项目,安装thinkPHP

composer create-project topthink/think

指定版本安装

composer create-project topthink/think=6.0

配置文件composer.json

该文件记录着项目中所使用的包,及版本等详细信息

安装需要的包

以下命令会自动创建composer.json(已经存在则不会创建)

composer require monolog/monolog

初始化项目的依赖包

以下命令在项目目录中会自动根据composer.json的依赖配置文件,自动下载依赖。

composer install