Skip to content

Commit

Permalink
ULMS-1075 Added cache-buster component
Browse files Browse the repository at this point in the history
  • Loading branch information
alexkonst committed Mar 25, 2021
1 parent 32edee5 commit 581959a
Show file tree
Hide file tree
Showing 9 changed files with 290 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"browser": true,
"jquery": true
},
"globals": {
"globalThis": true
},
"rules": {
"node/no-unsupported-features/es-syntax": 0,
"no-underscore-dangle": 0,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"preanalyze": "npm run build/dev",
"analyze": "source-map-explorer ./packages/*/es/index.js",
"prebootstrap": "rm -rf ./packages/**/.*.sw*",
"bootstrap": "lerna list | sed 's/@ulms\\/ui-//g' | xargs -I{} scripts/populate-rollup.sh {} && lerna bootstrap",
"bootstrap": "lerna list | sed 's/@ulms\\///g' | sed 's/ui-//g' | xargs -I{} scripts/populate-rollup.sh {} && lerna bootstrap",
"prebuild": "npm run prebootstrap",
"build": "lerna exec 'NODE_ENV=production npm run build'",
"build-storybook": "build-storybook",
Expand Down
1 change: 1 addition & 0 deletions packages/cache-buster/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.*.sw*
1 change: 1 addition & 0 deletions packages/cache-buster/es/.gitkeep
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

1 change: 1 addition & 0 deletions packages/cache-buster/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { CacheBuster } from './src/cache-buster'
51 changes: 51 additions & 0 deletions packages/cache-buster/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 33 additions & 0 deletions packages/cache-buster/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "@ulms/cache-buster",
"version": "1.0.0",
"description": "",
"keywords": [
"lerna"
],
"homepage": "https://github.com/netology-group/ulms-media-ui#readme",
"bugs": {
"url": "https://github.com/netology-group/ulms-media-ui/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/netology-group/ulms-media-ui.git"
},
"license": "MIT",
"author": "",
"main": "index.js",
"module": "es/index.js",
"files": [
"es",
"src"
],
"scripts": {
"build": "rm -rf ./es/* && BABEL_ENV=es rollup --config ./rollup.config.js index.js"
},
"dependencies": {
"react": "^16.12.0"
},
"peerDependencies": {
"react": "^15.6 || ^16.x || ^17.x"
}
}
133 changes: 133 additions & 0 deletions packages/cache-buster/src/cache-buster.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import React from 'react'

import { FetchVersionResolver, VersionChecker } from './utils'

const refresh = () => globalThis.location.reload()

class CacheBuster extends React.Component {
state = {
error: null,
loading: true,
versionMismatch: true,
}

constructor (props) {
super(props)

this.intervalId = null
this._versionChecker = null
}

componentDidMount () {
const {
interval, url, version: localVersion,
} = this.props

const resolver = new FetchVersionResolver(url)

this._versionChecker = new VersionChecker(resolver, localVersion)

if (interval) {
this.intervalId = setInterval(() => {
this._versionChecker.check()
.then(this.checkMajorVersion)
.catch((error) => {
// eslint-disable-next-line no-console
console.log('[CacheBuster] interval check error:', error)
})
}, interval * 1e3)
}

this._versionChecker.check()
.then(this.checkVersion)
.catch((error) => {
this.setState({
error,
loading: false,
versionMismatch: true,
})
})
}

componentWillUnmount () {
clearInterval(this.intervalId)

this.intervalId = null

if (this._versionChecker) {
this._versionChecker.destroy()

this._versionChecker = null
}
}

checkMajorVersion = (result) => {
const {
error, major, version,
} = result

if (error) {
// eslint-disable-next-line no-console
console.log('[CacheBuster] interval check error:', error)
} else if (major) {
// eslint-disable-next-line no-console
console.log(`[CacheBuster] app version ${version} - refresh needed (forced)`)

refresh()
}
}

checkVersion = (result) => {
const {
error, major, minor, patch, version,
} = result

if (error) {
// eslint-disable-next-line no-console
console.log('[CacheBuster] initial check error:', error)

this.setState({
error,
loading: false,
versionMismatch: true,
})

return
}

const versionMismatch = major || minor || patch

// eslint-disable-next-line no-console
console.log(`[CacheBuster] app version ${version} - ${versionMismatch ? 'refresh needed' : 'OK'}`)

this.setState({
error: null,
loading: false,
versionMismatch,
})
}

render () {
const { children } = this.props
const {
error,
loading,
versionMismatch,
} = this.state

return children({
error,
loading,
refresh,
versionMismatch,
})
}
}

CacheBuster.defaultProps = {
interval: 30,
url: '/meta.json',
version: '',
}

export { CacheBuster }
66 changes: 66 additions & 0 deletions packages/cache-buster/src/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/* eslint-disable max-classes-per-file */
function toSemver (versionStr) {
const [major, minor, patch] = versionStr.split('.')

return {
major,
minor,
patch,
}
}

export class FetchVersionResolver {
constructor (url, key = 'version') {
this._url = url
this._key = key
}

resolve () {
return fetch(this._url, { cache: 'no-cache' })
.then(response => response.json())
.then(response => response[this._key])
}
}

export class VersionChecker {
constructor (resolver, version) {
this._resolver = resolver
this._version = version

this._checkPromise = null
}

static compare (local, remote) {
const localVersion = toSemver(local)
const remoteVersion = toSemver(remote)

return {
major: localVersion.major !== remoteVersion.major,
minor: localVersion.minor !== remoteVersion.minor,
patch: localVersion.patch !== remoteVersion.patch,
}
}

check () {
if (!this._checkPromise) {
this._checkPromise = this._resolver.resolve()
.then((version) => {
this._checkPromise = null

return { version, ...VersionChecker.compare(this._version, version) }
})
.catch((error) => {
this._checkPromise = null

return { error }
})
}

return this._checkPromise
}

destroy () {
this._resolver = null
this._checkPromise = null
}
}

0 comments on commit 581959a

Please sign in to comment.