@quilted/quilt 0.5.136 → 0.5.138

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.
Files changed (59) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/build/cjs/index.cjs +34 -0
  3. package/build/cjs/server/ServerContext.cjs +3 -3
  4. package/build/cjs/server/index.cjs +28 -14
  5. package/build/cjs/server/preload.cjs +37 -0
  6. package/build/cjs/server/request-router.cjs +73 -57
  7. package/build/cjs/static/StaticContext.cjs +3 -3
  8. package/build/cjs/static/index.cjs +30 -44
  9. package/build/cjs/static/render.cjs +9 -6
  10. package/build/esm/index.mjs +2 -0
  11. package/build/esm/server/ServerContext.mjs +3 -3
  12. package/build/esm/server/index.mjs +3 -2
  13. package/build/esm/server/preload.mjs +35 -0
  14. package/build/esm/server/request-router.mjs +55 -39
  15. package/build/esm/static/StaticContext.mjs +3 -3
  16. package/build/esm/static/index.mjs +25 -39
  17. package/build/esm/static/render.mjs +7 -4
  18. package/build/esnext/index.esnext +2 -0
  19. package/build/esnext/server/ServerContext.esnext +3 -3
  20. package/build/esnext/server/index.esnext +3 -2
  21. package/build/esnext/server/preload.esnext +35 -0
  22. package/build/esnext/server/request-router.esnext +55 -39
  23. package/build/esnext/static/StaticContext.esnext +3 -3
  24. package/build/esnext/static/index.esnext +25 -39
  25. package/build/esnext/static/render.esnext +7 -4
  26. package/build/tsconfig.tsbuildinfo +1 -1
  27. package/build/typescript/assets.d.ts +7 -0
  28. package/build/typescript/assets.d.ts.map +1 -0
  29. package/build/typescript/index.d.ts +3 -0
  30. package/build/typescript/index.d.ts.map +1 -1
  31. package/build/typescript/magic/assets.d.ts +3 -0
  32. package/build/typescript/magic/assets.d.ts.map +1 -0
  33. package/build/typescript/server/ServerContext.d.ts +5 -5
  34. package/build/typescript/server/ServerContext.d.ts.map +1 -1
  35. package/build/typescript/server/index.d.ts +4 -3
  36. package/build/typescript/server/index.d.ts.map +1 -1
  37. package/build/typescript/server/preload.d.ts +8 -0
  38. package/build/typescript/server/preload.d.ts.map +1 -0
  39. package/build/typescript/server/request-router.d.ts +23 -14
  40. package/build/typescript/server/request-router.d.ts.map +1 -1
  41. package/build/typescript/static/StaticContext.d.ts +5 -5
  42. package/build/typescript/static/StaticContext.d.ts.map +1 -1
  43. package/build/typescript/static/index.d.ts +3 -5
  44. package/build/typescript/static/index.d.ts.map +1 -1
  45. package/build/typescript/static/render.d.ts +6 -4
  46. package/build/typescript/static/render.d.ts.map +1 -1
  47. package/package.json +5 -3
  48. package/source/assets.ts +7 -0
  49. package/source/index.ts +19 -0
  50. package/source/magic/assets.ts +5 -0
  51. package/source/server/ServerContext.tsx +7 -10
  52. package/source/server/index.ts +19 -13
  53. package/source/server/preload.ts +69 -0
  54. package/source/server/request-router.tsx +129 -73
  55. package/source/static/StaticContext.tsx +7 -10
  56. package/source/static/index.tsx +30 -41
  57. package/source/static/render.tsx +9 -12
  58. package/tsconfig.json +2 -0
  59. package/source/magic/asset-manifest.ts +0 -5
@@ -1,14 +1,15 @@
1
- import {Fragment, type ReactElement, type LinkHTMLAttributes} from 'react';
1
+ import {Fragment, type ReactElement} from 'react';
2
2
 
3
3
  import {
4
4
  styleAssetAttributes,
5
5
  styleAssetPreloadAttributes,
6
6
  scriptAssetAttributes,
7
7
  scriptAssetPreloadAttributes,
8
- type AssetsEntry,
9
- type AssetManifest,
10
- } from '@quilted/async/server';
11
- import {AsyncAssetManager} from '@quilted/react-async/server';
8
+ type AssetsCacheKey,
9
+ type BrowserAssets,
10
+ type BrowserAssetsEntry,
11
+ } from '@quilted/assets';
12
+ import {AssetsManager} from '@quilted/react-assets/server';
12
13
  import {HttpManager} from '@quilted/react-http/server';
13
14
  import {
14
15
  renderHtmlToString,
@@ -30,39 +31,52 @@ import type {
30
31
 
31
32
  import {ServerContext} from './ServerContext';
32
33
 
33
- export interface ServerRenderOptions<Context = RequestContext> {
34
+ export interface ServerRenderOptions<
35
+ Context = RequestContext,
36
+ CacheKey = AssetsCacheKey,
37
+ > {
34
38
  stream?: 'headers' | false;
35
- assets?: AssetManifest<unknown>;
36
- extract?: ExtractOptions;
37
- context?(
38
- request: EnhancedRequest,
39
- context: Context,
40
- ): ServerRenderRequestContext;
39
+ assets?: BrowserAssets<CacheKey>;
40
+ extract?: Omit<ExtractOptions, 'context'> & {
41
+ readonly context?:
42
+ | ServerRenderRequestContext
43
+ | ((
44
+ request: EnhancedRequest,
45
+ context: Context,
46
+ ) => ServerRenderRequestContext);
47
+ };
41
48
  renderHtml?(
42
49
  content: string | undefined,
43
- request: Request,
44
50
  details: Pick<ServerRenderAppDetails, 'http' | 'html'> & {
45
- readonly assets?: AssetsEntry;
46
- readonly preloadAssets?: AssetsEntry;
51
+ readonly request: EnhancedRequest;
52
+ readonly context: Context;
53
+ readonly assets?: BrowserAssetsEntry;
54
+ readonly preloadAssets?: BrowserAssetsEntry;
47
55
  },
48
56
  ): ReactElement<any> | Promise<ReactElement<any>>;
49
57
  }
50
58
 
51
- export interface ServerRenderAppDetails {
59
+ export interface ServerRenderAppDetails<
60
+ _Context = RequestContext,
61
+ CacheKey = AssetsCacheKey,
62
+ > {
52
63
  readonly http: HttpManager;
53
64
  readonly html: HtmlManager;
65
+ readonly assets: AssetsManager<CacheKey>;
54
66
  readonly rendered?: string;
55
- readonly asyncAssets: AsyncAssetManager;
56
67
  }
57
68
 
58
- export function createServerRender<Context = RequestContext>(
69
+ export function createServerRender<
70
+ Context = RequestContext,
71
+ CacheKey = AssetsCacheKey,
72
+ >(
59
73
  getApp:
60
74
  | ReactElement<any>
61
75
  | ((
62
76
  request: EnhancedRequest,
63
77
  context: Context,
64
78
  ) => ReactElement<any> | Promise<ReactElement<any>>),
65
- {context, stream, ...options}: ServerRenderOptions<Context> = {},
79
+ {stream, ...options}: ServerRenderOptions<Context, CacheKey> = {},
66
80
  ): RequestHandler<Context> {
67
81
  return async (request, requestContext) => {
68
82
  const accepts = request.headers.get('Accept');
@@ -77,36 +91,46 @@ export function createServerRender<Context = RequestContext>(
77
91
  typeof getApp === 'function'
78
92
  ? () => getApp(request, requestContext)
79
93
  : getApp,
80
- request,
81
94
  {
82
95
  ...options,
96
+ request,
97
+ context: requestContext,
83
98
  extract: {
84
99
  ...options.extract,
85
100
  context:
86
- options.extract ??
87
- context?.(request, requestContext) ??
88
- (requestContext as any),
101
+ typeof options.extract?.context === 'function'
102
+ ? options.extract.context(request, requestContext)
103
+ : options.extract?.context,
89
104
  },
90
105
  },
91
106
  );
92
107
  };
93
108
  }
94
109
 
95
- export async function renderAppToResponse(
110
+ export async function renderAppToResponse<
111
+ Context = RequestContext,
112
+ CacheKey = AssetsCacheKey,
113
+ >(
96
114
  getApp:
97
115
  | ReactElement<any>
98
116
  | (() => ReactElement<any> | Promise<ReactElement<any>>),
99
- request: Request,
100
117
  {
118
+ request,
119
+ context,
101
120
  assets,
102
121
  extract,
103
122
  renderHtml,
104
- }: Pick<ServerRenderOptions, 'assets' | 'renderHtml' | 'extract'> = {},
123
+ }: Pick<
124
+ ServerRenderOptions<Context, CacheKey>,
125
+ 'assets' | 'renderHtml' | 'extract'
126
+ > & {readonly request: EnhancedRequest; readonly context: Context},
105
127
  ) {
106
128
  const app = typeof getApp === 'function' ? await getApp() : getApp;
129
+ const cacheKey = (await assets?.cacheKey?.(request)) as CacheKey;
107
130
 
108
131
  const renderDetails = await serverRenderDetailsForApp(app, {
109
132
  extract,
133
+ cacheKey,
110
134
  url: request.url,
111
135
  headers: request.headers,
112
136
  });
@@ -120,10 +144,15 @@ export async function renderAppToResponse(
120
144
  });
121
145
  }
122
146
 
123
- const content = await renderAppDetailsToHtmlString(renderDetails, request, {
124
- assets,
125
- renderHtml,
126
- });
147
+ const content = await renderAppDetailsToHtmlString<Context, CacheKey>(
148
+ renderDetails,
149
+ {
150
+ request,
151
+ context,
152
+ assets,
153
+ renderHtml,
154
+ },
155
+ );
127
156
 
128
157
  return html(content, {
129
158
  headers,
@@ -131,22 +160,29 @@ export async function renderAppToResponse(
131
160
  });
132
161
  }
133
162
 
134
- export async function renderAppToStreamedResponse(
163
+ export async function renderAppToStreamedResponse<
164
+ Context = RequestContext,
165
+ CacheKey = AssetsCacheKey,
166
+ >(
135
167
  getApp:
136
168
  | ReactElement<any>
137
169
  | (() => ReactElement<any> | Promise<ReactElement<any>>),
138
- request: Request,
139
170
  {
171
+ request,
172
+ context,
140
173
  assets,
141
174
  extract,
142
175
  renderHtml,
143
- }: Pick<ServerRenderOptions, 'assets' | 'renderHtml' | 'extract'> = {},
176
+ }: Pick<
177
+ ServerRenderOptions<Context, CacheKey>,
178
+ 'assets' | 'renderHtml' | 'extract'
179
+ > & {readonly request: EnhancedRequest; readonly context: Context},
144
180
  ) {
145
181
  const headers = new Headers();
146
182
  const stream = new TransformStream();
147
183
 
148
- const assetContext = {userAgent: request.headers.get('User-Agent')};
149
- const guaranteedAssets = await assets?.assets({context: assetContext});
184
+ const cacheKey = (await assets?.cacheKey?.(request)) as CacheKey;
185
+ const guaranteedAssets = await assets?.entry({cacheKey});
150
186
 
151
187
  if (guaranteedAssets) {
152
188
  for (const style of guaranteedAssets.styles) {
@@ -173,14 +209,20 @@ export async function renderAppToStreamedResponse(
173
209
 
174
210
  const renderDetails = await serverRenderDetailsForApp(app, {
175
211
  extract,
212
+ cacheKey,
176
213
  url: request.url,
177
214
  headers: request.headers,
178
215
  });
179
216
 
180
- const content = await renderAppDetailsToHtmlString(renderDetails, request, {
181
- assets,
182
- renderHtml,
183
- });
217
+ const content = await renderAppDetailsToHtmlString<Context, CacheKey>(
218
+ renderDetails,
219
+ {
220
+ request,
221
+ context,
222
+ assets,
223
+ renderHtml,
224
+ },
225
+ );
184
226
 
185
227
  const encoder = new TextEncoder();
186
228
  const writer = stream.writable.getWriter();
@@ -189,34 +231,34 @@ export async function renderAppToStreamedResponse(
189
231
  }
190
232
  }
191
233
 
192
- async function serverRenderDetailsForApp(
234
+ async function serverRenderDetailsForApp<
235
+ Context = RequestContext,
236
+ CacheKey = AssetsCacheKey,
237
+ >(
193
238
  app: ReactElement<any>,
194
239
  {
195
240
  url,
196
241
  headers,
242
+ cacheKey,
197
243
  extract: extractOptions,
198
244
  }: Pick<ServerRenderOptions, 'extract'> & {
199
245
  url?: string | URL;
246
+ cacheKey?: CacheKey;
200
247
  headers?: NonNullable<
201
248
  ConstructorParameters<typeof HttpManager>[0]
202
249
  >['headers'];
203
250
  } = {},
204
- ): Promise<ServerRenderAppDetails> {
251
+ ): Promise<ServerRenderAppDetails<Context, CacheKey>> {
205
252
  const html = new HtmlManager();
206
- const asyncAssets = new AsyncAssetManager();
207
253
  const http = new HttpManager({headers});
254
+ const assets = new AssetsManager<CacheKey>({cacheKey});
208
255
 
209
256
  const {decorate, ...rest} = extractOptions ?? {};
210
257
 
211
258
  const rendered = await extract(app, {
212
259
  decorate(app) {
213
260
  return (
214
- <ServerContext
215
- asyncAssets={asyncAssets}
216
- http={http}
217
- html={html}
218
- url={url}
219
- >
261
+ <ServerContext http={http} html={html} url={url} assets={assets}>
220
262
  {decorate?.(app) ?? app}
221
263
  </ServerContext>
222
264
  );
@@ -224,32 +266,42 @@ async function serverRenderDetailsForApp(
224
266
  ...rest,
225
267
  });
226
268
 
227
- return {rendered, http, html, asyncAssets};
269
+ return {rendered, http, html, assets};
228
270
  }
229
271
 
230
- async function renderAppDetailsToHtmlString(
231
- details: ServerRenderAppDetails,
232
- request: Request,
272
+ async function renderAppDetailsToHtmlString<
273
+ Context = RequestContext,
274
+ CacheKey = AssetsCacheKey,
275
+ >(
276
+ details: ServerRenderAppDetails<Context, CacheKey>,
233
277
  {
278
+ request,
279
+ context,
234
280
  assets,
235
281
  renderHtml = defaultRenderHtml,
236
- }: Pick<ServerRenderOptions, 'assets' | 'renderHtml'> = {},
282
+ }: Pick<ServerRenderOptions<Context, CacheKey>, 'assets' | 'renderHtml'> & {
283
+ readonly request: EnhancedRequest;
284
+ readonly context: Context;
285
+ readonly cacheKey?: Partial<CacheKey>;
286
+ },
237
287
  ) {
238
- const {html: htmlManager, http, rendered, asyncAssets} = details;
288
+ const {http, rendered, html: htmlManager, assets: assetsManager} = details;
239
289
 
240
- const usedAssets = asyncAssets.used({timing: 'load'});
241
- const assetContext = {userAgent: request.headers.get('User-Agent')};
290
+ const cacheKey = assetsManager.cacheKey as CacheKey;
291
+ const usedModules = assetsManager.usedModules({timing: 'load'});
242
292
 
243
293
  const [entryAssets, preloadAssets] = assets
244
294
  ? await Promise.all([
245
- assets.assets({async: usedAssets, context: assetContext}),
246
- assets.asyncAssets(asyncAssets.used({timing: 'preload'}), {
247
- context: assetContext,
295
+ assets.entry({modules: usedModules, cacheKey}),
296
+ assets.modules(assetsManager.usedModules({timing: 'preload'}), {
297
+ cacheKey,
248
298
  }),
249
299
  ])
250
300
  : [];
251
301
 
252
- const htmlElement = await renderHtml(rendered, request, {
302
+ const htmlElement = await renderHtml(rendered, {
303
+ request,
304
+ context,
253
305
  html: htmlManager,
254
306
  http,
255
307
  assets: entryAssets,
@@ -260,7 +312,7 @@ async function renderAppDetailsToHtmlString(
260
312
  }
261
313
 
262
314
  const defaultRenderHtml: NonNullable<ServerRenderOptions<any>['renderHtml']> =
263
- function defaultRenderHtml(content, request, {html, assets, preloadAssets}) {
315
+ function defaultRenderHtml(content, {request, html, assets, preloadAssets}) {
264
316
  const baseUrl = new URL(request.url);
265
317
 
266
318
  return (
@@ -269,14 +321,14 @@ const defaultRenderHtml: NonNullable<ServerRenderOptions<any>['renderHtml']> =
269
321
  headEndContent={
270
322
  <>
271
323
  {assets &&
272
- [...assets.styles].map((style) => {
324
+ assets.styles.map((style) => {
273
325
  const attributes = styleAssetAttributes(style, {baseUrl});
274
- return <link key={style.source} {...attributes} />;
326
+ return <link key={style.source} {...(attributes as any)} />;
275
327
  })}
276
328
 
277
329
  {assets &&
278
- [...assets.scripts].map((script) => {
279
- const isModule = script.attributes.type === 'module';
330
+ assets.scripts.map((script) => {
331
+ const isModule = script.attributes?.type === 'module';
280
332
 
281
333
  const attributes = scriptAssetAttributes(script, {
282
334
  baseUrl,
@@ -285,31 +337,35 @@ const defaultRenderHtml: NonNullable<ServerRenderOptions<any>['renderHtml']> =
285
337
  if (isModule) {
286
338
  return (
287
339
  <Fragment key={script.source}>
288
- <link {...scriptAssetPreloadAttributes(script)} />
289
- <script {...attributes} async />
340
+ <link
341
+ {...(scriptAssetPreloadAttributes(script) as any)}
342
+ />
343
+ <script {...(attributes as any)} async />
290
344
  </Fragment>
291
345
  );
292
346
  }
293
347
 
294
- return <script key={script.source} {...attributes} defer />;
348
+ return (
349
+ <script key={script.source} {...(attributes as any)} defer />
350
+ );
295
351
  })}
296
352
 
297
353
  {preloadAssets &&
298
- [...preloadAssets.styles].map((style) => {
354
+ preloadAssets.styles.map((style) => {
299
355
  const attributes = styleAssetPreloadAttributes(style, {
300
356
  baseUrl,
301
357
  });
302
358
 
303
- return <link key={style.source} {...attributes} />;
359
+ return <link key={style.source} {...(attributes as any)} />;
304
360
  })}
305
361
 
306
362
  {preloadAssets &&
307
- [...preloadAssets.scripts].map((script) => {
363
+ preloadAssets.scripts.map((script) => {
308
364
  const attributes = scriptAssetPreloadAttributes(script, {
309
365
  baseUrl,
310
366
  });
311
367
 
312
- return <link key={script.source} {...attributes} />;
368
+ return <link key={script.source} {...(attributes as any)} />;
313
369
  })}
314
370
  </>
315
371
  }
@@ -319,7 +375,7 @@ const defaultRenderHtml: NonNullable<ServerRenderOptions<any>['renderHtml']> =
319
375
  );
320
376
  };
321
377
 
322
- function preloadHeader(attributes: LinkHTMLAttributes<HTMLLinkElement>) {
378
+ function preloadHeader(attributes: Partial<HTMLLinkElement>) {
323
379
  const {
324
380
  as,
325
381
  rel = 'preload',
@@ -1,12 +1,9 @@
1
1
  import type {PropsWithChildren} from 'react';
2
2
 
3
+ import {AssetsContext, type AssetsManager} from '@quilted/react-assets/server';
3
4
  import {InitialUrlContext} from '@quilted/react-router';
4
- import {HtmlContext} from '@quilted/react-html/server';
5
- import type {HtmlManager} from '@quilted/react-html/server';
6
- import {AsyncAssetContext} from '@quilted/react-async/server';
7
- import type {AsyncAssetManager} from '@quilted/react-async/server';
8
- import {HttpServerContext} from '@quilted/react-http/server';
9
- import type {HttpManager} from '@quilted/react-http/server';
5
+ import {HtmlContext, type HtmlManager} from '@quilted/react-html/server';
6
+ import {HttpServerContext, type HttpManager} from '@quilted/react-http/server';
10
7
 
11
8
  import {maybeWrapContext} from '../utilities/react';
12
9
 
@@ -14,21 +11,21 @@ interface Props {
14
11
  url?: string | URL;
15
12
  html?: HtmlManager;
16
13
  http?: HttpManager;
17
- asyncAssets?: AsyncAssetManager;
14
+ assets?: AssetsManager;
18
15
  }
19
16
 
20
17
  export function StaticContext({
21
18
  url,
22
19
  html,
23
20
  http,
24
- asyncAssets,
21
+ assets,
25
22
  children,
26
23
  }: PropsWithChildren<Props>) {
27
24
  const normalizedUrl = typeof url === 'string' ? new URL(url) : url;
28
25
 
29
26
  return maybeWrapContext(
30
- AsyncAssetContext,
31
- asyncAssets,
27
+ AssetsContext,
28
+ assets,
32
29
  maybeWrapContext(
33
30
  HttpServerContext,
34
31
  http,
@@ -1,12 +1,12 @@
1
- import type {ComponentType} from 'react';
1
+ import {Fragment, type ComponentType} from 'react';
2
2
 
3
3
  import {
4
4
  styleAssetAttributes,
5
5
  styleAssetPreloadAttributes,
6
6
  scriptAssetAttributes,
7
7
  scriptAssetPreloadAttributes,
8
- type AssetManifest,
9
- } from '@quilted/async/server';
8
+ type BrowserAssets,
9
+ } from '@quilted/assets';
10
10
  import {renderHtmlToString, Html} from '@quilted/react-html/server';
11
11
  import type {RouteDefinition} from '@quilted/react-router';
12
12
  import {
@@ -32,7 +32,7 @@ interface RenderableRoute {
32
32
 
33
33
  export interface Options {
34
34
  routes: string[];
35
- assets: AssetManifest<{modules: boolean}>;
35
+ assets: BrowserAssets<any>;
36
36
  crawl?: boolean;
37
37
  baseUrl?: string;
38
38
  prettify?: boolean;
@@ -212,13 +212,16 @@ export async function renderStatic(
212
212
  forceFallback: fallback ? url.pathname : undefined,
213
213
  });
214
214
 
215
+ const initialCacheKey = await assets.cacheKey?.(new Request(url));
216
+
215
217
  const {
216
218
  http,
217
219
  html: htmlManager,
220
+ assets: assetsManager,
218
221
  markup,
219
- asyncAssets,
220
222
  } = await renderApp(<App />, {
221
223
  url,
224
+ cacheKey: initialCacheKey,
222
225
  decorate(app) {
223
226
  return (
224
227
  <StaticRendererContext.Provider value={routeRecorder}>
@@ -228,71 +231,57 @@ export async function renderStatic(
228
231
  },
229
232
  });
230
233
 
231
- const usedAssets = asyncAssets.used({timing: 'load'});
234
+ const cacheKey = assetsManager.cacheKey;
232
235
 
233
- const [moduleAssets, modulePreload, nomoduleAssets] = await Promise.all([
234
- assets.assets({async: usedAssets, context: {modules: true}}),
235
- assets.asyncAssets(asyncAssets.used({timing: 'preload'}), {
236
- context: {modules: true},
236
+ const [mainAssets, preloadAssets] = await Promise.all([
237
+ assets.entry({
238
+ modules: assetsManager.usedModules({timing: 'load'}),
239
+ cacheKey,
240
+ }),
241
+ assets.modules(assetsManager.usedModules({timing: 'preload'}), {
242
+ cacheKey,
237
243
  }),
238
- assets.assets({async: usedAssets, context: {modules: false}}),
239
244
  ]);
240
245
 
241
- // We don’t want to load styles from both bundles, so we only use module styles,
242
- // since modules are intended to be the default and CSS (usually) doesn’t
243
- // have features that meaningfully break older user agents.
244
- const styles =
245
- moduleAssets.styles.length > 0
246
- ? moduleAssets.styles
247
- : nomoduleAssets.styles;
248
-
249
246
  const minifiedHtml = renderHtmlToString(
250
247
  <Html
251
248
  manager={htmlManager}
252
249
  headEndContent={
253
250
  <>
254
- {[...styles].map((style) => {
251
+ {[...mainAssets.styles].map((style) => {
255
252
  const attributes = styleAssetAttributes(style, {baseUrl: url});
256
- return <link key={style.source} {...attributes} />;
257
- })}
258
-
259
- {[...moduleAssets.scripts].map((script) => {
260
- const attributes = scriptAssetAttributes(script, {
261
- baseUrl: url,
262
- });
263
-
264
- return <script key={script.source} {...attributes} />;
253
+ return <link key={style.source} {...(attributes as any)} />;
265
254
  })}
266
255
 
267
- {[...nomoduleAssets.scripts].map((script) => {
256
+ {[...mainAssets.scripts].map((script) => {
268
257
  const attributes = scriptAssetAttributes(script, {
269
258
  baseUrl: url,
270
259
  });
271
260
 
272
- return (
273
- <script
274
- key={script.source}
275
- {...attributes}
276
- // @ts-expect-error Rendering to HTML, so using the lowercase name
277
- nomodule={moduleAssets.scripts.length > 0 ? true : undefined}
278
- />
261
+ return attributes.type === 'module' ? (
262
+ <Fragment key={script.source}>
263
+ <link {...(scriptAssetPreloadAttributes(script) as any)} />
264
+ <script {...(attributes as any)} />
265
+ </Fragment>
266
+ ) : (
267
+ <script key={script.source} {...(attributes as any)} />
279
268
  );
280
269
  })}
281
270
 
282
- {[...modulePreload.styles].map((style) => {
271
+ {[...preloadAssets.styles].map((style) => {
283
272
  const attributes = styleAssetPreloadAttributes(style, {
284
273
  baseUrl: url,
285
274
  });
286
275
 
287
- return <link key={style.source} {...attributes} />;
276
+ return <link key={style.source} {...(attributes as any)} />;
288
277
  })}
289
278
 
290
- {[...modulePreload.scripts].map((script) => {
279
+ {[...preloadAssets.scripts].map((script) => {
291
280
  const attributes = scriptAssetPreloadAttributes(script, {
292
281
  baseUrl: url,
293
282
  });
294
283
 
295
- return <link key={script.source} {...attributes} />;
284
+ return <link key={script.source} {...(attributes as any)} />;
296
285
  })}
297
286
  </>
298
287
  }
@@ -4,34 +4,31 @@ import {extract} from '@quilted/react-server-render/server';
4
4
  import type {Options as ExtractOptions} from '@quilted/react-server-render/server';
5
5
  import {HtmlManager} from '@quilted/react-html/server';
6
6
  import {HttpManager} from '@quilted/react-http/server';
7
- import {AsyncAssetManager} from '@quilted/react-async/server';
7
+ import {AssetsManager} from '@quilted/react-assets/server';
8
+ import type {AssetsCacheKey} from '@quilted/assets';
8
9
 
9
10
  import {StaticContext} from './StaticContext';
10
11
 
11
- interface Options extends ExtractOptions {
12
+ interface Options<CacheKey = AssetsCacheKey> extends ExtractOptions {
12
13
  url?: string | URL;
14
+ cacheKey?: CacheKey;
13
15
  headers?: NonNullable<
14
16
  ConstructorParameters<typeof HttpManager>[0]
15
17
  >['headers'];
16
18
  }
17
19
 
18
- export async function renderApp(
20
+ export async function renderApp<CacheKey = AssetsCacheKey>(
19
21
  app: ReactElement<any>,
20
- {decorate, url, headers, ...rest}: Options = {},
22
+ {decorate, url, headers, cacheKey, ...rest}: Options<CacheKey> = {},
21
23
  ) {
22
24
  const html = new HtmlManager();
23
- const asyncAssets = new AsyncAssetManager();
24
25
  const http = new HttpManager({headers});
26
+ const assets = new AssetsManager<CacheKey>({cacheKey});
25
27
 
26
28
  const markup = await extract(app, {
27
29
  decorate(app) {
28
30
  return (
29
- <StaticContext
30
- asyncAssets={asyncAssets}
31
- html={html}
32
- http={http}
33
- url={url}
34
- >
31
+ <StaticContext html={html} http={http} url={url} assets={assets}>
35
32
  {decorate?.(app) ?? app}
36
33
  </StaticContext>
37
34
  );
@@ -39,5 +36,5 @@ export async function renderApp(
39
36
  ...rest,
40
37
  });
41
38
 
42
- return {markup, http, html, asyncAssets};
39
+ return {markup, http, html, assets};
43
40
  }
package/tsconfig.json CHANGED
@@ -7,11 +7,13 @@
7
7
  "include": ["source"],
8
8
  "exclude": ["quilt.project.ts", "**/*.test.ts", "**/*.test.tsx"],
9
9
  "references": [
10
+ {"path": "../assets"},
10
11
  {"path": "../async"},
11
12
  {"path": "../events"},
12
13
  {"path": "../graphql"},
13
14
  {"path": "../polyfills"},
14
15
  {"path": "../react"},
16
+ {"path": "../react-assets"},
15
17
  {"path": "../react-async"},
16
18
  {"path": "../react-dom"},
17
19
  {"path": "../react-graphql"},
@@ -1,5 +0,0 @@
1
- import type {AssetManifest} from '@quilted/async/server';
2
-
3
- export declare function createAssetManifest(): AssetManifest<{
4
- userAgent?: string;
5
- }>;