refresh frontend on backend restart, fix caching statics
This commit is contained in:
parent
968183d216
commit
f8be724e70
|
|
@ -0,0 +1,13 @@
|
||||||
|
"""middleware"""
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.utils.deprecation import MiddlewareMixin
|
||||||
|
|
||||||
|
|
||||||
|
class StartTimeMiddleware(MiddlewareMixin):
|
||||||
|
"""add a start time header"""
|
||||||
|
|
||||||
|
def __call__(self, request):
|
||||||
|
response = self.get_response(request)
|
||||||
|
response["X-Start-Timestamp"] = settings.TA_START
|
||||||
|
return response
|
||||||
|
|
@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/3.2/ref/settings/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
|
from datetime import datetime
|
||||||
from os import environ, path
|
from os import environ, path
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
@ -76,6 +77,7 @@ MIDDLEWARE = [
|
||||||
"django.middleware.security.SecurityMiddleware",
|
"django.middleware.security.SecurityMiddleware",
|
||||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||||
"corsheaders.middleware.CorsMiddleware",
|
"corsheaders.middleware.CorsMiddleware",
|
||||||
|
"config.middleware.StartTimeMiddleware",
|
||||||
"whitenoise.middleware.WhiteNoiseMiddleware",
|
"whitenoise.middleware.WhiteNoiseMiddleware",
|
||||||
"django.middleware.common.CommonMiddleware",
|
"django.middleware.common.CommonMiddleware",
|
||||||
"django.middleware.csrf.CsrfViewMiddleware",
|
"django.middleware.csrf.CsrfViewMiddleware",
|
||||||
|
|
@ -220,10 +222,13 @@ CORS_ALLOW_CREDENTIALS = True
|
||||||
CORS_ALLOW_HEADERS = list(default_headers) + [
|
CORS_ALLOW_HEADERS = list(default_headers) + [
|
||||||
"mode",
|
"mode",
|
||||||
]
|
]
|
||||||
|
CORS_EXPOSE_HEADERS = ["X-Start-Timestamp"]
|
||||||
|
|
||||||
|
|
||||||
# TA application settings
|
# TA application settings
|
||||||
TA_UPSTREAM = "https://github.com/tubearchivist/tubearchivist"
|
TA_UPSTREAM = "https://github.com/tubearchivist/tubearchivist"
|
||||||
TA_VERSION = "v0.5.8-unstable"
|
TA_VERSION = "v0.5.8-unstable"
|
||||||
|
TA_START = str(int(datetime.now().timestamp()))
|
||||||
|
|
||||||
# API
|
# API
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
|
|
|
||||||
|
|
@ -50,17 +50,21 @@ server {
|
||||||
root /app/static;
|
root /app/static;
|
||||||
index index.html;
|
index index.html;
|
||||||
|
|
||||||
location ~* .(?:css|js)$ {
|
location ~* ^/(?!static/|cache/).*\.(?:css|js|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
|
||||||
try_files $uri $uri/ /index.html =404;
|
try_files $uri $uri/ /index.html =404;
|
||||||
}
|
}
|
||||||
|
|
||||||
location = /index.html {
|
location = /index.html {
|
||||||
add_header Cache-Control 'no-store';
|
add_header Cache-Control "no-store, no-cache, must-revalidate";
|
||||||
|
add_header Pragma "no-cache";
|
||||||
|
add_header Expires 0;
|
||||||
expires 0;
|
expires 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
add_header Cache-Control 'no-store';
|
add_header Cache-Control "no-store, no-cache, must-revalidate";
|
||||||
|
add_header Pragma "no-cache";
|
||||||
|
add_header Expires 0;
|
||||||
try_files $uri $uri/ /index.html =404;
|
try_files $uri $uri/ /index.html =404;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import getFetchCredentials from '../configuration/getFetchCredentials';
|
||||||
import logOut from '../api/actions/logOut';
|
import logOut from '../api/actions/logOut';
|
||||||
import getCookie from './getCookie';
|
import getCookie from './getCookie';
|
||||||
import Routes from '../configuration/routes/RouteList';
|
import Routes from '../configuration/routes/RouteList';
|
||||||
|
import { useBackendStore } from '../stores/BackendStore';
|
||||||
|
|
||||||
export interface ApiClientOptions extends Omit<RequestInit, 'body'> {
|
export interface ApiClientOptions extends Omit<RequestInit, 'body'> {
|
||||||
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
||||||
|
|
@ -44,6 +45,12 @@ const APIClient = async <T>(
|
||||||
...options,
|
...options,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const backendTimestamp = response.headers.get('X-Start-Timestamp');
|
||||||
|
if (backendTimestamp) {
|
||||||
|
const { setStartTimestamp } = useBackendStore.getState();
|
||||||
|
setStartTimestamp(backendTimestamp);
|
||||||
|
}
|
||||||
|
|
||||||
// Handle common errors
|
// Handle common errors
|
||||||
if (response.status === 400) {
|
if (response.status === 400) {
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { create } from 'zustand';
|
||||||
|
|
||||||
|
interface BackendState {
|
||||||
|
startTimestamp: string | null;
|
||||||
|
setStartTimestamp: (timestamp: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useBackendStore = create<BackendState>((set, get) => ({
|
||||||
|
startTimestamp: null,
|
||||||
|
setStartTimestamp: timestamp => {
|
||||||
|
const prev = get().startTimestamp;
|
||||||
|
if (prev && prev !== timestamp) {
|
||||||
|
console.warn('Backend restart detected — reloading frontend...');
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
set({ startTimestamp: timestamp });
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
@ -8,14 +8,22 @@ export default defineConfig({
|
||||||
base: '/',
|
base: '/',
|
||||||
server: {
|
server: {
|
||||||
host: true,
|
host: true,
|
||||||
port: 3000, // This is the port which we will use in docker
|
port: 3000,
|
||||||
// Thanks @sergiomoura for the window fix
|
|
||||||
// add the next lines if you're using windows and hot reload doesn't work
|
|
||||||
watch: {
|
watch: {
|
||||||
usePolling: true,
|
usePolling: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
|
outDir: 'dist',
|
||||||
|
assetsDir: 'assets',
|
||||||
|
manifest: true,
|
||||||
|
rollupOptions: {
|
||||||
|
output: {
|
||||||
|
entryFileNames: 'assets/[name].[hash].js',
|
||||||
|
chunkFileNames: 'assets/[name].[hash].js',
|
||||||
|
assetFileNames: 'assets/[name].[hash].[ext]',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue