0


我把前端部署用户提醒做成了一个npm包

背景

最近发现很多手机APP和小程序在打开或者使用过程中会弹框提示用户新版本发布,是否更新。我就想着自己能不能实现一个。

点此跳转Github查看源码

功能要求

  • 纯前端实现,不限制框架用React、Vue、Angular都可
  • 不限制打包工具Webpack、Vite都可使用
  • 使用发布订阅模式实现,支持用户自定义更新提醒事件
  • 发布到npm,安装后开箱即用

功能实现

功能实现也非常简单,大致实现如下:

  1. 打包构建的时候拿到webpack或者vite的打包id,通过Node的fs模块将其放到打包(/dist)目录下(最好是可访问的静态资源里面,例如/public/config.json)。
// /public/config.json{hash:"123456"}
  1. 我们需要写一个webpack或者vite插件在打包构建完成后拿到hash生成文件,然后输出到/dist目录里,还好我们有unplugin,一套代码可以适配webpack、vite插件。> 注意:Webpack的afterEmit钩子里有提供当前打包构建的hash值,而Vite没有(希望只是我没有找到,有没有大佬告诉我Vite哪个钩子可以获取到打包构建的hash值)所以我是自己生成了uuid作为hash代码如下:import{ createUnplugin }from"unplugin"import{ writeFileSync, mkdirSync }from"node:fs"import path from"node:path"// 生成config.json文件constgenerateConfig=(configPath: string,hash: string)=>{// 确保目录存在mkdirSync(path.dirname(configPath),{recursive:true})writeFileSync( configPath,JSON.stringify({ hash,},null,2))}// filePath不传默认生成到/dist目录下exportdefaultcreateUnplugin((filePath: string ="config.json")=>{let viteOutDir ="dist"return{name:"unplugin-app-update",// 生成Vite插件vite:{configResolved(config){ viteOutDir = config.build.outDir },closeBundle(){const configPath = path.join(process.cwd(), viteOutDir, filePath)generateConfig(configPath,uuid())},},// 生成webpack插件webpack(compiler){// 只在生产模式下生成文件if(compiler.options.mode !=="production"){return} compiler.hooks.afterEmit.tap("unplugin-app-update",(compilation: any)=>{const configPath = path.join( compiler.options.output.path as string, filePath )generateConfig(configPath, compilation.hash)})},}})
  2. 然后前端通过轮询这个文件,对比hash有变化则打开一个弹窗提醒用户有新功能发布。 我用发布订阅模式写了一个AppUpdate的类去实现这个功能,。 首先我们需要有一个获取config.json配置文件的方法,为了不引入axios直接使用fetch API
exportclassAppUpdate{// 请求配置文件的url,默认不传请求url: http://your.website.com/config.jsonconstructor({url ="config.json"}){this.url = url
  }/* ... */asyncgetConfig(){const config =awaitfetch(this.url,{// 强制开启协商缓存headers:{"Cache-Control":"max-age=0"},}).then((res)=> res.text())returnJSON.parse(config)}/* ... */
  1. 然后我们需要在首次进入页面时加载一次当前配置文件获取初始hash值
asyncinit(){this.oldConfig =awaitthis.getConfig()}
  1. 开启轮询,对比hash是否变化
// 开始检查check(){this.stop()this.timer =setInterval(async()=>{this.newConfig =awaitthis.getConfig()this.compare()},this.interval)as unknown as number
}// 停止检查stop(){clearInterval(this.timer)}// 对比compare(){if(this.newConfig.hash ===this.oldConfig.hash){this.dispatch("notUpdate")}else{this.oldConfig =this.newConfig
    this.newConfig ={}this.dispatch("update")}}// 触发事件dispatch(key:"notUpdate"|"update"){this.callbacks[key]?.forEach((callback: AnyMethod)=>{callback()})}
  1. 支持用户自定义更新和未更新的事件回调
on(key:"notUpdate"|"update",callback: AnyMethod){;(this.callbacks[key]||(this.callbacks[key]=[])).push(callback)}off(key:"notUpdate"|"update",callback: AnyMethod){const index =(this.callbacks[key]||(this.callbacks[key]=[])).findIndex((item)=> item === callback
  )if(index !==-1){this.callbacks[key].splice(index,1)}}
  1. 默认添加应用更新弹窗提醒
exportclassAppUpdate{// 初始化constructor({
      url ="config.json",
      interval =30000,
      locate,
      custom =false,}){// 国际化,默认为当前浏览器语言if(locate){
        i18n.changeLanguage(locate)}this.url = url
      this.interval = interval
      // 初次获取config文件hash值this.init()// 开始轮询this.check()// 添加默认提醒事件,自定义设置可设置custom: trueif(!custom){this.on("update",()=>{if(!this.modal){this.modal = Modal.confirm({title: i18n.t("updateModelTitle"),content: i18n.t("updateModelContent"),style:{top:200,},okText: i18n.t("comfirm"),cancelText: i18n.t("cancel"),onOk:()=>{
                window.location.reload()},onCancel:()=>{this.modal =null},})}})}}/* ... */}

如何使用

安装

// npm
npm i unplugin-app-update -S// pnpm
pnpm i unplugin-app-update -S// yarn
yarn add unplugin-app-update

Webpack

// webpack.config.jsconst appUpdate =require("unplugin-app-update/webpack")

module.exports ={/* ... */plugins:[appUpdate('/path/to/config.json'),],}

Vite

// vite.config.tsimport appUpdate from"unplugin-app-update/vite"exportdefaultdefineConfig({plugins:[// default to the dist directoryappUpdate(),],})

入口配置

// main.js or index.jsimport{ AppUpdate }from"unplugin-app-update"const appUpdate =newAppUpdate({/* Options */})// 停止轮询// appUpdate.stop()// 继续轮询// appUpdate.check()// 事件:update, notUpdateconstupdate=()=>{
  console.log("Update")}// 自定义更新用户提醒
appUpdate.on("update", update)
appUpdate.on("notUpdate",()=>{
  console.log("Not Update")})// 解绑事件
appUpdate.off("update", update)

AppUpdate选项

属性类型描述默认值urlStringconfig.json配置文件url

config.json

intervalNumber轮询时间间隔

30000

locate

zh_CN

|

en_US

国际化

Default language of browser

customBoolean设置为true可删除默认弹出提醒,添加on(‘update’,fn)事件自定义弹出

false

注意

在本地开发时,需要在公共目录中放置一个config.json文件

手动更改哈希值以模拟项目构建

如果webpack或vite调整了公共目录,您应该新建AppUpdate({url:‘your/customer/path’)

// /public/config.json{hash:"123456"}

404错误

在生产和本地开发过程中,配置时经常遇到404错误。找不到json

// webpack.config.js or vite.config.ts{output:{// 修改打包后访问路径publicPath:"/",}}

最后

  1. 都看到这了,可以给我的Github仓库点个小小的Star吗?这真的对我很重要!重要!重要!欢迎给我提Issue、共建。
  2. 有兴趣可以加我微信号:vgbire,一起了解更多前端资讯。

在这里插入图片描述


本文转载自: https://blog.csdn.net/RkHker/article/details/141565626
版权归原作者 Vgbire 所有, 如有侵权,请联系我们删除。

“我把前端部署用户提醒做成了一个npm包”的评论:

还没有评论