{"id":13417423,"url":"https://github.com/GreatAuk/plugin-web-update-notification","last_synced_at":"2025-03-15T02:31:19.881Z","repository":{"id":36964409,"uuid":"505248252","full_name":"GreatAuk/plugin-web-update-notification","owner":"GreatAuk","description":"Detect webpage updates and notify user to reload. support Vite, Umijs, and Webpack.","archived":false,"fork":false,"pushed_at":"2024-08-21T11:48:04.000Z","size":1519,"stargazers_count":471,"open_issues_count":13,"forks_count":38,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-09-30T23:24:06.870Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GreatAuk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-06-20T00:21:32.000Z","updated_at":"2024-09-25T12:33:18.000Z","dependencies_parsed_at":"2023-01-17T09:03:31.268Z","dependency_job_id":"cd2cc899-2bd6-4e1c-83be-b20b199b7c02","html_url":"https://github.com/GreatAuk/plugin-web-update-notification","commit_stats":{"total_commits":134,"total_committers":2,"mean_commits":67.0,"dds":0.02238805970149249,"last_synced_commit":"c64c82fb1b629eece091e78a2a36ff61c8b2b6e8"},"previous_names":[],"tags_count":40,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GreatAuk%2Fplugin-web-update-notification","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GreatAuk%2Fplugin-web-update-notification/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GreatAuk%2Fplugin-web-update-notification/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GreatAuk%2Fplugin-web-update-notification/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GreatAuk","download_url":"https://codeload.github.com/GreatAuk/plugin-web-update-notification/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243674825,"owners_count":20329167,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T22:00:36.970Z","updated_at":"2025-03-15T02:31:19.668Z","avatar_url":"https://github.com/GreatAuk.png","language":"TypeScript","readme":"English | [简体中文](./README.zh-CN.md)\n\n# plugin-web-update-notification\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://unpkg.com/@plugin-web-update-notification/core/dist/webUpdateNoticeInjectScript.js\" target=\"__blank\"\u003e\n      \u003cimg src=\"https://img.badgesize.io/https://unpkg.com/@plugin-web-update-notification/core/dist/webUpdateNoticeInjectScript.js?compression=gzip\u0026style=flat-square\" alt=\"Gzip Size\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://www.npmjs.com/package/@plugin-web-update-notification/core\" target=\"__blank\"\u003e\n      \u003cimg src=\"https://img.shields.io/npm/v/@plugin-web-update-notification/core.svg?style=flat-square\u0026colorB=51C838\" alt=\"NPM Version\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://www.npmjs.com/package/@plugin-web-update-notification/core\" target=\"__blank\"\u003e\u003cimg alt=\"NPM Downloads\" src=\"https://img.shields.io/npm/dm/@plugin-web-update-notification/core?color=50a36f\u0026label=\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/GreatAuk/plugin-web-update-notification/blob/master/LICENSE\"\u003e\n      \u003cimg src=\"https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square\" alt=\"License\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/GreatAuk/plugin-web-update-notification/discussions\" target=\"__blank\"\u003e\n      \u003cimg src=\"https://img.shields.io/badge/discussions-on%20github-blue?style=flat-square\u0026colorB=51C838\" alt=\"discussions-image\" /\u003e\n    \u003c/a\u003e\n    \u003cbr\u003e\n\u003c/p\u003e\n\n\nDetect webpage updates and notify user to reload. support vite, umijs and webpack.\n\n\u003e Take the git commit hash (also support svn revision number、package.json version、build timestamp、custom) as the version number, and write version into json file. The client polls the version of the server (visibilitychange or focus event assistant), compares it with the local one, and if it is not the same, notifies the user to refresh the page (you can custom behavior).\n\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"180\" src=\"https://raw.githubusercontent.com/GreatAuk/plugin-web-update-notification/master/images/vue_example.webp\"\u003e\n  \u003cimg width=\"180\" src=\"https://raw.githubusercontent.com/GreatAuk/plugin-web-update-notification/master/images/react_example.webp\"\u003e\n  \u003cimg width=\"180\" src=\"https://raw.githubusercontent.com/GreatAuk/plugin-web-update-notification/master/images/svelte_example.webp\"\u003e\n  \u003cimg width=\"180\" src=\"https://raw.githubusercontent.com/GreatAuk/plugin-web-update-notification/master/images/react_umi_example.webp\"\u003e\n\u003c/p\u003e\n\n**When to check for updates (fetch version.json)** ?\n\n1. first load page.\n2. poll (default: 10 * 60 * 1000 ms).\n3. script resource loading failure detected (404 ?).\n4. when the tab page is refocus or revisible.\n\n## Why\n\nSome users do not have the habit of closing web pages. If the front-end page is updated, the user page has always been a historical version, any there may be report an error (file 404) or a white screen.\n\n## Install\n\n```bash\n# vite\npnpm add @plugin-web-update-notification/vite -D\n\n# umijs\npnpm add @plugin-web-update-notification/umijs -D\n\n# webpack plugin\npnpm add @plugin-web-update-notification/webpack -D\n```\n\n## Usage\n\n[vite](#vite) | [umi](#umijs) | [webpack](#webpack)\n\n### Important: Disable `index.html` caching!\n\nIf `index.html` is cached, the update notification may still appear after refreshing, so it is necessary to disable the caching of `index.html`. This is also a best practice for deploy SPA applications.\n\nTo disable caching through `nginx`:\n\n```nginx\n# nginx.conf\nlocation / {\n  index index.html index.htm;\n\n  if ( $uri = '/index.html' ) { # disabled index.html cache\n    add_header Cache-Control \"no-cache, no-store, must-revalidate\";\n  }\n\n  try_files $uri $uri/ /index.html;\n}\n```\n\nDirectly disable caching through `html meta` tags:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n\u003chead\u003e\n\n  \u003cmeta http-equiv=\"Cache-Control\" content=\"no-cache, no-store, must-revalidate\" /\u003e\n  \u003cmeta http-equiv=\"Pragma\" content=\"no-cache\" /\u003e\n  \u003cmeta http-equiv=\"Expires\" content=\"0\" /\u003e\n\n\u003c/head\u003e\n\u003c/html\u003e\n```\n\n### Vite\n\n**basic usage**\n\n```ts\n// vite.config.ts\nimport { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\nimport { webUpdateNotice } from '@plugin-web-update-notification/vite'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  plugins: [\n    vue(),\n    webUpdateNotice({\n      logVersion: true,\n    }),\n  ]\n})\n```\n\n**custom notification text**\n\n```ts\n// vite.config.ts\nexport default defineConfig({\n  plugins: [\n    vue(),\n    webUpdateNotice({\n      notificationProps: {\n        title: 'system update',\n        description: 'System update, please refresh the page',\n        buttonText: 'refresh',\n      },\n    }),\n  ]\n})\n```\n\n**internationalization**\n\n```ts\n// vite.config.ts\nexport default defineConfig({\n  plugins: [\n    vue(),\n    webUpdateNotice({\n      // plugin preset: zh_CN | zh_TW | en_US\n      locale: \"en_US\",\n      localeData: {\n        en_US: {\n          title: \"📢 system update\",\n          description: \"System update, please refresh the page\",\n          buttonText: \"refresh\",\n          dismissButtonText: \"dismiss\",\n        },\n        zh_CN: {\n          ...\n        },\n        ...\n      },\n    }),\n  ],\n});\n\n\n// other file to set locale\nwindow.pluginWebUpdateNotice_.setLocale('zh_CN')\n```\n\n**hidden default notification, listener to update event and custom behavior.**\n\n```ts\n// vite.config.ts\nexport default defineConfig({\n  plugins: [\n    vue(),\n    webUpdateNotice({\n      hiddenDefaultNotification: true\n    }),\n  ]\n})\n\n// other file to listener update event and custom behavior\ndocument.body.addEventListener('plugin_web_update_notice', (e) =\u003e {\n  const { version, options } = e.detail\n  // write some code, show your custom notification and etc.\n  alert('System update!')\n})\n```\n\n### Umijs\n\n```ts\n// .umirc.ts\nimport { defineConfig } from 'umi'\nimport type { Options as WebUpdateNotificationOptions } from '@plugin-web-update-notification/umijs'\n\nexport default {\n  plugins: ['@plugin-web-update-notification/umijs'],\n  webUpdateNotification: {\n    logVersion: true,\n    checkInterval: 0.5 * 60 * 1000,\n    notificationProps: {\n      title: 'system update',\n      description: 'System update, please refresh the page',\n      buttonText: 'refresh',\n      dismissButtonText: 'dismiss',\n    },\n  } as WebUpdateNotificationOptions\n}\n```\n\n### webpack\n\n```js\n// vue.config.js(vue-cli project)\nconst { WebUpdateNotificationPlugin } = require('@plugin-web-update-notification/webpack')\nconst { defineConfig } = require('@vue/cli-service')\n\nmodule.exports = defineConfig({\n  // ...other config\n  configureWebpack: {\n    plugins: [\n      new WebUpdateNotificationPlugin({\n        logVersion: true,\n      }),\n    ],\n  },\n})\n```\n\n### suggest: disabled index.html cache\n\n```nginx\n# nginx.conf\nlocation / {\n  index index.html index.htm;\n\n  if ( $uri = '/index.html' ) { # disabled index.html cache\n    add_header Cache-Control \"no-cache, no-store, must-revalidate\";\n  }\n\n  try_files $uri $uri/ /index.html;\n}\n```\n\n\n\n## webUpdateNotice Options\n\n```ts\nfunction webUpdateNotice(options?: Options): Plugin\n\nexport interface Options {\n  /**\n   * support 'git_commit_hash' | 'svn_revision_number' | 'pkg_version' | 'build_timestamp' | 'custom'\n   * * if repository type is 'Git', default is 'git_commit_hash'\n   * * if repository type is 'SVN', default is 'svn_revision_number'\n   * * if repository type is 'unknown', default is 'build_timestamp'\n   * */\n  versionType?: VersionType\n  /**\n   * custom version, if versionType is 'custom', this option is required\n   */\n  customVersion?: string\n  /** polling interval（ms）\n   * if set to 0, it will not polling\n   * @default 10 * 60 * 1000\n   */\n  checkInterval?: number\n  /**\n   * check update when window focus\n   * @default true\n   */\n  checkOnWindowFocus?: boolean\n  /**\n   * check update immediately after page loaded\n   * @default true\n   */\n  checkImmediately?: boolean\n  /**\n   * check update when load js file error\n   * @default true\n   */\n  checkOnLoadFileError?: boolean\n  /**\n   * whether to output version in console\n   *\n   * you can also pass a function to handle the version\n   * ```ts\n   * logVersion: (version) =\u003e {\n   *  console.log(`version: %c${version}`, 'color: #1890ff') // this is the default behavior\n   * }\n   * ```\n   * @default true\n   */\n  logVersion?: boolean | ((version: string) =\u003e void)\n  /**\n   * whether to silence the notification.\n   * such as when local version is v1.0, you can set this option to true and build a new version v1.0.1, then the notification will not show\n   */\n  silence?: boolean\n  /**\n   * @deprecated\n   */\n  customNotificationHTML?: string\n  /** notificationProps have higher priority than locale */\n  notificationProps?: NotificationProps\n  notificationConfig?: NotificationConfig\n  /**\n   * preset: zh_CN | zh_TW | en_US\n   * @default 'zh_CN'\n   * */\n  locale?: string\n  /**\n   * custom locale data\n   * @link default data: https://github.com/GreatAuk/plugin-web-update-notification/blob/master/packages/core/src/locale.ts\n   */\n  localeData?: LocaleData\n  /**\n   * Whether to hide the default notification, if you set it to true, you need to custom behavior by yourself\n   * ```ts\n    document.body.addEventListener('plugin_web_update_notice', (e) =\u003e {\n      const { version, options } = e.detail\n      // write some code, show your custom notification and etc.\n      alert('System update!')\n    })\n   * ```\n   * @default false\n   */\n  hiddenDefaultNotification?: boolean\n  /**\n   * Whether to hide the dismiss button\n   * @default false\n   */\n  hiddenDismissButton?: boolean\n  /**\n   * After version 1.2.0, you not need to set this option, it will be automatically detected from the base of vite config、publicPath of webpack config or publicPath of umi config\n   *\n   * Base public path for inject file, Valid values include:\n   * * Absolute URL pathname, e.g. /foo/\n   * * Full URL, e.g. https://foo.com/\n   * * Empty string(default) or ./\n   *\n   * !!! Don't forget / at the end of the path\n  */\n  injectFileBase?: string\n}\n\nexport type VersionType = 'git_commit_hash' | 'pkg_version' | 'build_timestamp' | 'custom'\n\nexport interface NotificationConfig {\n  /**\n   * refresh button color\n   * @default '#1677ff'\n  */\n  primaryColor?: string\n  /**\n   * dismiss button color\n   * @default 'rgba(0,0,0,.25)'\n  */\n  secondaryColor?: string\n  /** @default 'bottomRight' */\n  placement?: 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight'\n}\n\nexport interface NotificationProps {\n  title?: string\n  description?: string\n  /** refresh button text */\n  buttonText?: string\n  /** dismiss button text */\n  dismissButtonText?: string\n}\n\nexport type LocaleData = Record\u003cstring, NotificationProps\u003e\n```\n\n## export Functions\n| name                                            | params                              | describe                                                     |\n| ----------------------------------------------- | ----------------------------------- | ------------------------------------------------------------ |\n| window.pluginWebUpdateNotice_.setLocale         | locale(preset: zh_CN、zh_TW、en_US) | set locale                                                   |\n| window.pluginWebUpdateNotice_.closeNotification |                                     | close notification                                           |\n| window.pluginWebUpdateNotice_.dismissUpdate     |                                     | dismiss current update and close notification,same behavior as dismiss button |\n| window.pluginWebUpdateNotice_.checkUpdate       |                                     | manual check update, a function wrap by debounce(5000ms)     |\n```ts\ninterface Window {\n  pluginWebUpdateNotice_: {\n    /**\n       * set language.\n       * preset: zh_CN、zh_TW、en_US\n      */\n    setLocale: (locale: string) =\u003e void\n    /**\n     * manual check update, a function wrap by debounce(5000ms)\n     */\n    checkUpdate: () =\u003e void\n    /** dismiss current update and close notification, same behavior as dismiss the button */\n    dismissUpdate: () =\u003e void\n    /** close notification */\n    closeNotification: () =\u003e void\n    /**\n     * refresh button click event, if you set it, it will cover the default event (location.reload())\n     */\n    onClickRefresh?: (version: string) =\u003e void\n    /**\n     * dismiss button click event, if you set it, it will cover the default event (dismissUpdate())\n     */\n    onClickDismiss?: (version: string) =\u003e void\n  }\n}\n```\n\n## What was changed\n\n![inject_content](https://raw.githubusercontent.com/GreatAuk/plugin-web-update-notification/master/images/inject_content.webp)\n\n## Q\u0026A\n\n1. `TypeScript` intellisense, if you use `window.pluginWebUpdateNotice_.` or listener custom update event。\n\n   ```ts\n   // src/shim.d.ts\n\n   // if you use vite plugin\n   /// \u003creference types=\"@plugin-web-update-notification/vite\" /\u003e\n\n   // if you use umi plugin\n   /// \u003creference types=\"@plugin-web-update-notification/umijs\" /\u003e\n\n   // if you use webpack plugin\n   /// \u003creference types=\"@plugin-web-update-notification/webpack\" /\u003e\n   ```\n\n2. request `version.json` file get `404 error`.\n\n   If you upload the production files bundled to cdn server:\n\n   ```ts\n   // vite.config.ts\n\n   const prod = process.env.NODE_ENV === 'production'\n\n   const cdnServerUrl = 'https://foo.com/'\n\n   export default defineConfig({\n     base: prod ? cdnServerUrl : '/',\n     plugins: [\n       vue(),\n       webUpdateNotice({\n         injectFileBase: cdnServerUrl\n       })\n     ]\n   })\n   ```\n\n   Deploy the project in a non-root directory:\n\n   ```ts\n   // vite.config.ts\n\n   const prod = process.env.NODE_ENV === 'production'\n\n   const base = '/folder/' // https://example.com/folder/\n\n   export default defineConfig({\n     base,\n     plugins: [\n       vue(),\n       webUpdateNotice({\n         injectFileBase: base\n       })\n     ]\n   })\n   ```\n\n   \u003e After version 1.2.0, in most case, you not need to set injectFileBase, it will be automatically detected from the base of vite config、publicPath of webpack config or publicPath of umi config\n\n3. Custom notification button event.\n\n   ```ts\n   // refresh button click event, if you set it, it will cover the default event (location.reload())\n   window.pluginWebUpdateNotice_.onClickRefresh = (version) =\u003e { alert(`click refresh btn: ${version}`) }\n\n   // dismiss button click event, if you set it, it will cover the default event (dismissUpdate())\n   window.pluginWebUpdateNotice_.onClickDismiss = (version) =\u003e { alert(`click dismiss btn: ${version}`) }\n   ```\n\n4. Custom notification style.\n\n   you can cover css styles with higher weights. ([default css file](https://github.com/GreatAuk/plugin-web-update-notification/blob/master/packages/core/public/webUpdateNoticeInjectStyle.css))\n\n   ```html\n   \u003c!-- notification html content --\u003e\n\n   \u003cdiv class=\"plugin-web-update-notice-anchor\"\u003e\n     \u003cdiv class=\"plugin-web-update-notice\"\u003e\n       \u003cdiv class=\"plugin-web-update-notice-content\" data-cy=\"notification-content\"\u003e\n         \u003cdiv class=\"plugin-web-update-notice-content-title\"\u003e\n           📢  system update\n         \u003c/div\u003e\n         \u003cdiv class=\"plugin-web-update-notice-content-desc\"\u003e\n           System update, please refresh the page\n         \u003c/div\u003e\n         \u003cdiv class=\"plugin-web-update-notice-tools\"\u003e\n           \u003ca class=\"plugin-web-update-notice-btn plugin-web-update-notice-dismiss-btn\"\u003edismiss\u003c/a\u003e\n           \u003ca class=\"plugin-web-update-notice-btn plugin-web-update-notice-refresh-btn\"\u003e\n             refresh\n           \u003c/a\u003e\n         \u003c/div\u003e\n       \u003c/div\u003e\n     \u003c/div\u003e\n   \u003c/div\u003e\n   ```\n\n5. manual check update.\n\n   ```ts\n   // vue-router check update before each route change\n   router.beforeEach((to, from, next) =\u003e {\n     window.pluginWebUpdateNotice_.checkUpdate()\n     next()\n   })\n   ```\n\n6. Some versions do not notify. For example, if the customer version is `v1.0`, you need to update to `v1.0.1`, but do not want to display the update prompt.\n\n   ```ts\n   webUpdateNotice({\n     ...\n     silence: true\n   })\n   ```\n\n## License\n\n[MIT](./LICENSE)\n","funding_links":[],"categories":["Plugins","TypeScript"],"sub_categories":["Framework-agnostic Plugins"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGreatAuk%2Fplugin-web-update-notification","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FGreatAuk%2Fplugin-web-update-notification","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGreatAuk%2Fplugin-web-update-notification/lists"}