@koehler8/cms 1.4.0 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/package.json +1 -1
- package/src/main.js +15 -11
- package/src/utils/currentRoute.js +49 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.4.1
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **The embedded config payload is now actually used on locale-prefixed routes.**
|
|
8
|
+
vite-ssg runs the setup fn *before* `app.use(router)`, so `router.currentRoute`
|
|
9
|
+
is still `START_LOCATION` (`'/'`, `params: {}`) there — identically on every
|
|
10
|
+
page. During SSG that was already handled, because vite-ssg hands the route
|
|
11
|
+
over on `ctx.routePath`. On the **client** it calls the setup fn with no
|
|
12
|
+
argument at all, so there was nothing to resolve and the code fell through to
|
|
13
|
+
`START_LOCATION`.
|
|
14
|
+
|
|
15
|
+
`loadSiteConfig` derives its cache key from `params.locale`, so the key came
|
|
16
|
+
out `'default'` on every client page while the SSG had stamped the real locale
|
|
17
|
+
on `siteConfigLocale`. On a locale-prefixed route the two never matched, so
|
|
18
|
+
`primeConfigSync` was skipped, `hydrateFromSyncCache` missed, and the client
|
|
19
|
+
discarded the payload it had just been served and awaited a full config load
|
|
20
|
+
**inside the setup fn, on the critical path, before mount** — the exact
|
|
21
|
+
regression the priming machinery exists to prevent.
|
|
22
|
+
|
|
23
|
+
Measured on a multi-locale site, same machine and build, only this patch
|
|
24
|
+
differing. First config chunk on a `/th/` piece page: **44 ms before**
|
|
25
|
+
(DOMContentLoaded 34 ms — on the critical path), **1364 ms after** (deferred
|
|
26
|
+
to `requestIdleCallback`, as designed). The load is *deferred, not removed*:
|
|
27
|
+
`trimConfigToPage` stamps `pagesPartial` on every page, so the idle reload
|
|
28
|
+
still runs.
|
|
29
|
+
|
|
30
|
+
⚠️ A cross-environment comparison hides this completely. A production bundle
|
|
31
|
+
that needs ~1.4 s to download and execute shows its config chunks at ~1607 ms,
|
|
32
|
+
which *looks* deferred when it is in fact immediate. Only a same-environment
|
|
33
|
+
A/B separates the two.
|
|
34
|
+
|
|
35
|
+
**No action needed in a site.** Single-locale sites already stamped `default`
|
|
36
|
+
and primed correctly, so their behaviour is unchanged; multi-locale sites gain
|
|
37
|
+
the deferral.
|
|
38
|
+
|
|
3
39
|
## 1.4.0
|
|
4
40
|
|
|
5
41
|
### Changed
|
package/package.json
CHANGED
package/src/main.js
CHANGED
|
@@ -8,6 +8,7 @@ import { routes, resolveHistory, applyRouterGuards } from './router/index.js';
|
|
|
8
8
|
import { shouldEnableAnalytics, scheduleAnalyticsLoad, configureAnalyticsConsentMode } from './utils/cookieConsent.js';
|
|
9
9
|
import { loadConfigData, primeConfigSync, trimConfigToPage, resolvePageIdForRoute } from './utils/loadConfig.js';
|
|
10
10
|
import { applyInitialStateTrims } from './utils/initialStateTrim.js';
|
|
11
|
+
import { currentRouteHref } from './utils/currentRoute.js';
|
|
11
12
|
import { persistAttributionFromLocation } from './utils/trackingContext.js';
|
|
12
13
|
import { applyThemeVariables } from './themes/themeManager.js';
|
|
13
14
|
import { setActiveThemeKey } from './utils/themeColors.js';
|
|
@@ -136,19 +137,22 @@ export function createCmsApp() {
|
|
|
136
137
|
};
|
|
137
138
|
|
|
138
139
|
const extractCurrentRoute = () => {
|
|
139
|
-
//
|
|
140
|
-
//
|
|
141
|
-
// —
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
const
|
|
147
|
-
|
|
140
|
+
// vite-ssg runs this setup fn BEFORE `app.use(router)`, so
|
|
141
|
+
// `router.currentRoute` is still vue-router's START_LOCATION ('/') here,
|
|
142
|
+
// identically on every page — during SSG *and* on the client. The href
|
|
143
|
+
// that IS authoritative differs per half (ctx.routePath vs the window's
|
|
144
|
+
// own location); currentRouteHref picks it, with the full account of why
|
|
145
|
+
// the client half is not optional. Resolve it through the router — a pure
|
|
146
|
+
// match, no navigation — to recover the real path + `params.locale`.
|
|
147
|
+
const href = currentRouteHref(
|
|
148
|
+
ctx,
|
|
149
|
+
typeof window !== 'undefined' ? window.location : null,
|
|
150
|
+
);
|
|
151
|
+
if (href) {
|
|
148
152
|
try {
|
|
149
|
-
return router.resolve(
|
|
153
|
+
return router.resolve(href);
|
|
150
154
|
} catch {
|
|
151
|
-
return { path:
|
|
155
|
+
return { path: href, params: {} };
|
|
152
156
|
}
|
|
153
157
|
}
|
|
154
158
|
if (ctx?.route) {
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Which href the app should resolve through the router to learn the route it is
|
|
2
|
+
// actually on.
|
|
3
|
+
//
|
|
4
|
+
// Both halves of the lifecycle are blind to this in the same way, for the same
|
|
5
|
+
// reason: vite-ssg runs the setup fn BEFORE `app.use(router)`, so
|
|
6
|
+
// `router.currentRoute` is still vue-router's START_LOCATION ('/', `params: {}`)
|
|
7
|
+
// — identically on every page.
|
|
8
|
+
//
|
|
9
|
+
// - During SSG, vite-ssg hands the route being pre-rendered over as a string on
|
|
10
|
+
// `ctx.routePath`, so that is authoritative.
|
|
11
|
+
// - On the CLIENT it calls the setup fn with no argument at all: no
|
|
12
|
+
// `ctx.routePath`, no `ctx.route`. The only authoritative source left is the
|
|
13
|
+
// window's own location.
|
|
14
|
+
//
|
|
15
|
+
// Falling through to START_LOCATION on the client is not a cosmetic miss. The
|
|
16
|
+
// config cache key is derived from `params.locale`, so it came out 'default' on
|
|
17
|
+
// every page while the SSG had stamped the real locale on `siteConfigLocale`.
|
|
18
|
+
// The two never matched on a locale-prefixed route, `primeConfigSync` was
|
|
19
|
+
// skipped, and the client discarded the embedded payload and re-fetched the
|
|
20
|
+
// whole config tree on the critical path — the exact regression the priming
|
|
21
|
+
// machinery exists to prevent. Measured on sparkbang.com/th/<piece>/ before the
|
|
22
|
+
// fix: 151 JS requests / 405 KB, 112 of them per-piece config chunks, while the
|
|
23
|
+
// 17 KB embedded payload was parsed and thrown away.
|
|
24
|
+
//
|
|
25
|
+
// Pure and dependency-free so the fall-through can be pinned by a unit test;
|
|
26
|
+
// `main.js` owns the router.resolve() call itself (a pure match, no navigation).
|
|
27
|
+
//
|
|
28
|
+
// Returns null when the caller should use `ctx.route` as-is, or when there is
|
|
29
|
+
// nothing authoritative to resolve and START_LOCATION is genuinely all there is.
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {{routePath?: unknown, route?: unknown}|null|undefined} ctx
|
|
33
|
+
* The vite-ssg setup context. `routePath` is set during SSG only.
|
|
34
|
+
* @param {{pathname?: unknown, search?: unknown}|null|undefined} location
|
|
35
|
+
* `window.location` on the client; omit/null on the server.
|
|
36
|
+
* @returns {string|null} the href to resolve, or null to fall back.
|
|
37
|
+
*/
|
|
38
|
+
export function currentRouteHref(ctx, location) {
|
|
39
|
+
const routePath = ctx?.routePath;
|
|
40
|
+
if (typeof routePath === 'string' && routePath) return routePath;
|
|
41
|
+
// A context that already carries a resolved route needs no href at all.
|
|
42
|
+
if (ctx?.route) return null;
|
|
43
|
+
const pathname = location?.pathname;
|
|
44
|
+
if (typeof pathname === 'string' && pathname) {
|
|
45
|
+
const search = typeof location?.search === 'string' ? location.search : '';
|
|
46
|
+
return `${pathname}${search}`;
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|