Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
@plugin-web-update-notification/vite
Advanced tools
Vite plugin for detect web page updates and notify.
English | 简体中文
Detect webpage updates and notify user to reload. support vite, umijs and webpack.
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).
When to check for updates (fetch version.json) ?
Some 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.
# vite
pnpm add @plugin-web-update-notification/vite -D
# umijs
pnpm add @plugin-web-update-notification/umijs -D
# webpack plugin
pnpm add @plugin-web-update-notification/webpack -D
index.html
caching!If 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.
To disable caching through nginx
:
# nginx.conf
location / {
index index.html index.htm;
if ( $uri = '/index.html' ) { # disabled index.html cache
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
try_files $uri $uri/ /index.html;
}
Directly disable caching through html meta
tags:
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
</head>
</html>
basic usage
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { webUpdateNotice } from '@plugin-web-update-notification/vite'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
webUpdateNotice({
logVersion: true,
}),
]
})
custom notification text
// vite.config.ts
export default defineConfig({
plugins: [
vue(),
webUpdateNotice({
notificationProps: {
title: 'system update',
description: 'System update, please refresh the page',
buttonText: 'refresh',
},
}),
]
})
internationalization
// vite.config.ts
export default defineConfig({
plugins: [
vue(),
webUpdateNotice({
// plugin preset: zh_CN | zh_TW | en_US
locale: "en_US",
localeData: {
en_US: {
title: "📢 system update",
description: "System update, please refresh the page",
buttonText: "refresh",
dismissButtonText: "dismiss",
},
zh_CN: {
...
},
...
},
}),
],
});
// other file to set locale
window.pluginWebUpdateNotice_.setLocale('zh_CN')
hidden default notification, listener to update event and custom behavior.
// vite.config.ts
export default defineConfig({
plugins: [
vue(),
webUpdateNotice({
hiddenDefaultNotification: true
}),
]
})
// other file to listener update event and custom behavior
document.body.addEventListener('plugin_web_update_notice', (e) => {
const { version, options } = e.detail
// write some code, show your custom notification and etc.
alert('System update!')
})
// .umirc.ts
import { defineConfig } from 'umi'
import type { Options as WebUpdateNotificationOptions } from '@plugin-web-update-notification/umijs'
export default {
plugins: ['@plugin-web-update-notification/umijs'],
webUpdateNotification: {
logVersion: true,
checkInterval: 0.5 * 60 * 1000,
notificationProps: {
title: 'system update',
description: 'System update, please refresh the page',
buttonText: 'refresh',
dismissButtonText: 'dismiss',
},
} as WebUpdateNotificationOptions
}
// vue.config.js(vue-cli project)
const { WebUpdateNotificationPlugin } = require('@plugin-web-update-notification/webpack')
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
// ...other config
configureWebpack: {
plugins: [
new WebUpdateNotificationPlugin({
logVersion: true,
}),
],
},
})
# nginx.conf
location / {
index index.html index.htm;
if ( $uri = '/index.html' ) { # disabled index.html cache
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
try_files $uri $uri/ /index.html;
}
function webUpdateNotice(options?: Options): Plugin
export interface Options {
/**
* support 'git_commit_hash' | 'svn_revision_number' | 'pkg_version' | 'build_timestamp' | 'custom'
* * if repository type is 'Git', default is 'git_commit_hash'
* * if repository type is 'SVN', default is 'svn_revision_number'
* * if repository type is 'unknown', default is 'build_timestamp'
* */
versionType?: VersionType
/**
* custom version, if versionType is 'custom', this option is required
*/
customVersion?: string
/** polling interval(ms)
* if set to 0, it will not polling
* @default 10 * 60 * 1000
*/
checkInterval?: number
/**
* check update when window focus
* @default true
*/
checkOnWindowFocus?: boolean
/**
* check update immediately after page loaded
* @default true
*/
checkImmediately?: boolean
/**
* check update when load js file error
* @default true
*/
checkOnLoadFileError?: boolean
/**
* whether to output version in console
*
* you can also pass a function to handle the version
* ```ts
* logVersion: (version) => {
* console.log(`version: %c${version}`, 'color: #1890ff') // this is the default behavior
* }
* ```
* @default true
*/
logVersion?: boolean | ((version: string) => void)
/**
* whether to silence the notification.
* 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
*/
silence?: boolean
/**
* @deprecated
*/
customNotificationHTML?: string
/** notificationProps have higher priority than locale */
notificationProps?: NotificationProps
notificationConfig?: NotificationConfig
/**
* preset: zh_CN | zh_TW | en_US
* @default 'zh_CN'
* */
locale?: string
/**
* custom locale data
* @link default data: https://github.com/GreatAuk/plugin-web-update-notification/blob/master/packages/core/src/locale.ts
*/
localeData?: LocaleData
/**
* Whether to hide the default notification, if you set it to true, you need to custom behavior by yourself
* ```ts
document.body.addEventListener('plugin_web_update_notice', (e) => {
const { version, options } = e.detail
// write some code, show your custom notification and etc.
alert('System update!')
})
* ```
* @default false
*/
hiddenDefaultNotification?: boolean
/**
* Whether to hide the dismiss button
* @default false
*/
hiddenDismissButton?: boolean
/**
* 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
*
* Base public path for inject file, Valid values include:
* * Absolute URL pathname, e.g. /foo/
* * Full URL, e.g. https://foo.com/
* * Empty string(default) or ./
*
* !!! Don't forget / at the end of the path
*/
injectFileBase?: string
}
export type VersionType = 'git_commit_hash' | 'pkg_version' | 'build_timestamp' | 'custom'
export interface NotificationConfig {
/**
* refresh button color
* @default '#1677ff'
*/
primaryColor?: string
/**
* dismiss button color
* @default 'rgba(0,0,0,.25)'
*/
secondaryColor?: string
/** @default 'bottomRight' */
placement?: 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight'
}
export interface NotificationProps {
title?: string
description?: string
/** refresh button text */
buttonText?: string
/** dismiss button text */
dismissButtonText?: string
}
export type LocaleData = Record<string, NotificationProps>
name | params | describe |
---|---|---|
window.pluginWebUpdateNotice_.setLocale | locale(preset: zh_CN、zh_TW、en_US) | set locale |
window.pluginWebUpdateNotice_.closeNotification | close notification | |
window.pluginWebUpdateNotice_.dismissUpdate | dismiss current update and close notification,same behavior as dismiss button | |
window.pluginWebUpdateNotice_.checkUpdate | manual check update, a function wrap by debounce(5000ms) |
interface Window {
pluginWebUpdateNotice_: {
/**
* set language.
* preset: zh_CN、zh_TW、en_US
*/
setLocale: (locale: string) => void
/**
* manual check update, a function wrap by debounce(5000ms)
*/
checkUpdate: () => void
/** dismiss current update and close notification, same behavior as dismiss the button */
dismissUpdate: () => void
/** close notification */
closeNotification: () => void
/**
* refresh button click event, if you set it, it will cover the default event (location.reload())
*/
onClickRefresh?: (version: string) => void
/**
* dismiss button click event, if you set it, it will cover the default event (dismissUpdate())
*/
onClickDismiss?: (version: string) => void
}
}
TypeScript
intellisense, if you use window.pluginWebUpdateNotice_.
or listener custom update event。
// src/shim.d.ts
// if you use vite plugin
/// <reference types="@plugin-web-update-notification/vite" />
// if you use umi plugin
/// <reference types="@plugin-web-update-notification/umijs" />
// if you use webpack plugin
/// <reference types="@plugin-web-update-notification/webpack" />
request version.json
file get 404 error
.
If you upload the production files bundled to cdn server:
// vite.config.ts
const prod = process.env.NODE_ENV === 'production'
const cdnServerUrl = 'https://foo.com/'
export default defineConfig({
base: prod ? cdnServerUrl : '/',
plugins: [
vue(),
webUpdateNotice({
injectFileBase: cdnServerUrl
})
]
})
Deploy the project in a non-root directory:
// vite.config.ts
const prod = process.env.NODE_ENV === 'production'
const base = '/folder/' // https://example.com/folder/
export default defineConfig({
base,
plugins: [
vue(),
webUpdateNotice({
injectFileBase: base
})
]
})
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
Custom notification button event.
// refresh button click event, if you set it, it will cover the default event (location.reload())
window.pluginWebUpdateNotice_.onClickRefresh = (version) => { alert(`click refresh btn: ${version}`) }
// dismiss button click event, if you set it, it will cover the default event (dismissUpdate())
window.pluginWebUpdateNotice_.onClickDismiss = (version) => { alert(`click dismiss btn: ${version}`) }
Custom notification style.
you can cover css styles with higher weights. (default css file)
<!-- notification html content -->
<div class="plugin-web-update-notice-anchor">
<div class="plugin-web-update-notice">
<div class="plugin-web-update-notice-content" data-cy="notification-content">
<div class="plugin-web-update-notice-content-title">
📢 system update
</div>
<div class="plugin-web-update-notice-content-desc">
System update, please refresh the page
</div>
<div class="plugin-web-update-notice-tools">
<a class="plugin-web-update-notice-btn plugin-web-update-notice-dismiss-btn">dismiss</a>
<a class="plugin-web-update-notice-btn plugin-web-update-notice-refresh-btn">
refresh
</a>
</div>
</div>
</div>
</div>
manual check update.
// vue-router check update before each route change
router.beforeEach((to, from, next) => {
window.pluginWebUpdateNotice_.checkUpdate()
next()
})
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.
webUpdateNotice({
...
silence: true
})
FAQs
Vite plugin for detect web page updates and notify.
We found that @plugin-web-update-notification/vite demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.