mirror of
https://github.com/modrinth/code.git
synced 2026-08-25 00:55:25 +00:00
perf: further reduce memory (#7015)
* feat: server source maps * perf: strip unused fields from search results * perf: reduce game version memory usage
This commit is contained in:
@@ -68,11 +68,16 @@ export interface GeneratedState extends GloballyUsedState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Composable for accessing the globally used generated state.
|
* Built once per module load rather than via `useState`, because every `useState` value is
|
||||||
* This includes both fetched data and runtime-defined constants.
|
* serialized into the SSR payload of every page. This is build-time constant data that the
|
||||||
|
* client already has via the static import above, so putting it in the payload would ship a
|
||||||
|
* second copy for no benefit.
|
||||||
|
*
|
||||||
|
* Consequence: on the server this object is shared by every request in the isolate, so it must
|
||||||
|
* stay immutable there. Runtime refreshes are client-only and go through `setGameVersions`.
|
||||||
*/
|
*/
|
||||||
export const useGeneratedState = () =>
|
const generatedState = shallowRef<GeneratedState>(
|
||||||
useState<GeneratedState>('generatedState', () => ({
|
Object.freeze({
|
||||||
// Cast JSON data to typed API responses
|
// Cast JSON data to typed API responses
|
||||||
categories: (categories ?? []) as Labrinth.Tags.v2.Category[],
|
categories: (categories ?? []) as Labrinth.Tags.v2.Category[],
|
||||||
loaders: (loaders ?? []) as Labrinth.Tags.v2.Loader[],
|
loaders: (loaders ?? []) as Labrinth.Tags.v2.Loader[],
|
||||||
@@ -147,4 +152,24 @@ export const useGeneratedState = () =>
|
|||||||
errors,
|
errors,
|
||||||
|
|
||||||
buildYear: new Date().getFullYear(),
|
buildYear: new Date().getFullYear(),
|
||||||
}))
|
}) as GeneratedState,
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Composable for accessing the globally used generated state.
|
||||||
|
* This includes both fetched data and runtime-defined constants.
|
||||||
|
*/
|
||||||
|
export const useGeneratedState = () => generatedState
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces the build-time game versions with a freshly fetched list. Client-only: mutating this
|
||||||
|
* on the server would leak across every request sharing the isolate.
|
||||||
|
*/
|
||||||
|
export function setGameVersions(versions: Labrinth.Tags.v2.GameVersion[]) {
|
||||||
|
if (import.meta.server) return
|
||||||
|
|
||||||
|
generatedState.value = Object.freeze({
|
||||||
|
...generatedState.value,
|
||||||
|
gameVersions: versions,
|
||||||
|
}) as GeneratedState
|
||||||
|
}
|
||||||
|
|||||||
@@ -228,6 +228,19 @@ function parseSearchParams(requestParams: string): Labrinth.Search.SearchParams
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search returns expanded dependency data that no card renders and that isn't part of
|
||||||
|
// ResultSearchProject. On modpacks it is ~90% of the response, and everything cached here
|
||||||
|
// is serialized into the SSR payload, so drop it before it reaches the query cache.
|
||||||
|
function stripUnrenderedFields(
|
||||||
|
hits: Labrinth.Search.v3.ResultSearchProject[],
|
||||||
|
): Labrinth.Search.v3.ResultSearchProject[] {
|
||||||
|
return hits.map((hit) => {
|
||||||
|
const { dependencies, dependency_project_ids, compatible_dependency_project_ids, ...rendered } =
|
||||||
|
hit as Labrinth.Search.v3.ResultSearchProject & Record<string, unknown>
|
||||||
|
return rendered as Labrinth.Search.v3.ResultSearchProject
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
async function fetchSearch(requestParams: string) {
|
async function fetchSearch(requestParams: string) {
|
||||||
debug('search() called', {
|
debug('search() called', {
|
||||||
requestParams: requestParams.substring(0, 100),
|
requestParams: requestParams.substring(0, 100),
|
||||||
@@ -241,17 +254,19 @@ async function fetchSearch(requestParams: string) {
|
|||||||
|
|
||||||
debug('search() response', { total_hits: raw.total_hits, hitCount: raw.hits?.length })
|
debug('search() response', { total_hits: raw.total_hits, hitCount: raw.hits?.length })
|
||||||
|
|
||||||
|
const hits = stripUnrenderedFields(raw.hits ?? [])
|
||||||
|
|
||||||
if (isServerType.value) {
|
if (isServerType.value) {
|
||||||
return {
|
return {
|
||||||
projectHits: [],
|
projectHits: [],
|
||||||
serverHits: raw.hits,
|
serverHits: hits,
|
||||||
total_hits: raw.total_hits,
|
total_hits: raw.total_hits,
|
||||||
per_page: raw.hits_per_page,
|
per_page: raw.hits_per_page,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
projectHits: raw.hits,
|
projectHits: hits,
|
||||||
serverHits: [],
|
serverHits: [],
|
||||||
total_hits: raw.total_hits,
|
total_hits: raw.total_hits,
|
||||||
per_page: raw.hits_per_page,
|
per_page: raw.hits_per_page,
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import type { Labrinth } from '@modrinth/api-client'
|
||||||
|
|
||||||
|
import { setGameVersions } from '~/composables/generated'
|
||||||
|
|
||||||
|
export default defineNuxtPlugin((nuxtApp) => {
|
||||||
|
// Deferred until after hydration: the server renders with the build-time game versions, so
|
||||||
|
// swapping them in during setup would make the first client render disagree with the markup.
|
||||||
|
nuxtApp.hook('app:suspense:resolve', async () => {
|
||||||
|
try {
|
||||||
|
const gameVersions = await $fetch<Labrinth.Tags.v2.GameVersion[]>('/api/tags/game-versions')
|
||||||
|
|
||||||
|
if (gameVersions && gameVersions.length > 0) {
|
||||||
|
setGameVersions(gameVersions)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[Game Version Updater] Failed to fetch:', error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
import type { Labrinth } from '@modrinth/api-client'
|
|
||||||
|
|
||||||
export default defineNuxtPlugin(async () => {
|
|
||||||
try {
|
|
||||||
const gameVersions = await $fetch<Labrinth.Tags.v2.GameVersion[]>('/api/tags/game-versions')
|
|
||||||
|
|
||||||
if (gameVersions && gameVersions.length > 0) {
|
|
||||||
const state = useState<{ gameVersions: Labrinth.Tags.v2.GameVersion[] }>('generatedState')
|
|
||||||
|
|
||||||
if (state.value) {
|
|
||||||
state.value.gameVersions = gameVersions
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('[Game Version Updater] Failed to fetch:', error)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
"routes": ["modrinth.com/*"],
|
"routes": ["modrinth.com/*"],
|
||||||
"preview_urls": true,
|
"preview_urls": true,
|
||||||
"workers_dev": true,
|
"workers_dev": true,
|
||||||
|
"upload_source_maps": true,
|
||||||
"limits": {
|
"limits": {
|
||||||
"cpu_ms": 5000
|
"cpu_ms": 5000
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user