@quilted/quilt 0.5.135 → 0.5.137

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