diff --git a/spec/dependencies_test.js b/spec/dependencies_test.js
index 8eedefa1349600e8b1ce860e44def5383ca257c5..f7b109a38e41152e2db4d50e8401edc0a129af55 100644
--- a/spec/dependencies_test.js
+++ b/spec/dependencies_test.js
@@ -1,4 +1,4 @@
-import { viteManifestToDeps } from '../src/manifests.js'
+import { viteManifestToDeps } from '../src/util.js'
 import { expect } from 'chai'
 
 describe('Vite manifest parsing', function () {
diff --git a/spec/manifest_parsing_test.js b/spec/manifest_parsing_test.js
index 89f980f03789df51a9697dab1b8e0d5e1b8ff478..bed5ecddbd3ca392265051e4fd4463e9b22dbc63 100644
--- a/spec/manifest_parsing_test.js
+++ b/spec/manifest_parsing_test.js
@@ -1,4 +1,4 @@
-import { viteToOxManifest } from '../src/manifests.js'
+import { viteToOxManifest } from '../src/util.js'
 import { expect } from 'chai'
 
 describe('Vite manifest parsing', function () {
diff --git a/spec/server_test.js b/spec/server_test.js
index a29dd3e1b3aaee28f8d3e720afadcb008fd74f67..08c4afa8ae40b8542a63b98f742c8f3f7bf80741 100644
--- a/spec/server_test.js
+++ b/spec/server_test.js
@@ -2,12 +2,13 @@ import request from 'supertest'
 import { generateSimpleViteManifest, mockApp, mockConfig, mockFetch } from './util.js'
 import { expect } from 'chai'
 import * as td from 'testdouble'
+import { Response } from 'node-fetch'
 
 describe('UI Middleware', function () {
   let app
   let fetchConfig
 
-  before(async function () {
+  beforeEach(async function () {
     mockConfig({ urls: ['http://ui-server/'] })
     mockFetch(fetchConfig = {
       'http://ui-server': {
@@ -18,11 +19,8 @@ describe('UI Middleware', function () {
     app = await mockApp()
   })
 
-  after(function () {
+  afterEach(function () {
     td.reset()
-  })
-
-  afterEach(async function () {
     process.env.CACHE_TTL = 30000
   })
 
@@ -80,6 +78,8 @@ describe('UI Middleware', function () {
         '/example.js': ''
       }
 
+      // trigger update
+      await request(app).get('/manifests')
       // wait some time
       await new Promise(resolve => setTimeout(resolve, 10))
 
@@ -87,6 +87,42 @@ describe('UI Middleware', function () {
       expect(response2.statusCode).to.equal(200)
       expect(response2.body).to.deep.equal([{ namespace: 'other', path: 'example' }])
     })
+
+    it('only updates the version hash when the caches are warm', async function () {
+      process.env.CACHE_TTL = 0
+
+      // fetch the file to get the initial version
+      let response = await request(app).get('/example.js')
+      expect(response.text).to.equal('')
+      const version = response.headers.version
+      await new Promise(resolve => setTimeout(resolve, 1))
+
+      // update resources
+      let resolveExampleJs
+      fetchConfig['http://ui-server'] = {
+        '/manifest.json': generateSimpleViteManifest({ 'example.js': 'other' }),
+        '/example.js': () => new Promise(resolve => (resolveExampleJs = resolve))
+      }
+
+      // fetch file again while the update is still processing
+      // this will also trigger the update
+      response = await request(app).get('/example.js')
+      expect(response.text).to.equal('')
+      expect(response.headers.version).to.equal(version)
+
+      // fetch once again. this will not trigger an update of the file-cache
+      response = await request(app).get('/example.js')
+      expect(response.text).to.equal('')
+      expect(response.headers.version).to.equal(version)
+
+      // resolve the response to the example js file. This will finish the cache warmup
+      resolveExampleJs(new Response('new content'))
+
+      // fetch the file again. Content and version should be updated
+      response = await request(app).get('/example.js')
+      expect(response.text).to.equal('new content')
+      expect(response.headers.version).not.to.equal(version)
+    })
   })
 
   describe('multiple configurations', function () {
diff --git a/src/createApp.js b/src/createApp.js
index 4841e0e3fac7d3f8d440959c933ec709dd863582..9ca9690c6c12ad34e82c4b872549e9f95a3a6e2a 100644
--- a/src/createApp.js
+++ b/src/createApp.js
@@ -18,9 +18,10 @@ import promClient from 'prom-client'
 import swaggerUi from 'swagger-ui-express'
 import yaml from 'js-yaml'
 import fs from 'fs'
-import { getCSSDependenciesFor, getDependencies, getOxManifests, getVersion, loadViteManifests, viteManifestToDeps } from './manifests.js'
+import { getCSSDependenciesFor, getDependencies, getOxManifests, getVersion, loadViteManifests } from './manifests.js'
 import { fileCache } from './files.js'
 import { getMergedMetadata } from './meta.js'
+import { viteManifestToDeps } from './util.js'
 
 const swaggerDocument = yaml.load(fs.readFileSync('./src/swagger.yaml', 'utf8'))
 
diff --git a/src/files.js b/src/files.js
index c264499ce8878bcf6abf7c8aae7348034db28843..d7b4af44af9e2dc99bae62500b32a4ed89de7071 100644
--- a/src/files.js
+++ b/src/files.js
@@ -3,7 +3,7 @@ import crypto from 'crypto'
 import { config } from './config.js'
 import promClient from 'prom-client'
 import { logger } from './logger.js'
-import { isJSFile } from './util.js'
+import { isJSFile, viteToOxManifest } from './util.js'
 
 async function fetchData (path, baseUrl, appendix) {
   const response = await fetch(new URL(path, baseUrl))
@@ -34,6 +34,10 @@ const fileErrorCounter = new promClient.Counter({
 class FileCache {
   constructor () {
     this._cache = {}
+    this._manifests = {}
+    this._hash = ''
+    this._dependencies = {}
+    this._oxManifests = {}
   }
 
   async warmUp (manifests, deps) {
@@ -69,7 +73,13 @@ class FileCache {
       fileCounter.inc(result.length)
       return result
     }()))
+
     this._cache = cache
+    this._manifests = manifests
+    this._hash = `${+new Date()}.${manifests.__hash__}`
+    this._dependencies = deps
+    this._oxManifests = viteToOxManifest(manifests)
+
     logger.debug('cache warmed up')
   }
 
@@ -85,6 +95,22 @@ class FileCache {
   get (path) {
     return this?._cache[path.slice(1)] || {}
   }
+
+  get manifests () {
+    return this?._manifests
+  }
+
+  get hash () {
+    return this?._hash
+  }
+
+  get dependencies () {
+    return this?._dependencies
+  }
+
+  get oxManifests () {
+    return this?._oxManifests
+  }
 }
 
 export const fileCache = new FileCache()
diff --git a/src/manifests.js b/src/manifests.js
index 07c61747bd3fb405d1a986262b676d8a31857951..6801ea15aa9ff9850ba8e9408f96addf95516a18 100644
--- a/src/manifests.js
+++ b/src/manifests.js
@@ -1,9 +1,8 @@
 import fetch from 'node-fetch'
-import path from 'path'
 import { URL } from 'url'
 import { fileCache } from './files.js'
 import { config } from './config.js'
-import { hash } from './util.js'
+import { hash, viteManifestToDeps } from './util.js'
 import { logger } from './logger.js'
 
 export const loadViteManifests = (() => {
@@ -74,81 +73,24 @@ export const loadViteManifests = (() => {
   }
 })()
 
-export function viteToOxManifest (viteManifests) {
-  const deps = viteManifestToDeps(viteManifests)
-  return Object.values(viteManifests)
-    .filter(manifest => Array.isArray(manifest?.meta?.manifests))
-    .map(manifest =>
-      manifest.meta.manifests.map(oxManifest => {
-        const dependencies = deps[manifest.file]
-        const data = {
-          ...oxManifest,
-          path: manifest.file.slice(0, -path.parse(manifest.file).ext.length)
-        }
-        if (dependencies?.length > 0) data.dependencies = dependencies
-        return data
-      })
-    )
-    .flat()
+export async function getOxManifests () {
+  await loadViteManifests().catch(() => {})
+  return fileCache.oxManifests
 }
 
-export const getOxManifests = (() => {
-  let prevHash
-  let oxManifestCache
-  return async function getOxManifests () {
-    const viteManifest = await loadViteManifests().catch(() => {})
-    if (viteManifest && viteManifest.__hash__ !== prevHash) {
-      oxManifestCache = viteToOxManifest(viteManifest)
-      prevHash = viteManifest.__hash__
-    }
-    return oxManifestCache
-  }
-})()
-
-export function viteManifestToDeps (viteManifest) {
-  const deps = {}
-  for (const [codePoint, { isEntry, file, imports, css, assets }] of Object.entries(viteManifest)) {
-    if (isEntry && codePoint.endsWith('.html')) deps[codePoint] = [file]
-    if (Array.isArray(assets)) assets.forEach(asset => { deps[asset] = [] })
-    if (Array.isArray(css)) css.forEach(css => { deps[css] = [] })
-    deps[file] = []
-      .concat(imports?.map(path => viteManifest[path].file))
-      .concat(css)
-      .concat(assets)
-      .filter(Boolean)
-  }
-  return deps
+export async function getDependencies () {
+  // simply catch the error here. This might happen, when one of the UI containers is temporarily not available
+  await loadViteManifests().catch(() => {})
+  return fileCache.dependencies
 }
 
-export const getDependencies = (() => {
-  let prevHash
-  let depCache
-  return async function getDependencies () {
-    // simply catch the error here. This might happen, when one of the UI containers is temporarily not available
-    const viteManifest = await loadViteManifests().catch(() => {})
-    if (viteManifest && viteManifest.__hash__ !== prevHash) {
-      depCache = viteManifestToDeps(viteManifest)
-      prevHash = viteManifest.__hash__
-    }
-    return depCache
-  }
-})()
-
 export async function getCSSDependenciesFor (file) {
   const allDependencies = await getDependencies()
   const dependencies = allDependencies[file] || []
   return dependencies.filter(dep => /\.css/i.test(dep))
 }
 
-export const getVersion = (() => {
-  let prevHash
-  let versionString
-  return async function getVersion () {
-    const viteManifest = await loadViteManifests().catch(() => {})
-    if (viteManifest && viteManifest.__hash__ !== prevHash) {
-      versionString = `${+new Date()}.${viteManifest.__hash__}`
-      prevHash = viteManifest.__hash__
-    }
-    return versionString
-  }
-})()
+export async function getVersion () {
+  await loadViteManifests().catch(() => {})
+  return fileCache.hash
+}
diff --git a/src/util.js b/src/util.js
index 55c804338bf0eb5c4a790b68187b7f9dacaf631a..018a517395797976d9b7e8c6b70b7c598e763e5b 100644
--- a/src/util.js
+++ b/src/util.js
@@ -21,3 +21,36 @@ export function isJSFile (name) {
   const extname = path.extname(name)
   return extname === '.js'
 }
+
+export function viteManifestToDeps (viteManifest) {
+  const deps = {}
+  for (const [codePoint, { isEntry, file, imports, css, assets }] of Object.entries(viteManifest)) {
+    if (isEntry && codePoint.endsWith('.html')) deps[codePoint] = [file]
+    if (Array.isArray(assets)) assets.forEach(asset => { deps[asset] = [] })
+    if (Array.isArray(css)) css.forEach(css => { deps[css] = [] })
+    deps[file] = []
+      .concat(imports?.map(path => viteManifest[path].file))
+      .concat(css)
+      .concat(assets)
+      .filter(Boolean)
+  }
+  return deps
+}
+
+export function viteToOxManifest (viteManifests) {
+  const deps = viteManifestToDeps(viteManifests)
+  return Object.values(viteManifests)
+    .filter(manifest => Array.isArray(manifest?.meta?.manifests))
+    .map(manifest =>
+      manifest.meta.manifests.map(oxManifest => {
+        const dependencies = deps[manifest.file]
+        const data = {
+          ...oxManifest,
+          path: manifest.file.slice(0, -path.parse(manifest.file).ext.length)
+        }
+        if (dependencies?.length > 0) data.dependencies = dependencies
+        return data
+      })
+    )
+    .flat()
+}