Optimize SSR pt. 2
Some checks failed
E2E Tests / e2e (push) Has been cancelled
Tests and checks on push / run-checks-and-tests (push) Has been cancelled
Updates translation progress / update-translation-progress-issue (push) Has been cancelled

This commit is contained in:
Kalle
2026-08-21 17:40:47 +03:00
parent dabf58177b
commit d4450e2cfb
4 changed files with 180 additions and 15 deletions

View File

@@ -146,16 +146,23 @@ export function findLayoutDataByIdentifier(
)
.whereRef("VideoMatchPlayer.playerUserId", "=", "User.id")
.as("vodsCount"),
// authored and tagged art counted via an indexed union: an OR spanning
// Art and ArtUserMetadata would make SQLite scan the whole Art table
eb
.selectFrom("Art")
.leftJoin("ArtUserMetadata", "ArtUserMetadata.artId", "Art.id")
.innerJoin("UserSubmittedImage", "UserSubmittedImage.id", "Art.imgId")
.select(({ fn }) => fn.count<number>("Art.id").distinct().as("count"))
.where((innerEb) =>
innerEb.or([
innerEb("Art.authorId", "=", eb.ref("User.id")),
innerEb("ArtUserMetadata.userId", "=", eb.ref("User.id")),
]),
.select(({ fn }) => fn.countAll<number>().as("count"))
.where("Art.id", "in", (innerEb) =>
innerEb
.selectFrom("Art")
.select("Art.id")
.whereRef("Art.authorId", "=", "User.id")
.union(
innerEb
.selectFrom("ArtUserMetadata")
.select("ArtUserMetadata.artId as id")
.whereRef("ArtUserMetadata.userId", "=", "User.id"),
),
)
.as("artCount"),
])

View File

@@ -0,0 +1,156 @@
diff --git a/dist/cjs/i18next.js b/dist/cjs/i18next.js
index 6cdf84263936193ff243df98546da3e9104ab24c..1169f1f82abd621a40f8bc75bc62374d24e73a1d 100644
--- a/dist/cjs/i18next.js
+++ b/dist/cjs/i18next.js
@@ -531,6 +531,41 @@ class Translator extends EventEmitter {
};
}
translate(keys, o, lastKey) {
+ if (lastKey === undefined && typeof keys === 'string') {
+ let ck = null;
+ if (o === undefined) {
+ ck = `${this.language}\u0001\u0001\u0001\u0001${keys}`;
+ } else if (typeof o === 'object' && o !== null) {
+ let cacheable = true;
+ for (const k in o) {
+ if (k !== 'lng' && k !== 'lngs' && k !== 'ns' && k !== 'keyPrefix' && o[k] !== undefined) {
+ cacheable = false;
+ break;
+ }
+ }
+ if (cacheable) ck = `${o.lng || this.language}\u0001${o.lngs || ''}\u0001${o.ns || ''}\u0001${o.keyPrefix || ''}\u0001${keys}`;
+ }
+ if (ck !== null) {
+ let cache = this.__translationCache;
+ if (cache === undefined) {
+ cache = this.__translationCache = new Map();
+ const clear = () => this.__translationCache.clear();
+ this.resourceStore?.on?.('added', clear);
+ this.resourceStore?.on?.('removed', clear);
+ }
+ const hit = cache.get(ck);
+ if (hit !== undefined) return hit;
+ const res = this.__translateUncached(keys, o, lastKey);
+ if (typeof res === 'string') {
+ if (cache.size >= 40000) cache.clear();
+ cache.set(ck, res);
+ }
+ return res;
+ }
+ }
+ return this.__translateUncached(keys, o, lastKey);
+ }
+ __translateUncached(keys, o, lastKey) {
let opt = typeof o === 'object' ? {
...o
} : o;
@@ -2049,21 +2084,24 @@ class I18n extends EventEmitter {
const explicitCallNs = o.ns !== undefined && o.ns !== null;
o.ns = o.ns || fixedT.ns;
if (o.keyPrefix !== '') o.keyPrefix = o.keyPrefix || keyPrefix || fixedT.keyPrefix;
- const selectorOpts = {
- ...this.options,
- ...o
+ const buildSelectorOpts = () => {
+ const selectorOpts = {
+ ...this.options,
+ ...o
+ };
+ if (Array.isArray(scopeNs) && !explicitCallNs) selectorOpts.ns = scopeNs;
+ return selectorOpts;
};
- if (Array.isArray(scopeNs) && !explicitCallNs) selectorOpts.ns = scopeNs;
- if (typeof o.keyPrefix === 'function') o.keyPrefix = keysFromSelector(o.keyPrefix, selectorOpts);
+ if (typeof o.keyPrefix === 'function') o.keyPrefix = keysFromSelector(o.keyPrefix, buildSelectorOpts());
const keySeparator = this.options.keySeparator || '.';
let resultKey;
if (o.keyPrefix && Array.isArray(key)) {
resultKey = key.map(k => {
- if (typeof k === 'function') k = keysFromSelector(k, selectorOpts);
+ if (typeof k === 'function') k = keysFromSelector(k, buildSelectorOpts());
return `${o.keyPrefix}${keySeparator}${k}`;
});
} else {
- if (typeof key === 'function') key = keysFromSelector(key, selectorOpts);
+ if (typeof key === 'function') key = keysFromSelector(key, buildSelectorOpts());
resultKey = o.keyPrefix ? `${o.keyPrefix}${keySeparator}${key}` : key;
}
return this.t(resultKey, o);
diff --git a/dist/esm/i18next.js b/dist/esm/i18next.js
index d01bbdbd1c0c4a4ebf99d64f5fc61c290be67fc6..dbd2eded184a5e3bb6411a6f7a4afd9e368cb1f0 100644
--- a/dist/esm/i18next.js
+++ b/dist/esm/i18next.js
@@ -529,6 +529,41 @@ class Translator extends EventEmitter {
};
}
translate(keys, o, lastKey) {
+ if (lastKey === undefined && typeof keys === 'string') {
+ let ck = null;
+ if (o === undefined) {
+ ck = `${this.language}\u0001\u0001\u0001\u0001${keys}`;
+ } else if (typeof o === 'object' && o !== null) {
+ let cacheable = true;
+ for (const k in o) {
+ if (k !== 'lng' && k !== 'lngs' && k !== 'ns' && k !== 'keyPrefix' && o[k] !== undefined) {
+ cacheable = false;
+ break;
+ }
+ }
+ if (cacheable) ck = `${o.lng || this.language}\u0001${o.lngs || ''}\u0001${o.ns || ''}\u0001${o.keyPrefix || ''}\u0001${keys}`;
+ }
+ if (ck !== null) {
+ let cache = this.__translationCache;
+ if (cache === undefined) {
+ cache = this.__translationCache = new Map();
+ const clear = () => this.__translationCache.clear();
+ this.resourceStore?.on?.('added', clear);
+ this.resourceStore?.on?.('removed', clear);
+ }
+ const hit = cache.get(ck);
+ if (hit !== undefined) return hit;
+ const res = this.__translateUncached(keys, o, lastKey);
+ if (typeof res === 'string') {
+ if (cache.size >= 40000) cache.clear();
+ cache.set(ck, res);
+ }
+ return res;
+ }
+ }
+ return this.__translateUncached(keys, o, lastKey);
+ }
+ __translateUncached(keys, o, lastKey) {
let opt = typeof o === 'object' ? {
...o
} : o;
@@ -2047,21 +2082,24 @@ class I18n extends EventEmitter {
const explicitCallNs = o.ns !== undefined && o.ns !== null;
o.ns = o.ns || fixedT.ns;
if (o.keyPrefix !== '') o.keyPrefix = o.keyPrefix || keyPrefix || fixedT.keyPrefix;
- const selectorOpts = {
- ...this.options,
- ...o
+ const buildSelectorOpts = () => {
+ const selectorOpts = {
+ ...this.options,
+ ...o
+ };
+ if (Array.isArray(scopeNs) && !explicitCallNs) selectorOpts.ns = scopeNs;
+ return selectorOpts;
};
- if (Array.isArray(scopeNs) && !explicitCallNs) selectorOpts.ns = scopeNs;
- if (typeof o.keyPrefix === 'function') o.keyPrefix = keysFromSelector(o.keyPrefix, selectorOpts);
+ if (typeof o.keyPrefix === 'function') o.keyPrefix = keysFromSelector(o.keyPrefix, buildSelectorOpts());
const keySeparator = this.options.keySeparator || '.';
let resultKey;
if (o.keyPrefix && Array.isArray(key)) {
resultKey = key.map(k => {
- if (typeof k === 'function') k = keysFromSelector(k, selectorOpts);
+ if (typeof k === 'function') k = keysFromSelector(k, buildSelectorOpts());
return `${o.keyPrefix}${keySeparator}${k}`;
});
} else {
- if (typeof key === 'function') key = keysFromSelector(key, selectorOpts);
+ if (typeof key === 'function') key = keysFromSelector(key, buildSelectorOpts());
resultKey = o.keyPrefix ? `${o.keyPrefix}${keySeparator}${key}` : key;
}
return this.t(resultKey, o);

17
pnpm-lock.yaml generated
View File

@@ -7,6 +7,7 @@ settings:
patchedDependencies:
'@react-router/serve@8.1.0': 0073d0acad5d92eea7ef30ed24d736df9f4d59e204f8358ecb3b06b9ea9d8738
'@techstark/opencv-js@5.0.0-release.1': 0e23b4243e8e2f88294c00eefdf8dfc3624f59442bd0c8d075be89a8136144f3
i18next@26.3.6: 34c245cebb3f9c7861d2576a3a44228364cb898037f86b23a5bbf8b20f55fb1a
kysely@0.29.0: a3e94339939b1be5b70610601e96fff19ed5678aab525de24b52dfc5212c686a
react-i18next@17.0.11: 1f928881d134daf116e494299036454a3c311fe6fb81f60ef8d158f27466a269
@@ -82,7 +83,7 @@ importers:
version: 4.0.3
i18next:
specifier: 26.3.6
version: 26.3.6(typescript@7.0.2)
version: 26.3.6(patch_hash=34c245cebb3f9c7861d2576a3a44228364cb898037f86b23a5bbf8b20f55fb1a)(typescript@7.0.2)
i18next-browser-languagedetector:
specifier: 8.2.1
version: 8.2.1
@@ -151,7 +152,7 @@ importers:
version: 7.2.4(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
react-i18next:
specifier: 17.0.11
version: 17.0.11(patch_hash=1f928881d134daf116e494299036454a3c311fe6fb81f60ef8d158f27466a269)(i18next@26.3.6(typescript@7.0.2))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(typescript@7.0.2)
version: 17.0.11(patch_hash=1f928881d134daf116e494299036454a3c311fe6fb81f60ef8d158f27466a269)(i18next@26.3.6(patch_hash=34c245cebb3f9c7861d2576a3a44228364cb898037f86b23a5bbf8b20f55fb1a)(typescript@7.0.2))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(typescript@7.0.2)
react-router:
specifier: 8.3.0
version: 8.3.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
@@ -169,7 +170,7 @@ importers:
version: 3.4.1(remix-auth@4.2.0)
remix-i18next:
specifier: 8.0.0
version: 8.0.0(i18next@26.3.6(typescript@7.0.2))(react-router@8.3.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8))
version: 8.0.0(i18next@26.3.6(patch_hash=34c245cebb3f9c7861d2576a3a44228364cb898037f86b23a5bbf8b20f55fb1a)(typescript@7.0.2))(react-router@8.3.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8))
slugify:
specifier: 1.6.9
version: 1.6.9
@@ -7680,7 +7681,7 @@ snapshots:
picomatch: 4.0.4
yargs: 17.7.2
i18next@26.3.6(typescript@7.0.2):
i18next@26.3.6(patch_hash=34c245cebb3f9c7861d2576a3a44228364cb898037f86b23a5bbf8b20f55fb1a)(typescript@7.0.2):
optionalDependencies:
typescript: 7.0.2
@@ -8264,11 +8265,11 @@ snapshots:
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
react-i18next@17.0.11(patch_hash=1f928881d134daf116e494299036454a3c311fe6fb81f60ef8d158f27466a269)(i18next@26.3.6(typescript@7.0.2))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(typescript@7.0.2):
react-i18next@17.0.11(patch_hash=1f928881d134daf116e494299036454a3c311fe6fb81f60ef8d158f27466a269)(i18next@26.3.6(patch_hash=34c245cebb3f9c7861d2576a3a44228364cb898037f86b23a5bbf8b20f55fb1a)(typescript@7.0.2))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(typescript@7.0.2):
dependencies:
'@babel/runtime': 7.29.7
html-parse-stringify: 4.0.1
i18next: 26.3.6(typescript@7.0.2)
i18next: 26.3.6(patch_hash=34c245cebb3f9c7861d2576a3a44228364cb898037f86b23a5bbf8b20f55fb1a)(typescript@7.0.2)
react: 19.2.8
use-sync-external-store: 1.6.0(react@19.2.8)
optionalDependencies:
@@ -8350,9 +8351,9 @@ snapshots:
remix-auth@4.2.0: {}
remix-i18next@8.0.0(i18next@26.3.6(typescript@7.0.2))(react-router@8.3.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)):
remix-i18next@8.0.0(i18next@26.3.6(patch_hash=34c245cebb3f9c7861d2576a3a44228364cb898037f86b23a5bbf8b20f55fb1a)(typescript@7.0.2))(react-router@8.3.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)):
dependencies:
i18next: 26.3.6(typescript@7.0.2)
i18next: 26.3.6(patch_hash=34c245cebb3f9c7861d2576a3a44228364cb898037f86b23a5bbf8b20f55fb1a)(typescript@7.0.2)
react-router: 8.3.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
require-directory@2.1.1: {}

View File

@@ -5,5 +5,6 @@ allowBuilds:
patchedDependencies:
'@react-router/serve@8.1.0': patches/@react-router__serve@8.1.0.patch
'@techstark/opencv-js@5.0.0-release.1': patches/@techstark__opencv-js@5.0.0-release.1.patch
i18next@26.3.6: patches/i18next@26.3.6.patch
kysely@0.29.0: patches/kysely@0.29.0.patch
react-i18next@17.0.11: patches/react-i18next@17.0.11.patch