Get Rewarded! We will reward you with up to €50 credit on your account for every tutorial that you write and we publish!

Erstellen eines live Versions-Checks für SPA Anwendungen

profile picture
Author
Thomas Schäfer
Published
2021-09-08
Time to read
7 minutes reading time

About the author- My life for Aiur

Einleitung

In diesem Tutorial möchte ich das Problem lösen, dass Benutzerinnen alte Versionen deiner Web App nutzen. Das kann z.B. dann passieren, wenn Benutzerinnen nicht mitbekommen, dass eine neue Version verfügbar gemacht wurde, während die App benutzt wird. Als Beispielanwendung wird eine React App genutzt, aber nach diesem Tutorial solltest du die gelernten Prinzipien auf alle npm basierten Single Page Applications anwenden können.

Voraussetzungen

  • Grundlegende JavaScript/ReactJS Kenntnisse
  • Grundlegende npm Kenntnisse
  • Ein klein bisschen bash
  • npm und git

Schritt 1 - Das Projekt aufsetzen

Anmerkung: Du kannst auch ein bereits bestehendes Projekt benutzen, welches mit create-react-app aufgesetzt wurde und diesen Schritt überspringen.

Im ersten Schritt setzen wir das projekt mit create-react-app auf. Wenn du npx create-react-app version-check-example --use-npm in der Kommandozeile ausführst, wird ein Ordner version-check-example mit allen notwendigen React Dependencies und npm Konfigurationen erstellt. Es wird außerdem ein git Repository und npm Projekt initialisiert.

Schritt 2 - Während der Laufzeit die Versionsnummer benutzen

Unsere Quelle für die Versionsnummer unserer App ist das "version" Feld in der package.json Datei. Nach dem Anlegen des neuen Projekts ist diese standardmäßig "version": "0.1.0" und wird hochgezählt während du deine App etnwickelst.

Wenn das Projekt gebaut wird (npm build), kann dank npm die Umgebungsvariable namens $npm_package_version verwendet werden. Diese können wir jedoch noch nicht in unserer React App verwenden. Dafür müssen wir eine datei .env im Projektordner erstellen und die folgende Zeile einfügen:

REACT_APP_VERSION=$npm_package_version

Alle Variablen in dieser Datei, welche mit REACT_APP anfangen, werden (dank webpack) unserer App während der Laufzeit zur Verfügung stehen. Unsere Variable kann nun folgendermaßen verwendet werden:

const version = process.env.REACT_APP_VERSION

Schritt 3 - (Regelmäßige) Versionsprüfung

In diesem Schritt erstellen wir ein Script, welches die neueste Versionsnummer vom Server lädt und sie mit der aktuellen Clientversion abgleicht. Dieses Script kann anschließend periodisch aufgerufen werden.

Zuerst legen wir deine Datei an, die die neuste Versionsummer enthält. Diese können wir dann in unserer App abrufen und mit der Clientversion vergleichen. Im nächsten Schritt wird diese Datei automatische erstellt. Wir legen nun also eine Datei namens version im public Ordner ab und fügen den folgenden Inhalt (die aktuelle Versionsnummer) ein:

0.1.0

Wichtig: Die Datei darf außer der aktuellen Version keine weiteren Zeichen wie Leerzeichen oder Zeilenumbrüche enthalten.

Danach erstellen wir eine Datei namens version-check.js im src/utils Ordner mit folgendem Inhalt:

// Lädt die derzeitige App Versionsnummer vom Server und gibt sie als String zurück
const fetchVersion = async () => {
  const response = await fetch('/version')
  if (!response.ok) {
    throw new Error('Error fetching version')
  }
  return response.text()
}

export const checkForNewVersion = async () => {
  // lade die Versionsnummer vom Server
  let serverVersion
  try {
    serverVersion = await fetchVersion()
  } catch (error) {
    console.error(error)
    return
  }
  // Vergleiche die Versionsnummer vom server mit der vom Client
  // Du könntest außerdem selbst einen Test hinzufügen um zu prüfen ob die Server version tatsächlich neuer ist, als die Clientversion
  // Damit verhindert man Probleme z.B. mit alten Versionen im Cache des Servers
  if (process.env.REACT_APP_VERSION === serverVersion) {
    return
  }
  // Zeige eine Benachrichtigung
  window.alert('Eine neue Version der Anwendung ist verfügbar. Bitte laden Sie die Seite neu.')
}

Anmerkung: create-react-app stellt im Entwicklungsprozess (mit npm run start) alle Dateien im public Ordner zur Verfügung. Deshalb kann mit fetch('/version') die Datei geladen werden. In Production muss diese Datei vom Server bereitgestellt werden. Hier kannst du mehr darüber erfahren.

Die Funktion checkForNewVersion kann nun an einer beliebigen Stelle in der Anwendung periodisch aufgerufen werden, z.B. in der Datei src/App.js:

import React, { useEffect } from 'react'
import checkForNewVersion from './utils/checkForNewVersion'

export const App = () => {
  // Erstelle ein Intervall wenn die Komponente im Browser eingebunden wird und prüfe die Version alle 5 Minuten
  useEffect(() => {
    const interval = setInterval(checkForNewVersion, 5 * 60 * 1000) // prüfe alle 5 Minuten
    // Lösche das Intervall, wenn die Komponente entfernt wird
    return () => clearInterval(interval)
  }, [])

  return (
    <div>...</div>
  )
}

Wenn du nun die App mit npm run start startest und dann den Inhalt der Datei public/version zu 0.1.1 änderst, sollte 5 Minuten nachdem du die App geladen hast, ein Alert-Fenster angezeigt werden.

Schritt 4 - Automatisches Generieren und Aktualisieren der Versionsdatei basierend auf der aktuellen Version

npm bietet uns die Möglichkeit die Version unserer App zu verwalten. Diese Version kann durch folgende Befehle erhöht werden:

  • npm version major
  • npm version minor
  • npm version patch

npm erhöht nun die Versionsnummer in der package.json Datei entsprechend der Semantic Versioning Regeln.

Immer wenn npm version ausgeführt wird, werden zusätzlich bestimmte Scripte ausgeführt, welche in der package.json Datei angegeben werden können:

  • preversion
  • version
  • postversion

Wir erstellen jetzt ein bash Script, welches den Wert der Umgebungsvariable $npm_package_version in die public/version Datei schreibt. Das Script legen wir im scripts Ordner ab und nennen es version.sh.

echo -n $npm_package_version > public/version
git add public/version
  • Die erste Zeile schreibt den Wert der Variable $npm_package_version in die Datei public/version
  • Die zweite Zeile fügt die Änderungen zu git hinzu, sodass die diese beim von npm erstellten git tag einbezogen werden

Danach fügen wir die folgende Zeile zum scripts Bereich der Datei package.json hinzu:

"version": "bash ./scripts/version.sh"

Anmerkung: Es kann sein, dass die Datei version.sh erst ausführbar gemacht werden muss, z.B. indem man chmod +x scripts/version.sh ausführt.

Step 5 - Testen

Führe npm version patch in der Kommandozeile aus. Dies sollte das version Feld in der Datei package.json (und package-lock.json) von 0.1.0 auf 0.1.1 aktualisieren. Der Inhalt der Datei public/version sollte nun ebenfalls 0.1.1 sein.

Wenn du git log in der Kommandozeile ausführst, sollte dort außerdem der folgende Eintrag angezeigt werden:

commit your-commit-hash (HEAD -> master, tag: v0.1.1)
...

Fazit

Wir haben einen automatisierten Prozess erstellt, der Benutzer*innen benachrichtigt, sobald eine neue Version der App veröffentlicht wurde. Immer wenn die Version mit npm version [major/minor/patch] geändert wird, wird ein Script ausgeführt, welches automatisch die Versionsdatei aktualisiert, die Änderungen in git übernimmt und einen git tag erstellt.

Die App lädt periodisch über einen Endpunkt die Versionsnummer und vergleicht sie mit der lokalen Version, welche derzeit im Browser läuft. Unterscheiden sich die Versionen, werden nun die Benutzer*innen benachrichtigen, und zum neu laden der Anwendung aufgefordert.

License: MIT
Want to contribute?

Get Rewarded: Get up to €50 in credit! Be a part of the community and contribute. Do it for the money. Do it for the bragging rights. And do it to teach others!

Report Issue

Discover our

Dedicated Servers

Configure your dream server. Top performance with an excellent connection at an unbeatable price!

Want to contribute?

Get Rewarded: Get up to €50 credit on your account for every tutorial you write and we publish!

Find out more