@farm.js/core 0.1.51-beta.1 → 0.1.51-beta.3
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/dist/{agent-mcp-handler-WWCC4GLG.mjs → agent-mcp-handler-7JSKGSOW.mjs} +4 -4
- package/dist/{agent-mcp-handler-RT3COCEL.cjs → agent-mcp-handler-YE4AGWHN.cjs} +5 -5
- package/dist/{agent-mcp.d-ZuuNgrkQ.d.ts → agent-mcp.d-BAR9njbJ.d.ts} +1 -1
- package/dist/{agent-mcp.d-BPzpKBHQ.d.mts → agent-mcp.d-BJKChOrO.d.mts} +1 -1
- package/dist/agent-runtime.d.mts +2 -2
- package/dist/agent-runtime.d.ts +2 -2
- package/dist/{analyzer-V74FTD2F.mjs → analyzer-OTPEWH5W.mjs} +82 -22
- package/dist/{analyzer-AZULAOPL.cjs → analyzer-TSQXZCZN.cjs} +82 -22
- package/dist/api/route-manager.d.mts +4 -4
- package/dist/api/route-manager.d.ts +4 -4
- package/dist/api/runtime.d.mts +3 -3
- package/dist/api/runtime.d.ts +3 -3
- package/dist/api.d.mts +4 -4
- package/dist/api.d.ts +4 -4
- package/dist/{app-manifest.d-HWhqbP2X.d.ts → app-manifest.d-BLFbaqx8.d.ts} +1 -1
- package/dist/{app-manifest.d-BJDcZn3W.d.mts → app-manifest.d-DEQNnNhV.d.mts} +1 -1
- package/dist/app-markdown.cjs +4 -4
- package/dist/app-markdown.d.mts +3 -3
- package/dist/app-markdown.d.ts +3 -3
- package/dist/app-markdown.mjs +3 -3
- package/dist/{app.d-B5EWdob-.d.ts → app.d-CNPaUYaa.d.ts} +4 -4
- package/dist/{app.d-DOGW1KI8.d.mts → app.d-CT7xDkj2.d.mts} +4 -4
- package/dist/{chunk-YVJV7Q2X.mjs → chunk-3BLEXUGE.mjs} +1 -1
- package/dist/chunk-3HLQTOVU.cjs +6 -0
- package/dist/{chunk-KU7MBLDZ.mjs → chunk-3SMXQNFD.mjs} +2 -2
- package/dist/{chunk-EWC76P5D.mjs → chunk-3TLKUBXG.mjs} +411 -166
- package/dist/{chunk-BSEKNTMS.mjs → chunk-3WSIYBMG.mjs} +41 -19
- package/dist/{chunk-JVBNKWLV.cjs → chunk-3XQ57EFI.cjs} +16 -16
- package/dist/{chunk-GW4YUIHW.mjs → chunk-3Z63X45F.mjs} +1 -1
- package/dist/{chunk-SCRC5AMM.mjs → chunk-4353ZRE5.mjs} +1 -1
- package/dist/{chunk-SBABQKPT.cjs → chunk-46KXZBOG.cjs} +5 -5
- package/dist/{chunk-2756SHCI.cjs → chunk-4CGOMZP3.cjs} +221 -199
- package/dist/{chunk-RMPNYUGT.cjs → chunk-4SEHMBL4.cjs} +10 -10
- package/dist/{chunk-QAIAFCRZ.mjs → chunk-4TKAIO2F.mjs} +3 -3
- package/dist/{chunk-NJLTQR5P.cjs → chunk-53SACYBY.cjs} +7 -7
- package/dist/{chunk-I3EFXUAR.mjs → chunk-5FXPJIOT.mjs} +2 -2
- package/dist/chunk-7FVVQEVL.cjs +541 -0
- package/dist/{chunk-IFBINMI4.cjs → chunk-7MD37P5V.cjs} +5 -5
- package/dist/{chunk-JATTVAHA.cjs → chunk-B3GM5I6N.cjs} +4 -4
- package/dist/chunk-C3BOESDW.mjs +541 -0
- package/dist/{chunk-WJFFPXCV.cjs → chunk-D7UQC4O6.cjs} +10 -8
- package/dist/{chunk-KRRZJ77U.mjs → chunk-E5DXF5GE.mjs} +2 -2
- package/dist/chunk-EFZGB7JC.cjs +114 -0
- package/dist/{chunk-NYQSC4DX.cjs → chunk-FFE2EMF7.cjs} +5 -5
- package/dist/{chunk-KMB5BMFX.mjs → chunk-GAO7MS5O.mjs} +9 -3
- package/dist/{chunk-HIFIG6HL.cjs → chunk-H33PJEXN.cjs} +5 -5
- package/dist/{chunk-TT66CP3P.cjs → chunk-HLWOWZFX.cjs} +2 -2
- package/dist/chunk-JXEPLIXD.cjs +389 -0
- package/dist/{chunk-VITZRYW3.cjs → chunk-KLNFJDFM.cjs} +15 -9
- package/dist/{chunk-KBRZAYI7.mjs → chunk-LDNSSHEG.mjs} +2 -2
- package/dist/chunk-LLZSYFOM.mjs +6 -0
- package/dist/{chunk-N77JBPLC.mjs → chunk-LPDKG6RA.mjs} +9 -7
- package/dist/chunk-MIGFX2FN.mjs +758 -0
- package/dist/{chunk-72D2NX77.mjs → chunk-MRNDAJEV.mjs} +1 -1
- package/dist/{chunk-5A5GAZ75.mjs → chunk-NOTSHVRN.mjs} +406 -234
- package/dist/{chunk-AGR7VJH2.cjs → chunk-OAMUSC7H.cjs} +1 -1
- package/dist/chunk-P6MHI5O2.cjs +758 -0
- package/dist/{chunk-EOSFVNXZ.mjs → chunk-R4PHCZ3G.mjs} +1 -1
- package/dist/{chunk-X2M4XN4V.cjs → chunk-TQMI6BYO.cjs} +675 -430
- package/dist/{chunk-76GHW3WI.cjs → chunk-TSFMFPRU.cjs} +4 -4
- package/dist/{chunk-5N7QAGEA.cjs → chunk-TWHXBMLJ.cjs} +37 -7
- package/dist/{chunk-BOVGCUDZ.cjs → chunk-UJL4JOXV.cjs} +2 -2
- package/dist/chunk-UQF3OJVE.mjs +389 -0
- package/dist/{chunk-XY4DYGSU.cjs → chunk-WGUHDWT5.cjs} +607 -435
- package/dist/{chunk-LAZK6UV7.mjs → chunk-YAJTD3ZG.mjs} +1 -1
- package/dist/{chunk-7UPCJDB5.mjs → chunk-YUEYBL35.mjs} +2 -2
- package/dist/{chunk-EIMK7D2D.mjs → chunk-ZD2VKAUI.mjs} +34 -4
- package/dist/chunk-ZNXTU4YH.mjs +114 -0
- package/dist/{client-plugins.d-C_3CdALC.d.mts → client-plugins.d-DllmH8eM.d.mts} +31 -5
- package/dist/{client-plugins.d-C0n8Yhh-.d.ts → client-plugins.d-n3iWY1EJ.d.ts} +31 -5
- package/dist/client-plugins.d.mts +2 -2
- package/dist/client-plugins.d.ts +2 -2
- package/dist/client.d.mts +7 -7
- package/dist/client.d.ts +7 -7
- package/dist/{config.d-CnhyvvmT.d.ts → config.d-DqKaCr1r.d.mts} +14 -3
- package/dist/{config.d-CnhyvvmT.d.mts → config.d-DqKaCr1r.d.ts} +14 -3
- package/dist/config.d.mts +2 -2
- package/dist/config.d.ts +2 -2
- package/dist/desktop.d.mts +3 -3
- package/dist/desktop.d.ts +3 -3
- package/dist/{devtools-KJFUE5FO.cjs → devtools-TO6TAO32.cjs} +5 -5
- package/dist/{devtools-BU5IT2PD.mjs → devtools-UESYARTF.mjs} +4 -4
- package/dist/docs.cjs +7 -7
- package/dist/docs.d.mts +3 -3
- package/dist/docs.d.ts +3 -3
- package/dist/docs.mjs +6 -6
- package/dist/index.cjs +23 -18
- package/dist/{index.d-CsGxS-hZ.d.mts → index.d-BL7KKiwa.d.mts} +1 -1
- package/dist/{index.d-B6M_8kmo.d.ts → index.d-BXsAXm1U.d.ts} +1 -1
- package/dist/index.d.mts +17 -17
- package/dist/index.d.ts +17 -17
- package/dist/index.mjs +23 -18
- package/dist/integrations.d.mts +2 -2
- package/dist/integrations.d.ts +2 -2
- package/dist/internal/app-markdown-runtime.cjs +3 -3
- package/dist/internal/app-markdown-runtime.d.mts +3 -3
- package/dist/internal/app-markdown-runtime.d.ts +3 -3
- package/dist/internal/app-markdown-runtime.mjs +2 -2
- package/dist/internal/build-runtime.cjs +21 -18
- package/dist/internal/build-runtime.d.mts +4 -4
- package/dist/internal/build-runtime.d.ts +4 -4
- package/dist/internal/build-runtime.mjs +20 -17
- package/dist/internal/cli-runtime.cjs +7 -7
- package/dist/internal/cli-runtime.mjs +6 -6
- package/dist/internal/client-error-overlay.cjs +4 -4
- package/dist/internal/client-error-overlay.mjs +1 -1
- package/dist/internal/client-runtime.d.mts +5 -5
- package/dist/internal/client-runtime.d.ts +5 -5
- package/dist/internal/compression-runtime.d.mts +2 -2
- package/dist/internal/compression-runtime.d.ts +2 -2
- package/dist/internal/config-runtime.cjs +6 -6
- package/dist/internal/config-runtime.d.mts +41 -80
- package/dist/internal/config-runtime.d.ts +41 -80
- package/dist/internal/config-runtime.mjs +5 -5
- package/dist/internal/infra-analytics-runtime.cjs +8 -8
- package/dist/internal/infra-analytics-runtime.mjs +6 -6
- package/dist/internal/product-telemetry-runtime.cjs +2 -2
- package/dist/internal/product-telemetry-runtime.mjs +1 -1
- package/dist/internal/production-runtime.cjs +91 -9
- package/dist/internal/production-runtime.d.mts +67 -12
- package/dist/internal/production-runtime.d.ts +67 -12
- package/dist/internal/production-runtime.mjs +90 -8
- package/dist/markdown.cjs +4 -2
- package/dist/markdown.d.mts +2 -2
- package/dist/markdown.d.ts +2 -2
- package/dist/markdown.mjs +3 -1
- package/dist/middleware.d.mts +4 -4
- package/dist/middleware.d.ts +4 -4
- package/dist/mobile.d.mts +21 -5
- package/dist/mobile.d.ts +21 -5
- package/dist/native-tree-EBPDFTRW.mjs +25 -0
- package/dist/native-tree-MMZS7S6W.cjs +25 -0
- package/dist/{navigation-delegate.d-C0BbdUgN.d.mts → navigation-delegate.d-C76gXTmO.d.mts} +1 -1
- package/dist/{navigation-delegate.d-jArRF0ZP.d.ts → navigation-delegate.d-DIyDslxt.d.ts} +1 -1
- package/dist/navigation.d.mts +5 -5
- package/dist/navigation.d.ts +5 -5
- package/dist/plugin.cjs +14 -13
- package/dist/plugin.d.mts +5 -4
- package/dist/plugin.d.ts +5 -4
- package/dist/plugin.mjs +13 -12
- package/dist/{production-runtime.d-DFaQ1qaV.d.mts → production-runtime.d-CDHztggO.d.mts} +1 -1
- package/dist/{production-runtime.d-UnXmSS_S.d.ts → production-runtime.d-tyaGdbk6.d.ts} +1 -1
- package/dist/{programmatic-routes-client.d-VZ0qcbH4.d.ts → programmatic-routes-client.d-XfmIrCK1.d.ts} +2 -2
- package/dist/{programmatic-routes-client.d-BIowUXQC.d.mts → programmatic-routes-client.d-aAWiDd64.d.mts} +2 -2
- package/dist/{render-plan.d-BNeqyPyJ.d.mts → render-plan.d-Diwybxo8.d.mts} +1 -1
- package/dist/{render-plan.d-BB6KrYjP.d.ts → render-plan.d-Dr5WRjoV.d.ts} +1 -1
- package/dist/renderer-client.d.mts +5 -5
- package/dist/renderer-client.d.ts +5 -5
- package/dist/{request.d-Bxhghm76.d.ts → request.d-D01fRn--.d.ts} +1 -1
- package/dist/{request.d-BV1munmx.d.mts → request.d-Dd3AFR79.d.mts} +1 -1
- package/dist/request.d.mts +3 -3
- package/dist/request.d.ts +3 -3
- package/dist/{route-rendering.d-DShqKlgK.d.mts → route-rendering.d-BQ53lJ_D.d.mts} +1 -1
- package/dist/{route-rendering.d-BIf7zE9d.d.ts → route-rendering.d-Bhx4QoJt.d.ts} +1 -1
- package/dist/{router.d-BE7i84fb.d.mts → router.d-Bi23a6Xc.d.mts} +1 -1
- package/dist/{router.d-Bw3K3b0a.d.ts → router.d-DQ3k7EYn.d.ts} +1 -1
- package/dist/{routes.d-_5tBQexL.d.mts → routes.d-BgTd7vI4.d.mts} +91 -4
- package/dist/{routes.d-DVZQL0-H.d.ts → routes.d-C7jMJFvP.d.ts} +91 -4
- package/dist/routes.d.mts +2 -2
- package/dist/routes.d.ts +2 -2
- package/dist/{rsc-pipeline-FBM6NFYY.mjs → rsc-pipeline-K3ER3Q4N.mjs} +5 -5
- package/dist/{rsc-pipeline-IQI5XQLS.cjs → rsc-pipeline-OCZIT5OF.cjs} +6 -6
- package/dist/{runtime-DXEVFYLE.cjs → runtime-DKNSIH7V.cjs} +85 -29
- package/dist/{runtime-2JYIDUON.mjs → runtime-MKYDEUZT.mjs} +75 -19
- package/dist/{runtime.d-CQgoYR0Q.d.mts → runtime.d-B2Js6qZ2.d.mts} +1 -1
- package/dist/{runtime.d-CfhaLPl-.d.ts → runtime.d-BL-CGwoi.d.ts} +1 -1
- package/dist/server-plugins.d.mts +3 -3
- package/dist/server-plugins.d.ts +3 -3
- package/dist/server.cjs +31 -30
- package/dist/server.d.mts +11 -10
- package/dist/server.d.ts +11 -10
- package/dist/server.mjs +16 -15
- package/dist/session-AAU7RNRO.cjs +23 -0
- package/dist/session-IGEDQ5PY.mjs +23 -0
- package/dist/{spa-router.d-D63jb6nX.d.mts → spa-router.d-B2rIFGs0.d.mts} +2 -2
- package/dist/{spa-router.d-C5opIgXg.d.ts → spa-router.d-DqZ6Lfs0.d.ts} +2 -2
- package/dist/testing.d.mts +2 -2
- package/dist/testing.d.ts +2 -2
- package/dist/{utils.d-CkpTqTsC.d.ts → utils.d-Bv2MPeLR.d.ts} +1 -1
- package/dist/{utils.d-CO-U4OVZ.d.mts → utils.d-fqXe8lNc.d.mts} +1 -1
- package/dist/version.cjs +2 -2
- package/dist/version.mjs +1 -1
- package/dist/vite.cjs +14 -13
- package/dist/vite.d.mts +12 -6
- package/dist/vite.d.ts +12 -6
- package/dist/vite.mjs +13 -12
- package/package.json +3 -3
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FARM_MOBILE_CLIENT_ENTRY_NAME,
|
|
3
|
+
FARM_MOBILE_SHELL_CLIENT_PLACEHOLDER,
|
|
4
|
+
createFarmMobileClientManifestPlugin,
|
|
5
|
+
encodeFarmMobileShellClient,
|
|
6
|
+
finalizeFarmMobileClient,
|
|
7
|
+
hasFarmMobileClientEntry,
|
|
8
|
+
removeFarmMobileClientManifest
|
|
9
|
+
} from "./chunk-ZNXTU4YH.mjs";
|
|
1
10
|
import {
|
|
2
11
|
loadFarmProductionVite
|
|
3
12
|
} from "./chunk-PSUYE5HR.mjs";
|
|
@@ -13,13 +22,16 @@ import {
|
|
|
13
22
|
import {
|
|
14
23
|
generateNativeMCPPluginSource
|
|
15
24
|
} from "./chunk-KQH2COEJ.mjs";
|
|
25
|
+
import {
|
|
26
|
+
FARM_MOBILE_SESSION_PLUGIN
|
|
27
|
+
} from "./chunk-C3BOESDW.mjs";
|
|
16
28
|
import {
|
|
17
29
|
assertFarmDocsAdapterServesNoGuardedPages,
|
|
18
30
|
compileFarmDocsAdapterEdgeManifest,
|
|
19
31
|
createFarmDocsAPIHandler,
|
|
20
32
|
hasFarmDocsRuntimeAdapter,
|
|
21
33
|
listFarmDocsAdapterPages
|
|
22
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-5FXPJIOT.mjs";
|
|
23
35
|
import {
|
|
24
36
|
FARM_DOCS_LAST_MODIFIED_MANIFEST,
|
|
25
37
|
createFarmDocsHandler,
|
|
@@ -31,7 +43,7 @@ import {
|
|
|
31
43
|
loadFarmDocsPage,
|
|
32
44
|
resolveFarmDocsContentDir,
|
|
33
45
|
toFarmDocsMarkdownPage
|
|
34
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-ZD2VKAUI.mjs";
|
|
35
47
|
import {
|
|
36
48
|
generateFarmDocsSearchClientRuntime,
|
|
37
49
|
isFarmDocsSearchEnabled,
|
|
@@ -39,7 +51,7 @@ import {
|
|
|
39
51
|
} from "./chunk-ALEUMLJN.mjs";
|
|
40
52
|
import {
|
|
41
53
|
FARM_PRERENDER_ENV
|
|
42
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-3SMXQNFD.mjs";
|
|
43
55
|
import {
|
|
44
56
|
resolveFarmInstrumentationFile
|
|
45
57
|
} from "./chunk-N35YPV4N.mjs";
|
|
@@ -54,7 +66,7 @@ import {
|
|
|
54
66
|
getDeployTargetForPreset,
|
|
55
67
|
hasCustomFarmRouteContext,
|
|
56
68
|
resolveDeployOutputPath
|
|
57
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-GAO7MS5O.mjs";
|
|
58
70
|
import {
|
|
59
71
|
DEFAULT_NOT_FOUND_STYLES,
|
|
60
72
|
FARM_LAYOUT_ELEMENT_CLIENT_SOURCE,
|
|
@@ -85,8 +97,10 @@ import {
|
|
|
85
97
|
resolveFarmImageServerRuntime,
|
|
86
98
|
resolveFarmIsolatedClientHydrationMode,
|
|
87
99
|
resolveFarmNotFoundComponentPath,
|
|
88
|
-
|
|
89
|
-
|
|
100
|
+
usePackageClientBoundaryCacheFile,
|
|
101
|
+
usesFarmServerTree,
|
|
102
|
+
withPackageClientBoundaryCache
|
|
103
|
+
} from "./chunk-3TLKUBXG.mjs";
|
|
90
104
|
import {
|
|
91
105
|
loadTailwindVitePlugin
|
|
92
106
|
} from "./chunk-PIHKO25G.mjs";
|
|
@@ -110,7 +124,10 @@ import {
|
|
|
110
124
|
layoutsCanCoverSamePage,
|
|
111
125
|
routeBoundaryCoversDirectory,
|
|
112
126
|
stripRouteGroups
|
|
113
|
-
} from "./chunk-
|
|
127
|
+
} from "./chunk-YUEYBL35.mjs";
|
|
128
|
+
import {
|
|
129
|
+
FARM_NATIVE_TREE_CONTENT_TYPE
|
|
130
|
+
} from "./chunk-LLZSYFOM.mjs";
|
|
114
131
|
import {
|
|
115
132
|
farmPluginMayAffectRuntimePath
|
|
116
133
|
} from "./chunk-UUMKLGUU.mjs";
|
|
@@ -124,18 +141,18 @@ import {
|
|
|
124
141
|
listFarmBuiltInRoutePaths,
|
|
125
142
|
resolveFarmApiCatalogInput,
|
|
126
143
|
resolveFarmAppManifestInput
|
|
127
|
-
} from "./chunk-
|
|
144
|
+
} from "./chunk-4TKAIO2F.mjs";
|
|
128
145
|
import {
|
|
129
146
|
FARM_DEFAULT_MCP_PATH,
|
|
130
147
|
createFarmDefaultMCPServer,
|
|
131
148
|
farmConfigMountsMCP
|
|
132
|
-
} from "./chunk-
|
|
149
|
+
} from "./chunk-E5DXF5GE.mjs";
|
|
133
150
|
import {
|
|
134
151
|
farmEnvironmentFunctionsPlugin
|
|
135
152
|
} from "./chunk-ZQ5BDNKW.mjs";
|
|
136
153
|
import {
|
|
137
154
|
isFarmMarkdownPageFile
|
|
138
|
-
} from "./chunk-
|
|
155
|
+
} from "./chunk-3Z63X45F.mjs";
|
|
139
156
|
import {
|
|
140
157
|
generateFarmDocsAdapterClientRuntime,
|
|
141
158
|
getFarmDocsAdapterConfigModule
|
|
@@ -188,7 +205,7 @@ import {
|
|
|
188
205
|
} from "./chunk-FSQMN2MQ.mjs";
|
|
189
206
|
import {
|
|
190
207
|
getFarmMarkdownAlternatePath
|
|
191
|
-
} from "./chunk-
|
|
208
|
+
} from "./chunk-LPDKG6RA.mjs";
|
|
192
209
|
import {
|
|
193
210
|
_collectFarmStorageModules
|
|
194
211
|
} from "./chunk-TJVUTGED.mjs";
|
|
@@ -233,7 +250,7 @@ import {
|
|
|
233
250
|
} from "./chunk-LM2YOGDK.mjs";
|
|
234
251
|
import {
|
|
235
252
|
FARM_VERSION
|
|
236
|
-
} from "./chunk-
|
|
253
|
+
} from "./chunk-R4PHCZ3G.mjs";
|
|
237
254
|
import {
|
|
238
255
|
getFarmPresetRuntime
|
|
239
256
|
} from "./chunk-UAQD67HM.mjs";
|
|
@@ -1612,7 +1629,7 @@ function restoreLiteralModuleSpecifiers(code, fileName, { parseSync, Visitor })
|
|
|
1612
1629
|
throw new Error(`Failed to minify ${fileName}: ${parsed.errors[0].message}`);
|
|
1613
1630
|
}
|
|
1614
1631
|
const replacements = [];
|
|
1615
|
-
let needsAst = hasRequireTemplate;
|
|
1632
|
+
let needsAst = hasRequireTemplate && /(?<![\w$])require\(`/.test(code);
|
|
1616
1633
|
if (!needsAst) {
|
|
1617
1634
|
const seenStarts = /* @__PURE__ */ new Set();
|
|
1618
1635
|
for (const { moduleRequest } of parsed.module.dynamicImports) {
|
|
@@ -1755,7 +1772,9 @@ function hasFarmPluginRoutes(config) {
|
|
|
1755
1772
|
}
|
|
1756
1773
|
function farmServerRuntimePluginsMayHandlePath(config, pathname) {
|
|
1757
1774
|
return (config.plugins || []).some(
|
|
1758
|
-
(plugin) => getFarmIntegrationPluginServerRuntime(plugin) !== false &&
|
|
1775
|
+
(plugin) => getFarmIntegrationPluginServerRuntime(plugin) !== false && // Mobile session tokens change only bearer requests and cookie-clearing responses, which a
|
|
1776
|
+
// prerendered file never answers or sends; its endpoints live under /__farm/.
|
|
1777
|
+
plugin.name !== FARM_MOBILE_SESSION_PLUGIN && farmPluginMayAffectRuntimePath(plugin, pathname)
|
|
1759
1778
|
);
|
|
1760
1779
|
}
|
|
1761
1780
|
async function discoverMiddlewareRoutes(appDir) {
|
|
@@ -1904,6 +1923,7 @@ ${islandsErrors.map((error) => ` - ${error}`).join("\n")}`
|
|
|
1904
1923
|
}
|
|
1905
1924
|
const productionVite = productionViteResult.value;
|
|
1906
1925
|
logger.info("\u26A1 Building application bundles with Vite Rolldown");
|
|
1926
|
+
const mobileClient = shouldBuildFarmMobileClient(config);
|
|
1907
1927
|
const buildClientBundle = () => buildClient(
|
|
1908
1928
|
productionVite,
|
|
1909
1929
|
config,
|
|
@@ -1916,7 +1936,8 @@ ${islandsErrors.map((error) => ` - ${error}`).join("\n")}`
|
|
|
1916
1936
|
isolatedClientBoundaryModules,
|
|
1917
1937
|
hydrationPlanCache,
|
|
1918
1938
|
rendererBuildLifetime,
|
|
1919
|
-
routeManager.getProgrammaticClientRoutes()
|
|
1939
|
+
routeManager.getProgrammaticClientRoutes(),
|
|
1940
|
+
mobileClient
|
|
1920
1941
|
);
|
|
1921
1942
|
const buildSSRBundle = () => buildSSRInMemory(
|
|
1922
1943
|
productionVite,
|
|
@@ -1969,7 +1990,8 @@ ${islandsErrors.map((error) => ` - ${error}`).join("\n")}`
|
|
|
1969
1990
|
isolatedClientBoundaryModules,
|
|
1970
1991
|
hydrationPlanCache,
|
|
1971
1992
|
rendererBuildLifetime,
|
|
1972
|
-
routeManager.getProgrammaticClientRoutes()
|
|
1993
|
+
routeManager.getProgrammaticClientRoutes(),
|
|
1994
|
+
mobileClient
|
|
1973
1995
|
);
|
|
1974
1996
|
} catch (retryError) {
|
|
1975
1997
|
if (!(retryError instanceof IncompleteClientBuildOutputError)) throw retryError;
|
|
@@ -2028,6 +2050,27 @@ ${islandsErrors.map((error) => ` - ${error}`).join("\n")}`
|
|
|
2028
2050
|
rendererBuild?.abort();
|
|
2029
2051
|
}
|
|
2030
2052
|
}
|
|
2053
|
+
function shouldBuildFarmMobileClient(config, options = {}) {
|
|
2054
|
+
if (!config.mobileClient || config.desktop) return false;
|
|
2055
|
+
const mode = resolveFarmServerComponentsMode(config.experimental?.serverComponents);
|
|
2056
|
+
if (mode === void 0) return true;
|
|
2057
|
+
if (!options.quiet)
|
|
2058
|
+
logger.info(
|
|
2059
|
+
`\u{1F4F1} No mobile client for experimental.serverComponents (${mode}) yet; a mobile shell loads the web client.`
|
|
2060
|
+
);
|
|
2061
|
+
return false;
|
|
2062
|
+
}
|
|
2063
|
+
function varyFarmNitroCacheRulesByShell(rules) {
|
|
2064
|
+
return Object.fromEntries(
|
|
2065
|
+
Object.entries(rules).map(([source, rule]) => {
|
|
2066
|
+
const cached = rule?.swr !== void 0 && rule.swr !== false || rule?.cache !== void 0 && rule.cache !== false;
|
|
2067
|
+
if (!cached || rule.cache === false) return [source, rule];
|
|
2068
|
+
const cache = rule.cache && typeof rule.cache === "object" ? rule.cache : {};
|
|
2069
|
+
const varies = [...Array.isArray(cache.varies) ? cache.varies : [], "x-farm-shell"];
|
|
2070
|
+
return [source, { ...rule, cache: { ...cache, varies } }];
|
|
2071
|
+
})
|
|
2072
|
+
);
|
|
2073
|
+
}
|
|
2031
2074
|
async function writeSSRAssetsToClient(bundle, outputDir) {
|
|
2032
2075
|
const fs4 = await import("fs/promises");
|
|
2033
2076
|
for (const [fileName, output] of Object.entries(bundle)) {
|
|
@@ -2121,7 +2164,8 @@ function getCachedClientModuleHydrationPlan(modulePath, root, mode, cache, optio
|
|
|
2121
2164
|
}
|
|
2122
2165
|
return { ...plan, isolatedBoundaries: [...plan.isolatedBoundaries] };
|
|
2123
2166
|
}
|
|
2124
|
-
async function buildClient(productionVite, config, root, srcDir, outputDir, pageRoutes, layoutRoutes = [], routeSlots = [], isolatedClientBoundaryModules = /* @__PURE__ */ new Set(), hydrationPlanCache = /* @__PURE__ */ new Map(), rendererBuildLifetime, programmaticClientRoutes) {
|
|
2167
|
+
async function buildClient(productionVite, config, root, srcDir, outputDir, pageRoutes, layoutRoutes = [], routeSlots = [], isolatedClientBoundaryModules = /* @__PURE__ */ new Set(), hydrationPlanCache = /* @__PURE__ */ new Map(), rendererBuildLifetime, programmaticClientRoutes, mobile = false) {
|
|
2168
|
+
if (!mobile) await removeFarmMobileClientManifest(path10.dirname(outputDir));
|
|
2125
2169
|
const viteBuild = productionVite.build;
|
|
2126
2170
|
const { farmPlugin, farmServerOnlyEntriesPlugin } = await import("./vite.mjs");
|
|
2127
2171
|
const { PluginManager: PluginManager2 } = await import("./plugin-53SY5YBS.mjs");
|
|
@@ -2364,206 +2408,229 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
|
|
|
2364
2408
|
logger.info(
|
|
2365
2409
|
`\u{1F4F1} Total hydratable routes detected: ${clientPages.length} pages, ${clientLayouts.filter((layout) => layout.shouldHydrate || layout.hasIsolatedClientBoundaries).length} layouts, and ${clientRouteSlots.length} slots`
|
|
2366
2410
|
);
|
|
2367
|
-
const
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
srcDir,
|
|
2377
|
-
adapterOwnsDocsRuntime ? false : isFarmDocsSearchEnabled(config.docs),
|
|
2378
|
-
adapterOwnsDocsRuntime ? void 0 : resolveFarmDocsSearchClientModule(root),
|
|
2379
|
-
config.docs?.enabled ? getFarmDocsRoots(config.docs).map((docsRoot) => docsRoot.entry) : void 0,
|
|
2380
|
-
adapterOwnsDocsRuntime ? config.docs.adapter?.react : void 0,
|
|
2381
|
-
config.i18n,
|
|
2382
|
-
config.plugins,
|
|
2383
|
-
config.renderer,
|
|
2384
|
-
config.publicRuntimeConfig,
|
|
2385
|
-
config.trailingSlash,
|
|
2386
|
-
getIntegrationProviders(config.integrations),
|
|
2387
|
-
config.basePath,
|
|
2388
|
-
generateClientCachePersistenceCode(resolveFarmClientCacheAdapterEntry(root, config.cache)),
|
|
2389
|
-
adapterOwnsDocsRuntime ? getFarmDocsAdapterConfigModule(config.docs) : void 0,
|
|
2390
|
-
resolveFarmServerComponentsMode(config.experimental?.serverComponents) === "islands"
|
|
2391
|
-
);
|
|
2392
|
-
await fs4.writeFile(clientEntryPath, clientHydrationCode);
|
|
2393
|
-
const hasScopedPostcssConfig = hasProjectPostcssConfig(root);
|
|
2394
|
-
let postcssSearchPath;
|
|
2395
|
-
let tailwindVitePlugin = void 0;
|
|
2396
|
-
const rendererVitePlugins = await loadFarmRendererVitePlugins(config.renderer, root, {
|
|
2397
|
-
ssr: false,
|
|
2398
|
-
buildLifetime: rendererBuildLifetime
|
|
2399
|
-
});
|
|
2400
|
-
if (hasScopedPostcssConfig) {
|
|
2401
|
-
logger.info("\u{1F4E6} Using project PostCSS/Tailwind configuration");
|
|
2402
|
-
} else {
|
|
2403
|
-
const postcssConfigPath = path10.join(clientEntryDir, "postcss.config.cjs");
|
|
2404
|
-
await fs4.writeFile(postcssConfigPath, "module.exports = { plugins: [] };\n");
|
|
2405
|
-
postcssSearchPath = clientEntryDir;
|
|
2406
|
-
tailwindVitePlugin = await loadTailwindVitePlugin({
|
|
2407
|
-
builder: productionVite.builder,
|
|
2408
|
-
announce: true
|
|
2409
|
-
});
|
|
2410
|
-
}
|
|
2411
|
-
try {
|
|
2412
|
-
const clientViteConfig = {
|
|
2411
|
+
const buildTarget = async (platform) => {
|
|
2412
|
+
const clientEntryRoot = path10.join(root, ".farm", "tmp");
|
|
2413
|
+
await fs4.mkdir(clientEntryRoot, { recursive: true });
|
|
2414
|
+
const clientEntryDir = await fs4.mkdtemp(path10.join(clientEntryRoot, "client-entry-"));
|
|
2415
|
+
const clientEntryPath = path10.join(clientEntryDir, "farm-client-entry.tsx");
|
|
2416
|
+
const clientHydrationCode = generateClientHydrationEntry(
|
|
2417
|
+
clientPages,
|
|
2418
|
+
clientLayouts,
|
|
2419
|
+
clientRouteSlots,
|
|
2413
2420
|
root,
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2421
|
+
srcDir,
|
|
2422
|
+
adapterOwnsDocsRuntime ? false : isFarmDocsSearchEnabled(config.docs),
|
|
2423
|
+
adapterOwnsDocsRuntime ? void 0 : resolveFarmDocsSearchClientModule(root),
|
|
2424
|
+
config.docs?.enabled ? getFarmDocsRoots(config.docs).map((docsRoot) => docsRoot.entry) : void 0,
|
|
2425
|
+
adapterOwnsDocsRuntime ? config.docs.adapter?.react : void 0,
|
|
2426
|
+
config.i18n,
|
|
2427
|
+
config.plugins,
|
|
2428
|
+
config.renderer,
|
|
2429
|
+
config.publicRuntimeConfig,
|
|
2430
|
+
config.trailingSlash,
|
|
2431
|
+
getIntegrationProviders(config.integrations),
|
|
2432
|
+
config.basePath,
|
|
2433
|
+
generateClientCachePersistenceCode(resolveFarmClientCacheAdapterEntry(root, config.cache)),
|
|
2434
|
+
adapterOwnsDocsRuntime ? getFarmDocsAdapterConfigModule(config.docs) : void 0,
|
|
2435
|
+
resolveFarmServerComponentsMode(config.experimental?.serverComponents) === "islands",
|
|
2436
|
+
platform
|
|
2437
|
+
);
|
|
2438
|
+
const entryName = platform === "mobile" ? FARM_MOBILE_CLIENT_ENTRY_NAME : "farm-client";
|
|
2439
|
+
await fs4.writeFile(clientEntryPath, clientHydrationCode);
|
|
2440
|
+
const hasScopedPostcssConfig = hasProjectPostcssConfig(root);
|
|
2441
|
+
let postcssSearchPath;
|
|
2442
|
+
let tailwindVitePlugin = void 0;
|
|
2443
|
+
const rendererVitePlugins = await loadFarmRendererVitePlugins(config.renderer, root, {
|
|
2444
|
+
ssr: false,
|
|
2445
|
+
buildLifetime: rendererBuildLifetime
|
|
2446
|
+
});
|
|
2447
|
+
if (hasScopedPostcssConfig) {
|
|
2448
|
+
logger.info("\u{1F4E6} Using project PostCSS/Tailwind configuration");
|
|
2449
|
+
} else {
|
|
2450
|
+
const postcssConfigPath = path10.join(clientEntryDir, "postcss.config.cjs");
|
|
2451
|
+
await fs4.writeFile(postcssConfigPath, "module.exports = { plugins: [] };\n");
|
|
2452
|
+
postcssSearchPath = clientEntryDir;
|
|
2453
|
+
tailwindVitePlugin = await loadTailwindVitePlugin({
|
|
2454
|
+
builder: productionVite.builder,
|
|
2455
|
+
announce: true
|
|
2456
|
+
});
|
|
2457
|
+
}
|
|
2458
|
+
try {
|
|
2459
|
+
const clientViteConfig = {
|
|
2460
|
+
root,
|
|
2461
|
+
// Vite otherwise falls back to <root>/public, silently dropping every
|
|
2462
|
+
// asset in a custom config.publicDir from the production client output.
|
|
2463
|
+
// The mobile client adds to the web client's output; public files are copied once.
|
|
2464
|
+
publicDir: platform === "mobile" ? false : config.publicDir,
|
|
2465
|
+
esbuild: {
|
|
2466
|
+
jsxDev: false
|
|
2467
|
+
},
|
|
2468
|
+
build: {
|
|
2469
|
+
// Preserve Farm's Vite 5 browser baseline when the production builder
|
|
2470
|
+
// uses Vite 8, whose default target only covers newer browsers.
|
|
2471
|
+
target: FARM_CLIENT_BUILD_TARGET,
|
|
2472
|
+
outDir: outputDir,
|
|
2473
|
+
emptyOutDir: platform === "web",
|
|
2474
|
+
// Never public: see resolveFarmClientSourcemap.
|
|
2475
|
+
sourcemap: resolveFarmClientSourcemap(config.vite?.build?.sourcemap),
|
|
2476
|
+
assetsInlineLimit: 0,
|
|
2477
|
+
cssCodeSplit: false,
|
|
2478
|
+
// Bundle all CSS into one file
|
|
2479
|
+
rollupOptions: {
|
|
2480
|
+
input: {
|
|
2481
|
+
[entryName]: clientEntryPath
|
|
2482
|
+
},
|
|
2483
|
+
output: {
|
|
2484
|
+
entryFileNames: "[name]-h[hash].js",
|
|
2485
|
+
chunkFileNames: "chunks/[name]-h[hash].js",
|
|
2486
|
+
hashCharacters: "hex",
|
|
2487
|
+
// Use predictable name for CSS so we can reference it in SSR HTML
|
|
2488
|
+
assetFileNames: (assetInfo) => {
|
|
2489
|
+
if (assetInfo.name?.endsWith(".css")) {
|
|
2490
|
+
return `${entryName}.css`;
|
|
2491
|
+
}
|
|
2492
|
+
return "assets/[name]-h[hash][extname]";
|
|
2443
2493
|
}
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
return
|
|
2494
|
+
},
|
|
2495
|
+
// A browser cannot load a Node builtin: farmServerOnlyEntriesPlugin
|
|
2496
|
+
// resolves one to Farm's browser module for it instead.
|
|
2497
|
+
external: (id) => {
|
|
2498
|
+
if (id === "fsevents" || id.includes("fsevents") || id.endsWith(".node")) {
|
|
2499
|
+
return true;
|
|
2500
|
+
}
|
|
2501
|
+
return false;
|
|
2452
2502
|
}
|
|
2453
|
-
return false;
|
|
2454
2503
|
}
|
|
2455
|
-
}
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2504
|
+
},
|
|
2505
|
+
plugins: [
|
|
2506
|
+
createFarmThemeCssPlugin(config.theme, config.basePath),
|
|
2507
|
+
createFarmPrivateClientSourcemapsPlugin({
|
|
2508
|
+
outDir: path10.join(
|
|
2509
|
+
path10.dirname(outputDir),
|
|
2510
|
+
platform === "mobile" ? `${FARM_CLIENT_SOURCEMAPS_DIR}-mobile` : FARM_CLIENT_SOURCEMAPS_DIR
|
|
2511
|
+
)
|
|
2512
|
+
}),
|
|
2513
|
+
// The web client's preload manifests; the mobile client records its files instead.
|
|
2514
|
+
platform === "mobile" ? createFarmMobileClientManifestPlugin({
|
|
2515
|
+
buildDir: path10.dirname(outputDir),
|
|
2516
|
+
entryName
|
|
2517
|
+
}) : createFarmClientModulePreloadPlugin({
|
|
2469
2518
|
root,
|
|
2470
2519
|
buildDir: path10.dirname(outputDir),
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2520
|
+
entryName: "farm-client"
|
|
2521
|
+
}),
|
|
2522
|
+
...adapterOwnsDocsRuntime && platform === "web" ? [
|
|
2523
|
+
createFarmDocsModulePreloadPlugin({
|
|
2524
|
+
root,
|
|
2525
|
+
buildDir: path10.dirname(outputDir),
|
|
2526
|
+
importer: clientEntryPath,
|
|
2527
|
+
entryName: "farm-client",
|
|
2528
|
+
modules: [
|
|
2529
|
+
config.docs.adapter.react,
|
|
2530
|
+
getFarmDocsAdapterConfigModule(config.docs)
|
|
2531
|
+
].filter((specifier) => Boolean(specifier))
|
|
2532
|
+
})
|
|
2533
|
+
] : [],
|
|
2534
|
+
...tailwindVitePlugin ? [tailwindVitePlugin] : [],
|
|
2535
|
+
...rendererVitePlugins,
|
|
2536
|
+
...config.vite.plugins || [],
|
|
2537
|
+
farmServerOnlyEntriesPlugin({ platform }),
|
|
2538
|
+
farmDocsClientConfigPlugin(
|
|
2539
|
+
adapterOwnsDocsRuntime ? getFarmDocsAdapterConfigModule(config.docs) : void 0
|
|
2540
|
+
),
|
|
2541
|
+
// Plugin to redirect @farm.js/core imports to client-only exports
|
|
2542
|
+
{
|
|
2543
|
+
name: "farm-client-only-imports",
|
|
2544
|
+
enforce: "pre",
|
|
2545
|
+
resolveId(id) {
|
|
2546
|
+
if (id === "@farm.js/core") {
|
|
2547
|
+
return { id: "\0farm-client-exports", external: false };
|
|
2548
|
+
}
|
|
2549
|
+
if (id === "@farm.js/core/i18n/server") {
|
|
2550
|
+
return { id: "\0farm-i18n-client-bridge", external: false };
|
|
2551
|
+
}
|
|
2552
|
+
if (id === "@farm.js/core/server" || id === "@farm.js/core/api" || id === "@farm.js/core/middleware" || id === "@farm.js/core/headers" || id === "@farm.js/core/config" || id.includes("@farm.js/core/middleware") || id.includes("@farm.js/core/query/server")) {
|
|
2553
|
+
return { id: "\0empty-module", external: false };
|
|
2554
|
+
}
|
|
2555
|
+
if (id.includes("/api/") && id.includes("/route")) {
|
|
2556
|
+
return { id: "\0empty-api-route", external: false };
|
|
2557
|
+
}
|
|
2558
|
+
if (id === "fsevents" || id.includes("fsevents") || id.endsWith(".node") || id === "nitro" || id === "vite" || id === "esbuild" || id === "rolldown" || id.startsWith("rolldown/") || id === "rollup" || id.startsWith("nitro/") || id.includes("node-pre-gyp") || id.includes("nf3")) {
|
|
2559
|
+
return { id: "\0empty-module", external: false };
|
|
2560
|
+
}
|
|
2561
|
+
return null;
|
|
2562
|
+
},
|
|
2563
|
+
load(id) {
|
|
2564
|
+
if (id === "\0empty-module") {
|
|
2565
|
+
return "const emptyMiddlewareStore = new Map(); export default {}; export const getMiddlewareContext = () => emptyMiddlewareStore; export const getMiddlewareData = () => emptyMiddlewareStore; export const getMiddlewareValue = () => undefined; export const middleware = () => ({});";
|
|
2566
|
+
}
|
|
2567
|
+
if (id === "\0empty-api-route") {
|
|
2568
|
+
return "export const GET = () => {}; export const HEAD = () => {}; export const QUERY = () => {}; export const POST = () => {}; export const PUT = () => {}; export const DELETE = () => {}; export const PATCH = () => {}; export const OPTIONS = () => {}; export default {};";
|
|
2569
|
+
}
|
|
2570
|
+
if (id === "\0farm-i18n-client-bridge") {
|
|
2571
|
+
return 'export { createTranslator, format, getLocale, getLocaleSource, t } from "@farm.js/core/i18n/client";';
|
|
2572
|
+
}
|
|
2573
|
+
if (id === "\0farm-client-exports") {
|
|
2574
|
+
return [
|
|
2575
|
+
"// Farm.js Client Exports - Safe for browser bundling",
|
|
2576
|
+
'export { Link } from "@farm.js/core/client";',
|
|
2577
|
+
'export { useRouter } from "@farm.js/core/client";',
|
|
2578
|
+
'export { usePathname, useSearchParams } from "@farm.js/core/navigation";',
|
|
2579
|
+
// A page that hydrates ships to the browser with its notFound()/redirect() calls.
|
|
2580
|
+
'export { getFarmRedirectError, isFarmNotFoundError, isFarmRedirectError, notFound, permanentRedirect, redirect } from "@farm.js/core/navigation";',
|
|
2581
|
+
'export { createAPIClient } from "@farm.js/core/client";',
|
|
2582
|
+
'export { localFont, remoteFont } from "@farm.js/core/font";'
|
|
2583
|
+
].join("\n");
|
|
2584
|
+
}
|
|
2585
|
+
return null;
|
|
2505
2586
|
}
|
|
2506
|
-
return null;
|
|
2507
2587
|
},
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
'export { useRouter } from "@farm.js/core/client";',
|
|
2523
|
-
'export { usePathname, useSearchParams } from "@farm.js/core/navigation";',
|
|
2524
|
-
// A page that hydrates ships to the browser with its notFound()/redirect() calls.
|
|
2525
|
-
'export { getFarmRedirectError, isFarmNotFoundError, isFarmRedirectError, notFound, permanentRedirect, redirect } from "@farm.js/core/navigation";',
|
|
2526
|
-
'export { createAPIClient } from "@farm.js/core/client";',
|
|
2527
|
-
'export { localFont, remoteFont } from "@farm.js/core/font";'
|
|
2528
|
-
].join("\n");
|
|
2529
|
-
}
|
|
2530
|
-
return null;
|
|
2531
|
-
}
|
|
2588
|
+
farmPlugin(
|
|
2589
|
+
{ ...config, isolatedClientBoundaryModules, programmaticClientRoutes },
|
|
2590
|
+
pluginManager
|
|
2591
|
+
),
|
|
2592
|
+
farmEnvironmentFunctionsPlugin(config)
|
|
2593
|
+
],
|
|
2594
|
+
mode: "production",
|
|
2595
|
+
css: postcssSearchPath ? {
|
|
2596
|
+
postcss: postcssSearchPath
|
|
2597
|
+
} : void 0,
|
|
2598
|
+
// Ensure React is bundled for client
|
|
2599
|
+
resolve: {
|
|
2600
|
+
alias: createFarmSourceAlias(root, config.srcDir),
|
|
2601
|
+
dedupe: [...config.renderer.dedupe || []]
|
|
2532
2602
|
},
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
}
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2603
|
+
// Optimize dependencies - exclude server-side code from client bundle
|
|
2604
|
+
optimizeDeps: {
|
|
2605
|
+
exclude: [
|
|
2606
|
+
"@farm.js/core/server",
|
|
2607
|
+
"@farm.js/core/api",
|
|
2608
|
+
"@farm.js/core/middleware",
|
|
2609
|
+
"@farm.js/core/headers"
|
|
2610
|
+
]
|
|
2611
|
+
}
|
|
2612
|
+
};
|
|
2613
|
+
await viteBuild(mergeFarmProductionViteConfig(clientViteConfig, config.vite));
|
|
2614
|
+
if (platform === "mobile") {
|
|
2615
|
+
await fs4.rm(path10.join(outputDir, `${entryName}.css`), { force: true });
|
|
2616
|
+
if (!await hasFarmMobileClientEntry(path10.dirname(outputDir), outputDir)) {
|
|
2617
|
+
throw new IncompleteClientBuildOutputError(
|
|
2618
|
+
`${FARM_MOBILE_CLIENT_ENTRY_NAME}.js is missing or empty`
|
|
2619
|
+
);
|
|
2620
|
+
}
|
|
2621
|
+
} else {
|
|
2622
|
+
await mergeBuiltFontCss(outputDir);
|
|
2623
|
+
await validateClientBuildOutput(root, srcDir, outputDir);
|
|
2624
|
+
}
|
|
2625
|
+
} finally {
|
|
2626
|
+
try {
|
|
2627
|
+
await fs4.rm(clientEntryDir, { recursive: true, force: true });
|
|
2628
|
+
} catch {
|
|
2556
2629
|
}
|
|
2557
|
-
};
|
|
2558
|
-
await viteBuild(mergeFarmProductionViteConfig(clientViteConfig, config.vite));
|
|
2559
|
-
await mergeBuiltFontCss(outputDir);
|
|
2560
|
-
await validateClientBuildOutput(root, srcDir, outputDir);
|
|
2561
|
-
} finally {
|
|
2562
|
-
try {
|
|
2563
|
-
await fs4.rm(clientEntryDir, { recursive: true, force: true });
|
|
2564
|
-
} catch {
|
|
2565
2630
|
}
|
|
2566
|
-
}
|
|
2631
|
+
};
|
|
2632
|
+
await buildTarget("web");
|
|
2633
|
+
if (mobile) await buildTarget("mobile");
|
|
2567
2634
|
}
|
|
2568
2635
|
function toBakedMarkdownSourcePath(root, filePath) {
|
|
2569
2636
|
if (!filePath) return "";
|
|
@@ -2642,21 +2709,24 @@ async function fetchFarmNavigationDocument(url, headers, recover = true, signal)
|
|
|
2642
2709
|
return response;
|
|
2643
2710
|
}
|
|
2644
2711
|
|
|
2645
|
-
${streamNavigations ?
|
|
2646
|
-
|
|
2647
|
-
// Reads a streamed navigation (F-Stream) up to the end of React's shell. \`next\` then resolves
|
|
2712
|
+
${streamNavigations ? `// Reads a streamed navigation (F-Stream) up to the end of React's shell. \`next\` then resolves
|
|
2648
2713
|
// with each later flush as it ends, and null at the end; a document without a marker is all shell.
|
|
2649
|
-
|
|
2714
|
+
// The marker carries the random token the server sent in the F-Flush header, so page content
|
|
2715
|
+
// cannot forge a boundary; a response without a valid token is all shell.
|
|
2716
|
+
async function readFarmNavigationStream(body, flushToken) {
|
|
2650
2717
|
const reader = body.getReader();
|
|
2651
2718
|
const decoder = new TextDecoder();
|
|
2719
|
+
const marker = typeof flushToken === "string" && /^[0-9a-f]{32}$/.test(flushToken)
|
|
2720
|
+
? "<!--farm-flush:" + flushToken + "-->"
|
|
2721
|
+
: "";
|
|
2652
2722
|
let text = "";
|
|
2653
2723
|
let done = false;
|
|
2654
2724
|
const next = async function() {
|
|
2655
2725
|
for (;;) {
|
|
2656
|
-
const at = text.indexOf(
|
|
2726
|
+
const at = marker ? text.indexOf(marker) : -1;
|
|
2657
2727
|
if (at !== -1) {
|
|
2658
2728
|
const flush = text.slice(0, at);
|
|
2659
|
-
text = text.slice(at +
|
|
2729
|
+
text = text.slice(at + marker.length);
|
|
2660
2730
|
return flush;
|
|
2661
2731
|
}
|
|
2662
2732
|
if (done) {
|
|
@@ -3230,7 +3300,7 @@ ${streamNavigations ? ` // A streamed navigation swaps in the page's shell; its
|
|
|
3230
3300
|
}
|
|
3231
3301
|
};
|
|
3232
3302
|
${streamNavigations ? ` if (streamShell && response.body) {
|
|
3233
|
-
const streamed = await readFarmNavigationStream(response.body);
|
|
3303
|
+
const streamed = await readFarmNavigationStream(response.body, response.headers.get("F-Flush"));
|
|
3234
3304
|
if (!streamed.next) {
|
|
3235
3305
|
store(streamed.shell);
|
|
3236
3306
|
return streamed.shell;
|
|
@@ -3436,13 +3506,14 @@ function generateClientHydrationEntry(clientPages, layoutRoutes, clientRouteSlot
|
|
|
3436
3506
|
secure: false
|
|
3437
3507
|
},
|
|
3438
3508
|
direction: {}
|
|
3439
|
-
}, plugins = [], renderer = REACT_RENDERER, publicRuntimeConfig = void 0, trailingSlash = false, integrationProviders = [], basePath = "/", clientCachePersistence = { imports: "", init: "" }, docsConfigModule, islandValues = false) {
|
|
3509
|
+
}, plugins = [], renderer = REACT_RENDERER, publicRuntimeConfig = void 0, trailingSlash = false, integrationProviders = [], basePath = "/", clientCachePersistence = { imports: "", init: "" }, docsConfigModule, islandValues = false, platform) {
|
|
3440
3510
|
const toImportPath = (targetPath) => targetPath.replace(/\\/g, "/");
|
|
3441
3511
|
const clientPluginEntry = generateFarmClientPluginEntryCode(
|
|
3442
3512
|
plugins,
|
|
3443
3513
|
root,
|
|
3444
3514
|
srcDir,
|
|
3445
|
-
publicRuntimeConfig
|
|
3515
|
+
publicRuntimeConfig,
|
|
3516
|
+
platform
|
|
3446
3517
|
);
|
|
3447
3518
|
const appSetupPath = resolveFarmRendererAppSetup(root, renderer);
|
|
3448
3519
|
const rendererClientImports = isReactRenderer(renderer) ? `import React from "react";
|
|
@@ -5953,6 +6024,7 @@ ReactDOMServer.configureApp(__farmAppSetup);`;
|
|
|
5953
6024
|
}
|
|
5954
6025
|
function generateVirtualEntryCode(apiRoutes, pageRoutes, layoutRoutes, routeSlots, errorRoutes, metadataImageRoutes, applicationMetadataRoutes, middlewareRoutes, redirectRoutes, configuredRewriteRoutes, configuredHeaderRoutes, openAPIReference, notFoundPath, instrumentationPath, config, farmDocsPrecompiledManifest, configModulePath, hasServerRuntimeIntegrations, hasRuntimeIntegrationConfig, hasConfiguredRuntimePlugins, hasServerRuntimePlugins, preset, i18nCatalogs, isolatedClientBoundaryModules, hydrationPlanCache) {
|
|
5955
6026
|
const farmIslandsMode = resolveFarmServerComponentsMode(config.experimental?.serverComponents) === "islands";
|
|
6027
|
+
const farmMobileClient = shouldBuildFarmMobileClient(config, { quiet: true });
|
|
5956
6028
|
const hasCompressionRuntime = config.compress && resolveFarmInstrumentationRuntime(preset) === "nodejs";
|
|
5957
6029
|
const servesAgentRobotsTxt = Boolean(config.agent?.crawlers?.enabled) && !applicationMetadataRoutes.some(
|
|
5958
6030
|
(metadata) => metadata.kind === "robots" && metadata.pattern === "/"
|
|
@@ -6381,8 +6453,22 @@ function renderFarmServerTreeLayout(Layout, props, outlets) {
|
|
|
6381
6453
|
stripFarmLocaleFromPathname,
|
|
6382
6454
|
withFarmRouteContext,
|
|
6383
6455
|
createLateNotFoundRecovery,
|
|
6384
|
-
createLateRedirectRecovery,${hasInfraAnalyticsRuntime ? "\n resolveFarmDocsEngineRouteLabel,\n resolveFarmDocsRouteLabel,\n resolveFarmMarkdownRouteLabel,\n resolveFarmMCPRouteLabel,\n setFarmRouteLabel," : ""}${hasFarmServerStorageConfig(config.storage) ? "\n _registerFarmStorageModules,\n disposeFarmStorage,\n initFarmStorage," : ""}
|
|
6385
|
-
} from "@farm.js/core/internal/production-runtime";${
|
|
6456
|
+
createLateRedirectRecovery,${config.mobileClient ? "\n createFarmNativeTreeResponse," : ""}${hasInfraAnalyticsRuntime ? "\n resolveFarmDocsEngineRouteLabel,\n resolveFarmDocsRouteLabel,\n resolveFarmMarkdownRouteLabel,\n resolveFarmMCPRouteLabel,\n setFarmRouteLabel," : ""}${hasFarmServerStorageConfig(config.storage) ? "\n _registerFarmStorageModules,\n disposeFarmStorage,\n initFarmStorage," : ""}
|
|
6457
|
+
} from "@farm.js/core/internal/production-runtime";${farmMobileClient ? `
|
|
6458
|
+
import { _applyFarmMobileShellClient } from "@farm.js/core/internal/production-runtime";
|
|
6459
|
+
// The mobile client documents load when a mobile shell asks for them (RFC 0004, 7.2), filled in
|
|
6460
|
+
// once the client build has finished (see buildNitroUniversal). A shell's document stays out of
|
|
6461
|
+
// shared caches, which the adapter learns as it does for a guarded response.
|
|
6462
|
+
const farmMobileShellClient = JSON.parse("${FARM_MOBILE_SHELL_CLIENT_PLACEHOLDER}");
|
|
6463
|
+
function applyFarmMobileShellResponse(request, response, context) {
|
|
6464
|
+
return _applyFarmMobileShellClient(request, response, farmMobileShellClient, () =>
|
|
6465
|
+
context?.onGuardedResponse?.()
|
|
6466
|
+
);
|
|
6467
|
+
}` : `
|
|
6468
|
+
// No mobile block: no mobile client, and documents ignore X-Farm-Shell.
|
|
6469
|
+
function applyFarmMobileShellResponse(request, response) {
|
|
6470
|
+
return response;
|
|
6471
|
+
}`}${farmIslandsMode ? `
|
|
6386
6472
|
import { getSharedLayoutPrefixLength, handleFarmFormActionRequest, ignoreFarmHeldValues, installFarmIslandValues, parseFarmLayoutChainHeader } from "@farm.js/core/internal/production-runtime";
|
|
6387
6473
|
import { installFarmIslandsServer } from "@farm.js/core/internal/islands-server";
|
|
6388
6474
|
installFarmIslandsServer();
|
|
@@ -6433,12 +6519,16 @@ import { fileURLToPath as farmDocsFileURLToPath } from "node:url";` : "";
|
|
|
6433
6519
|
const instrumentationImport = instrumentationPath ? `import * as FarmInstrumentationModule from ${toVirtualEntryImportSpecifier(instrumentationPath)};` : "";
|
|
6434
6520
|
const nativeAuth = generateNativeAuthIntegrationSource(config.auth);
|
|
6435
6521
|
const nativeMCP = generateNativeMCPPluginSource(config.mcp);
|
|
6522
|
+
const mobileSession = (config.plugins || []).some(
|
|
6523
|
+
(plugin) => plugin?.name === FARM_MOBILE_SESSION_PLUGIN
|
|
6524
|
+
);
|
|
6436
6525
|
const integrationImports = `
|
|
6437
6526
|
${configModulePath ? `import * as FarmUserConfigModule from ${toVirtualEntryImportSpecifier(configModulePath)};` : ""}
|
|
6438
6527
|
${layerConfigImports}
|
|
6439
6528
|
${integrationRuntimeImport}
|
|
6440
6529
|
${nativeAuth.importSource}
|
|
6441
6530
|
${nativeMCP.importSource}
|
|
6531
|
+
${mobileSession ? `import { createFarmMobileSessionPlugin as __farmCreateMobileSessionPlugin } from "@farm.js/core/internal/production-runtime";` : ""}
|
|
6442
6532
|
`;
|
|
6443
6533
|
const imageRuntime = resolveFarmImageServerRuntime(config.images, preset);
|
|
6444
6534
|
const imageRuntimeImport = imageRuntime === "none" ? "" : `import { _withFarmImageSourceClientAddress, createCloudflareImageTransformer, createFarmImageHandler } from "@farm.js/core/image/server";`;
|
|
@@ -6719,6 +6809,10 @@ const configuredPlugins = [
|
|
|
6719
6809
|
${hasCompressionRuntime && hasPluginRuntime ? "createCompressionPlugin()," : ""}
|
|
6720
6810
|
${hasRuntimeIntegrationConfig ? "...resolveIntegrationPlugins(serverRuntimeIntegrations)," : ""}
|
|
6721
6811
|
${nativeMCP.pluginSource}
|
|
6812
|
+
${mobileSession ? `__farmCreateMobileSessionPlugin({
|
|
6813
|
+
basePath: ${JSON.stringify(config.basePath)},
|
|
6814
|
+
integrations: () => serverRuntimeIntegrations,
|
|
6815
|
+
}),` : ""}
|
|
6722
6816
|
${hasConfiguredRuntimePlugins ? `...farmRuntimeConfigs.flatMap((runtimeConfig) =>
|
|
6723
6817
|
Array.isArray(runtimeConfig.plugins) ? runtimeConfig.plugins : [],
|
|
6724
6818
|
),` : ""}
|
|
@@ -7078,10 +7172,22 @@ function escapeFarmHtmlAttribute(value) {
|
|
|
7078
7172
|
.replace(/>/g, ">");
|
|
7079
7173
|
}
|
|
7080
7174
|
|
|
7081
|
-
|
|
7082
|
-
|
|
7175
|
+
// A streamed navigation's flush marker token: 128 random bits, hex.
|
|
7176
|
+
function createFarmFlushToken() {
|
|
7177
|
+
const bytes = new Uint8Array(16);
|
|
7178
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
7179
|
+
let token = "";
|
|
7180
|
+
for (const byte of bytes) token += byte.toString(16).padStart(2, "0");
|
|
7181
|
+
return token;
|
|
7182
|
+
}
|
|
7183
|
+
|
|
7184
|
+
async function renderFarmElement(ReactDOMServer, element, routeKey, flushToken = "") {
|
|
7185
|
+
// Written after each React flush in a streamed navigation (flushToken): the browser swaps in
|
|
7083
7186
|
// the shell, then adds each Suspense boundary as soon as the flush that completed it ends.
|
|
7084
|
-
|
|
7187
|
+
// The token is random per response and reaches the browser in the F-Flush header, so page
|
|
7188
|
+
// content cannot forge a boundary.
|
|
7189
|
+
const flushMarkers = Boolean(flushToken);
|
|
7190
|
+
const FARM_FLUSH_MARKER = flushMarkers ? "<!--farm-flush:" + flushToken + "-->" : "";
|
|
7085
7191
|
// Islands mode: each render writes its islands' values itself, so a request that renders twice
|
|
7086
7192
|
// (notFound(), or a synchronous attempt that suspends and streams) still sends them.
|
|
7087
7193
|
if (typeof farmIslandsRender === "function") element = farmIslandsRender(element);
|
|
@@ -9097,6 +9203,21 @@ ${hasServerRuntimeIntegrations ? `
|
|
|
9097
9203
|
}
|
|
9098
9204
|
` : ""}
|
|
9099
9205
|
|
|
9206
|
+
${config.mobileClient ? `
|
|
9207
|
+
// The mobile app's native-tier screens: the page, rendered as for a browser, read into a
|
|
9208
|
+
// tree of native views.
|
|
9209
|
+
if (
|
|
9210
|
+
(request.method === "GET" || request.method === "HEAD") &&
|
|
9211
|
+
request.headers.get("accept")?.includes(${JSON.stringify(FARM_NATIVE_TREE_CONTENT_TYPE)})
|
|
9212
|
+
) {
|
|
9213
|
+
const treeResponse = await createFarmNativeTreeResponse({
|
|
9214
|
+
request,
|
|
9215
|
+
renderPage: (targetRequest) => fetchFarmInnerRequest(targetRequest, adapterContext),
|
|
9216
|
+
});
|
|
9217
|
+
return applyProductionMiddlewareHeaders(treeResponse, middlewareHeaders);
|
|
9218
|
+
}
|
|
9219
|
+
` : ""}
|
|
9220
|
+
|
|
9100
9221
|
${config.md?.enabled ? `
|
|
9101
9222
|
if (farmMarkdownConfig?.enabled) {
|
|
9102
9223
|
const markdownResponse = await createMarkdownMirrorResponse({
|
|
@@ -9619,10 +9740,13 @@ ${hasServerRuntimeIntegrations ? `
|
|
|
9619
9740
|
!route.shouldHydrate &&
|
|
9620
9741
|
request.headers.get("f-render") === "tree";
|
|
9621
9742
|
// A navigation the browser streams marks where each React flush ends, so the browser
|
|
9622
|
-
// shows the page before its Suspense content arrives (FARM_FLUSH_MARKER).
|
|
9623
|
-
|
|
9743
|
+
// shows the page before its Suspense content arrives (FARM_FLUSH_MARKER). The marker
|
|
9744
|
+
// carries a random token sent in the F-Flush header: page content cannot forge one.
|
|
9745
|
+
const farmFlushToken = request.headers.get("f-stream") === "flush"
|
|
9746
|
+
? createFarmFlushToken()
|
|
9747
|
+
: "";` : `const farmLayoutKeyOf = null;
|
|
9624
9748
|
const farmPayloadOnlyNavigation = false;
|
|
9625
|
-
const
|
|
9749
|
+
const farmFlushToken = "";`}
|
|
9626
9750
|
const renderPageElement = async () => {
|
|
9627
9751
|
// First, render the page content
|
|
9628
9752
|
let pageElement;
|
|
@@ -9744,7 +9868,7 @@ ${hasServerRuntimeIntegrations ? `
|
|
|
9744
9868
|
}
|
|
9745
9869
|
|
|
9746
9870
|
wrappedElement = wrapWithFarmIntegrationProviders(wrappedElement);
|
|
9747
|
-
return renderFarmElement(ReactDOMServer, wrappedElement, route.pattern,
|
|
9871
|
+
return renderFarmElement(ReactDOMServer, wrappedElement, route.pattern, farmFlushToken);
|
|
9748
9872
|
};
|
|
9749
9873
|
const renderedPage = ${hasMiddlewareRuntime ? `await _runWithMiddlewareData(middlewareData, () =>
|
|
9750
9874
|
_runWithMiddlewareContext(middlewareContext, renderPageElement)
|
|
@@ -10051,7 +10175,11 @@ ${hasServerRuntimeIntegrations ? `
|
|
|
10051
10175
|
);
|
|
10052
10176
|
return applyProductionMiddlewareHeaders(farmOwnedResponse(streamedDocument, {
|
|
10053
10177
|
status: pageStatus,
|
|
10054
|
-
headers: {
|
|
10178
|
+
headers: {
|
|
10179
|
+
...responseHeaders,
|
|
10180
|
+
"x-farm-preload-streaming": "1",
|
|
10181
|
+
...(farmFlushToken ? { "F-Flush": farmFlushToken } : {}),
|
|
10182
|
+
},
|
|
10055
10183
|
}), middlewareHeaders);
|
|
10056
10184
|
}
|
|
10057
10185
|
|
|
@@ -10576,10 +10704,11 @@ async function handleFarmFetch(request, context) {
|
|
|
10576
10704
|
? getFarmRoutePathname(new URL(runtimeRequest.url).pathname)
|
|
10577
10705
|
: undefined;
|
|
10578
10706
|
const configured = applyConfiguredResponseHeaders(response, routePathname);
|
|
10707
|
+
// Configured headers may edit the response in place, so check it either way.
|
|
10708
|
+
const guarded = farmGuardedResponse ? _withFarmGuardedResponseCache(configured) : configured;
|
|
10579
10709
|
return applyFarmPreloadBudget(
|
|
10580
10710
|
applyFarmCspNonceToResponse(
|
|
10581
|
-
|
|
10582
|
-
farmGuardedResponse ? _withFarmGuardedResponseCache(configured) : configured,
|
|
10711
|
+
applyFarmMobileShellResponse(runtimeRequest, guarded, context),
|
|
10583
10712
|
farmSecurityConfig,
|
|
10584
10713
|
cspNonce,
|
|
10585
10714
|
),
|
|
@@ -10886,8 +11015,20 @@ async function buildNitroUniversal(config, routeManager, apiRouteManager, server
|
|
|
10886
11015
|
]);
|
|
10887
11016
|
const encodedDocsModulePreloads = encodeFarmDocsModulePreloads(docsModulePreloads);
|
|
10888
11017
|
const encodedClientModulePreloads = encodeFarmClientModulePreloads(clientModulePreloads);
|
|
11018
|
+
const encodedMobileShellClient = shouldBuildFarmMobileClient(config, { quiet: true }) ? encodeFarmMobileShellClient(
|
|
11019
|
+
await finalizeFarmMobileClient({
|
|
11020
|
+
buildDir: path10.join(root, distDir),
|
|
11021
|
+
clientOutputDir,
|
|
11022
|
+
webEntry: clientJsSrc,
|
|
11023
|
+
stylesheet: clientCssHref,
|
|
11024
|
+
webFiles: clientModulePreloads?.files ?? []
|
|
11025
|
+
})
|
|
11026
|
+
) : null;
|
|
10889
11027
|
for (const output of Object.values(ssrBundle)) {
|
|
10890
11028
|
if (output.type !== "chunk") continue;
|
|
11029
|
+
if (encodedMobileShellClient && output.code.includes(FARM_MOBILE_SHELL_CLIENT_PLACEHOLDER)) {
|
|
11030
|
+
output.code = output.code.split(FARM_MOBILE_SHELL_CLIENT_PLACEHOLDER).join(encodedMobileShellClient);
|
|
11031
|
+
}
|
|
10891
11032
|
if (output.code.includes(FARM_DOCS_MODULE_PRELOADS_PLACEHOLDER)) {
|
|
10892
11033
|
output.code = output.code.split(FARM_DOCS_MODULE_PRELOADS_PLACEHOLDER).join(encodedDocsModulePreloads);
|
|
10893
11034
|
}
|
|
@@ -10902,11 +11043,13 @@ async function buildNitroUniversal(config, routeManager, apiRouteManager, server
|
|
|
10902
11043
|
}
|
|
10903
11044
|
}
|
|
10904
11045
|
await fs4.mkdir(ssrOutputDir, { recursive: true });
|
|
10905
|
-
|
|
10906
|
-
|
|
10907
|
-
|
|
10908
|
-
|
|
10909
|
-
|
|
11046
|
+
await Promise.all(
|
|
11047
|
+
Object.entries(ssrBundle).map(async ([fileName, output]) => {
|
|
11048
|
+
const filePath = path10.join(ssrOutputDir, fileName);
|
|
11049
|
+
await fs4.mkdir(path10.dirname(filePath), { recursive: true });
|
|
11050
|
+
await fs4.writeFile(filePath, output.type === "chunk" ? output.code : output.source);
|
|
11051
|
+
})
|
|
11052
|
+
);
|
|
10910
11053
|
const nitroEntryPath = path10.join(ssrOutputDir, "nitro-entry.mjs");
|
|
10911
11054
|
const nodeAdapterModule = preset === "node-server" ? resolveNitroRuntimeDependency(root, "srvx/node") : null;
|
|
10912
11055
|
const hasNitroCacheRouteRules = hasFarmNitroCacheRouteRule(config.routeRules);
|
|
@@ -11163,7 +11306,7 @@ function toFarmNodeResponse(request, response) {
|
|
|
11163
11306
|
ssrOutputDir,
|
|
11164
11307
|
ssrEntryFile
|
|
11165
11308
|
);
|
|
11166
|
-
const configuredNitroRouteRules = routeRulesToNitroRouteRules(config.routeRules);
|
|
11309
|
+
const configuredNitroRouteRules = shouldBuildFarmMobileClient(config, { quiet: true }) ? varyFarmNitroCacheRulesByShell(routeRulesToNitroRouteRules(config.routeRules)) : routeRulesToNitroRouteRules(config.routeRules);
|
|
11167
11310
|
const prerenderNitroRouteRules = Object.fromEntries(
|
|
11168
11311
|
prerenderRoutes.map((route) => {
|
|
11169
11312
|
const configuredRule = configuredNitroRouteRules[route] || {};
|
|
@@ -11210,10 +11353,18 @@ function toFarmNodeResponse(request, response) {
|
|
|
11210
11353
|
// fixed top quality cost a docs app ~20 s of build CPU for a small further
|
|
11211
11354
|
// saving. Serverless and edge targets sit behind a CDN that compresses.
|
|
11212
11355
|
...preset === "node-server" ? { compressPublicAssets: { gzip: true } } : {},
|
|
11356
|
+
// Nitro gzips every server output file at level 9, node_modules included, to
|
|
11357
|
+
// print sizes after the build. A self-hosted server is never shipped compressed,
|
|
11358
|
+
// so list plain sizes; zipped serverless and edge bundles keep the gzip column.
|
|
11359
|
+
...preset === "node-server" || preset === "bun" ? { logging: { compressedSizes: false } } : {},
|
|
11213
11360
|
...prerenderRoutes.length > 0 ? {
|
|
11214
11361
|
prerender: {
|
|
11215
11362
|
crawlLinks: false,
|
|
11216
11363
|
failOnError: true,
|
|
11364
|
+
// Nitro's default renders one route at a time. Each prerender request is
|
|
11365
|
+
// answered independently, as by the production server, so keeping several
|
|
11366
|
+
// in flight overlaps the worker's rendering with this thread's per-route work.
|
|
11367
|
+
concurrency: Math.min(os.availableParallelism(), 8),
|
|
11217
11368
|
routes: prerenderRoutes
|
|
11218
11369
|
}
|
|
11219
11370
|
} : {},
|
|
@@ -11311,6 +11462,22 @@ function toFarmNodeResponse(request, response) {
|
|
|
11311
11462
|
}
|
|
11312
11463
|
nitroConfig.minify = useFarmServerMinifier ? false : shouldMinify;
|
|
11313
11464
|
const nitroInstance = await nitroBuilder.createNitro(nitroConfig);
|
|
11465
|
+
let prerenderOrder = /* @__PURE__ */ new Map();
|
|
11466
|
+
nitroInstance.hooks.hook("prerender:routes", (routes) => {
|
|
11467
|
+
prerenderOrder = new Map(
|
|
11468
|
+
Array.from(routes, (route, index) => {
|
|
11469
|
+
try {
|
|
11470
|
+
return [decodeURI(route), index];
|
|
11471
|
+
} catch {
|
|
11472
|
+
return [route, index];
|
|
11473
|
+
}
|
|
11474
|
+
})
|
|
11475
|
+
);
|
|
11476
|
+
});
|
|
11477
|
+
nitroInstance.hooks.hook("prerender:done", ({ prerenderedRoutes }) => {
|
|
11478
|
+
const orderOf = (route) => prerenderOrder.get(route) ?? Number.MAX_SAFE_INTEGER;
|
|
11479
|
+
prerenderedRoutes.sort((a, b) => orderOf(a.route) - orderOf(b.route));
|
|
11480
|
+
});
|
|
11314
11481
|
if (config.md?.enabled) {
|
|
11315
11482
|
nitroInstance.hooks.hook("prerender:generate", (route) => {
|
|
11316
11483
|
if (!route.contents || !route.contentType?.toLowerCase().includes("html")) return;
|
|
@@ -11918,7 +12085,9 @@ async function createFarmProjectModuleSsrEnvironment() {
|
|
|
11918
12085
|
|
|
11919
12086
|
// src/build/index.ts
|
|
11920
12087
|
async function build(config, options = {}) {
|
|
11921
|
-
return withProductionNodeEnv(
|
|
12088
|
+
return withProductionNodeEnv(
|
|
12089
|
+
() => withPackageClientBoundaryCache(() => buildWithProductionNodeEnv(config, options))
|
|
12090
|
+
);
|
|
11922
12091
|
}
|
|
11923
12092
|
function createBuildTargetBaseline(config) {
|
|
11924
12093
|
const preset = config.preset || "node-server";
|
|
@@ -11991,6 +12160,9 @@ async function buildWithProductionNodeEnv(inputConfig, options) {
|
|
|
11991
12160
|
if (config.docs?.enabled) await loadFarmDocsEngine();
|
|
11992
12161
|
pluginManager.updateContext({ config });
|
|
11993
12162
|
const { root, preset, srcDir, distDir, deployOutputDir } = targets;
|
|
12163
|
+
usePackageClientBoundaryCacheFile(
|
|
12164
|
+
path11.resolve(root, distDir, "cache", "client-boundaries.json")
|
|
12165
|
+
);
|
|
11994
12166
|
logger.info(`\u{1F69C} Building Farm.js application with preset: ${preset}...`);
|
|
11995
12167
|
await pluginManager.setupPlugins();
|
|
11996
12168
|
await pluginManager.runHookParallel("beforeBundle", {
|