@quilted/quilt 0.5.130 → 0.5.132

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @quilted/quilt
2
2
 
3
+ ## 0.5.132
4
+
5
+ ### Patch Changes
6
+
7
+ - [`ad97e366`](https://github.com/lemonmade/quilt/commit/ad97e366a1663d39873d5f0c37938e708069f9fa) Thanks [@lemonmade](https://github.com/lemonmade)! - Preserve async app getter through response creation
8
+
9
+ ## 0.5.131
10
+
11
+ ### Patch Changes
12
+
13
+ - [#508](https://github.com/lemonmade/quilt/pull/508) [`befb2aa9`](https://github.com/lemonmade/quilt/commit/befb2aa9d374aff66cbfe54fc8157522e3d3af21) Thanks [@lemonmade](https://github.com/lemonmade)! - Move logic out of HTML component
14
+
3
15
  ## 0.5.130
4
16
 
5
17
  ### Patch Changes
@@ -7,7 +7,6 @@ var server$3 = require('@quilted/react-async/server');
7
7
  var requestRouter = require('@quilted/react-localize/request-router');
8
8
  var requestRouter$1 = require('@quilted/request-router');
9
9
  var reactLocalize = require('@quilted/react-localize');
10
- var render = require('./render.cjs');
11
10
  var ServerContext = require('./ServerContext.cjs');
12
11
  var requestRouter$2 = require('./request-router.cjs');
13
12
 
@@ -61,6 +60,22 @@ Object.defineProperty(exports, 'createAssetManifest', {
61
60
  enumerable: true,
62
61
  get: function () { return server$2.createAssetManifest; }
63
62
  });
63
+ Object.defineProperty(exports, 'scriptAssetAttributes', {
64
+ enumerable: true,
65
+ get: function () { return server$2.scriptAssetAttributes; }
66
+ });
67
+ Object.defineProperty(exports, 'scriptAssetPreloadAttributes', {
68
+ enumerable: true,
69
+ get: function () { return server$2.scriptAssetPreloadAttributes; }
70
+ });
71
+ Object.defineProperty(exports, 'styleAssetAttributes', {
72
+ enumerable: true,
73
+ get: function () { return server$2.styleAssetAttributes; }
74
+ });
75
+ Object.defineProperty(exports, 'styleAssetPreloadAttributes', {
76
+ enumerable: true,
77
+ get: function () { return server$2.styleAssetPreloadAttributes; }
78
+ });
64
79
  Object.defineProperty(exports, 'ASYNC_ASSETS_SERVER_ACTION_ID', {
65
80
  enumerable: true,
66
81
  get: function () { return server$3.SERVER_ACTION_ID; }
@@ -105,7 +120,7 @@ Object.defineProperty(exports, 'parseAcceptLanguageHeader', {
105
120
  enumerable: true,
106
121
  get: function () { return reactLocalize.parseAcceptLanguageHeader; }
107
122
  });
108
- exports.renderApp = render.renderApp;
109
123
  exports.ServerContext = ServerContext.ServerContext;
110
124
  exports.createServerRender = requestRouter$2.createServerRender;
111
125
  exports.renderAppToResponse = requestRouter$2.renderAppToResponse;
126
+ exports.renderAppToStreamedResponse = requestRouter$2.renderAppToStreamedResponse;
@@ -1,36 +1,41 @@
1
1
  'use strict';
2
2
 
3
- var server = require('@quilted/react-html/server');
3
+ var react = require('react');
4
+ var server = require('@quilted/async/server');
5
+ var server$2 = require('@quilted/react-async/server');
6
+ var server$3 = require('@quilted/react-http/server');
7
+ var server$1 = require('@quilted/react-html/server');
8
+ var server$4 = require('@quilted/react-server-render/server');
4
9
  var requestRouter = require('@quilted/request-router');
5
- var render = require('./render.cjs');
10
+ var ServerContext = require('./ServerContext.cjs');
6
11
  var jsxRuntime = require('react/jsx-runtime');
7
12
 
8
- function createServerRender(render, {
13
+ function createServerRender(getApp, {
9
14
  context,
15
+ stream,
10
16
  ...options
11
17
  } = {}) {
12
18
  return async (request, requestContext) => {
13
19
  const accepts = request.headers.get('Accept');
14
20
  if (accepts != null && !accepts.includes('text/html')) return;
15
- const app = await render(request, requestContext);
16
- return renderAppToResponse(app, request, {
21
+ const renderResponse = stream ? renderAppToStreamedResponse : renderAppToResponse;
22
+ return renderResponse(typeof getApp === 'function' ? () => getApp(request, requestContext) : getApp, request, {
17
23
  ...options,
18
- context: context?.(request, requestContext) ?? requestContext
24
+ extract: {
25
+ ...options.extract,
26
+ context: options.extract ?? context?.(request, requestContext) ?? requestContext
27
+ }
19
28
  });
20
29
  };
21
30
  }
22
- async function renderAppToResponse(app, request, {
31
+ async function renderAppToResponse(getApp, request, {
23
32
  assets,
24
- renderHtml = defaultRenderHtml,
25
- ...options
33
+ extract,
34
+ renderHtml
26
35
  } = {}) {
27
- const {
28
- html: htmlManager,
29
- http,
30
- rendered,
31
- asyncAssets
32
- } = await render.renderApp(app, {
33
- ...options,
36
+ const app = typeof getApp === 'function' ? await getApp() : getApp;
37
+ const renderDetails = await serverRenderDetailsForApp(app, {
38
+ extract,
34
39
  url: request.url,
35
40
  headers: request.headers
36
41
  });
@@ -38,57 +43,203 @@ async function renderAppToResponse(app, request, {
38
43
  headers,
39
44
  statusCode = 200,
40
45
  redirectUrl
41
- } = http.state;
46
+ } = renderDetails.http.state;
42
47
  if (redirectUrl) {
43
48
  return requestRouter.redirect(redirectUrl, {
44
49
  status: statusCode,
45
50
  headers
46
51
  });
47
52
  }
53
+ const content = await renderAppDetailsToHtmlString(renderDetails, request, {
54
+ assets,
55
+ renderHtml
56
+ });
57
+ return requestRouter.html(content, {
58
+ headers,
59
+ status: statusCode
60
+ });
61
+ }
62
+ async function renderAppToStreamedResponse(getApp, request, {
63
+ assets,
64
+ extract,
65
+ renderHtml
66
+ } = {}) {
67
+ const headers = new Headers();
68
+ const stream = new TransformStream();
69
+ const assetContext = {
70
+ userAgent: request.headers.get('User-Agent')
71
+ };
72
+ const guaranteedAssets = await assets?.assets({
73
+ context: assetContext
74
+ });
75
+ if (guaranteedAssets) {
76
+ for (const style of guaranteedAssets.styles) {
77
+ headers.append('Link', preloadHeader(server.styleAssetPreloadAttributes(style)));
78
+ }
79
+ for (const script of guaranteedAssets.scripts) {
80
+ headers.append('Link', preloadHeader(server.scriptAssetPreloadAttributes(script)));
81
+ }
82
+ }
83
+ renderResponseToStream();
84
+ return requestRouter.html(stream.readable, {
85
+ headers,
86
+ status: 200
87
+ });
88
+ async function renderResponseToStream() {
89
+ const app = typeof getApp === 'function' ? await getApp() : getApp;
90
+ const renderDetails = await serverRenderDetailsForApp(app, {
91
+ extract,
92
+ url: request.url,
93
+ headers: request.headers
94
+ });
95
+ const content = await renderAppDetailsToHtmlString(renderDetails, request, {
96
+ assets,
97
+ renderHtml
98
+ });
99
+ const writer = stream.writable.getWriter();
100
+ await writer.write(content);
101
+ await writer.close();
102
+ }
103
+ }
104
+ async function serverRenderDetailsForApp(app, {
105
+ url,
106
+ headers,
107
+ extract: extractOptions
108
+ } = {}) {
109
+ const html = new server$1.HtmlManager();
110
+ const asyncAssets = new server$2.AsyncAssetManager();
111
+ const http = new server$3.HttpManager({
112
+ headers
113
+ });
114
+ const {
115
+ decorate,
116
+ ...rest
117
+ } = extractOptions ?? {};
118
+ const rendered = await server$4.extract(app, {
119
+ decorate(app) {
120
+ return /*#__PURE__*/jsxRuntime.jsx(ServerContext.ServerContext, {
121
+ asyncAssets: asyncAssets,
122
+ http: http,
123
+ html: html,
124
+ url: url,
125
+ children: decorate?.(app) ?? app
126
+ });
127
+ },
128
+ ...rest
129
+ });
130
+ return {
131
+ rendered,
132
+ http,
133
+ html,
134
+ asyncAssets
135
+ };
136
+ }
137
+ async function renderAppDetailsToHtmlString(details, request, {
138
+ assets,
139
+ renderHtml = defaultRenderHtml
140
+ } = {}) {
141
+ const {
142
+ html: htmlManager,
143
+ http,
144
+ rendered,
145
+ asyncAssets
146
+ } = details;
48
147
  const usedAssets = asyncAssets.used({
49
148
  timing: 'load'
50
149
  });
51
- const assetOptions = {
150
+ const assetContext = {
52
151
  userAgent: request.headers.get('User-Agent')
53
152
  };
54
- const [styles, scripts, preload] = assets ? await Promise.all([assets.styles({
153
+ const [entryAssets, preloadAssets] = assets ? await Promise.all([assets.assets({
55
154
  async: usedAssets,
56
- options: assetOptions
57
- }), assets.scripts({
58
- async: usedAssets,
59
- options: assetOptions
155
+ context: assetContext
60
156
  }), assets.asyncAssets(asyncAssets.used({
61
157
  timing: 'preload'
62
158
  }), {
63
- options: assetOptions
64
- })]) : [[], [], []];
159
+ context: assetContext
160
+ })]) : [];
65
161
  const htmlElement = await renderHtml(rendered, request, {
66
162
  html: htmlManager,
67
163
  http,
68
- styles,
69
- scripts,
70
- preload
71
- });
72
- return requestRouter.html(server.renderHtmlToString(htmlElement), {
73
- headers,
74
- status: statusCode
164
+ assets: entryAssets,
165
+ preloadAssets
75
166
  });
167
+ return server$1.renderHtmlToString(htmlElement);
76
168
  }
77
- function defaultRenderHtml(content, request, {
169
+ const defaultRenderHtml = function defaultRenderHtml(content, request, {
78
170
  html,
79
- styles,
80
- scripts,
81
- preload
171
+ assets,
172
+ preloadAssets
82
173
  }) {
83
- return /*#__PURE__*/jsxRuntime.jsx(server.Html, {
84
- url: new URL(request.url),
174
+ const baseUrl = new URL(request.url);
175
+ return /*#__PURE__*/jsxRuntime.jsx(server$1.Html, {
85
176
  manager: html,
86
- styles: styles,
87
- scripts: scripts,
88
- preloadAssets: preload,
177
+ headEndContent: /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
178
+ children: [assets && [...assets.styles].map(style => {
179
+ const attributes = server.styleAssetAttributes(style, {
180
+ baseUrl
181
+ });
182
+ return /*#__PURE__*/jsxRuntime.jsx("link", {
183
+ ...attributes
184
+ }, style.source);
185
+ }), assets && [...assets.scripts].map(script => {
186
+ const isModule = script.attributes.type === 'module';
187
+ const attributes = server.scriptAssetAttributes(script, {
188
+ baseUrl
189
+ });
190
+ if (isModule) {
191
+ return /*#__PURE__*/jsxRuntime.jsxs(react.Fragment, {
192
+ children: [/*#__PURE__*/jsxRuntime.jsx("link", {
193
+ ...server.scriptAssetPreloadAttributes(script)
194
+ }), /*#__PURE__*/jsxRuntime.jsx("script", {
195
+ ...attributes,
196
+ async: true
197
+ })]
198
+ }, script.source);
199
+ }
200
+ return /*#__PURE__*/jsxRuntime.jsx("script", {
201
+ ...attributes,
202
+ defer: true
203
+ }, script.source);
204
+ }), preloadAssets && [...preloadAssets.styles].map(style => {
205
+ const attributes = server.styleAssetPreloadAttributes(style, {
206
+ baseUrl
207
+ });
208
+ return /*#__PURE__*/jsxRuntime.jsx("link", {
209
+ ...attributes
210
+ }, style.source);
211
+ }), preloadAssets && [...preloadAssets.scripts].map(script => {
212
+ const attributes = server.scriptAssetPreloadAttributes(script, {
213
+ baseUrl
214
+ });
215
+ return /*#__PURE__*/jsxRuntime.jsx("link", {
216
+ ...attributes
217
+ }, script.source);
218
+ })]
219
+ }),
89
220
  children: content
90
221
  });
222
+ };
223
+ function preloadHeader(attributes) {
224
+ const {
225
+ as,
226
+ rel = 'preload',
227
+ href,
228
+ crossOrigin,
229
+ crossorigin
230
+ } = attributes;
231
+
232
+ // Support both property and attribute versions of the casing
233
+ const finalCrossOrigin = crossOrigin ?? crossorigin;
234
+ let header = `<${href}>; rel="${rel}"; as="${as}"`;
235
+ if (finalCrossOrigin === '' || finalCrossOrigin === true) {
236
+ header += `; crossorigin`;
237
+ } else if (typeof finalCrossOrigin === 'string') {
238
+ header += `; crossorigin="${finalCrossOrigin}"`;
239
+ }
240
+ return header;
91
241
  }
92
242
 
93
243
  exports.createServerRender = createServerRender;
94
244
  exports.renderAppToResponse = renderAppToResponse;
245
+ exports.renderAppToStreamedResponse = renderAppToStreamedResponse;
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ var server$1 = require('@quilted/async/server');
3
4
  var server = require('@quilted/react-html/server');
4
5
  var _static = require('@quilted/react-router/static');
5
6
  var render = require('./render.cjs');
@@ -175,30 +176,20 @@ async function renderStatic(App, {
175
176
  const usedAssets = asyncAssets.used({
176
177
  timing: 'load'
177
178
  });
178
- const [moduleStyles, moduleScripts, modulePreload, nomoduleStyles, nomoduleScripts] = await Promise.all([assets.styles({
179
+ const [moduleAssets, modulePreload, nomoduleAssets] = await Promise.all([assets.assets({
179
180
  async: usedAssets,
180
- options: {
181
- modules: true
182
- }
183
- }), assets.scripts({
184
- async: usedAssets,
185
- options: {
181
+ context: {
186
182
  modules: true
187
183
  }
188
184
  }), assets.asyncAssets(asyncAssets.used({
189
185
  timing: 'preload'
190
186
  }), {
191
- options: {
187
+ context: {
192
188
  modules: true
193
189
  }
194
- }), assets.styles({
195
- async: usedAssets,
196
- options: {
197
- modules: false
198
- }
199
- }), assets.scripts({
190
+ }), assets.assets({
200
191
  async: usedAssets,
201
- options: {
192
+ context: {
202
193
  modules: false
203
194
  }
204
195
  })]);
@@ -206,22 +197,49 @@ async function renderStatic(App, {
206
197
  // We don’t want to load styles from both bundles, so we only use module styles,
207
198
  // since modules are intended to be the default and CSS (usually) doesn’t
208
199
  // have features that meaningfully break older user agents.
209
- const styles = moduleStyles.length > 0 ? moduleStyles : nomoduleStyles;
210
-
211
- // If there are nomodule scripts, we can’t really do preloading, because we can’t
212
- // prevent the nomodule scripts from being preloaded in module browsers. If there
213
- // are only module scripts, we can preload those.
214
- const preload = nomoduleScripts.length > 0 ? [] : modulePreload;
215
- const scripts = [...moduleScripts, ...nomoduleScripts.map(script => ({
216
- ...script,
217
- nomodule: true
218
- }))];
200
+ const styles = moduleAssets.styles.length > 0 ? moduleAssets.styles : nomoduleAssets.styles;
219
201
  const minifiedHtml = server.renderHtmlToString( /*#__PURE__*/jsxRuntime.jsx(server.Html, {
220
- url: url,
221
202
  manager: htmlManager,
222
- styles: styles,
223
- scripts: scripts,
224
- preloadAssets: preload,
203
+ headEndContent: /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
204
+ children: [[...styles].map(style => {
205
+ const attributes = server$1.styleAssetAttributes(style, {
206
+ baseUrl: url
207
+ });
208
+ return /*#__PURE__*/jsxRuntime.jsx("link", {
209
+ ...attributes
210
+ }, style.source);
211
+ }), [...moduleAssets.scripts].map(script => {
212
+ const attributes = server$1.scriptAssetAttributes(script, {
213
+ baseUrl: url
214
+ });
215
+ return /*#__PURE__*/jsxRuntime.jsx("script", {
216
+ ...attributes
217
+ }, script.source);
218
+ }), [...nomoduleAssets.scripts].map(script => {
219
+ const attributes = server$1.scriptAssetAttributes(script, {
220
+ baseUrl: url
221
+ });
222
+ return /*#__PURE__*/jsxRuntime.jsx("script", {
223
+ ...attributes,
224
+ // @ts-expect-error Rendering to HTML, so using the lowercase name
225
+ nomodule: moduleAssets.scripts.length > 0 ? true : undefined
226
+ }, script.source);
227
+ }), [...modulePreload.styles].map(style => {
228
+ const attributes = server$1.styleAssetPreloadAttributes(style, {
229
+ baseUrl: url
230
+ });
231
+ return /*#__PURE__*/jsxRuntime.jsx("link", {
232
+ ...attributes
233
+ }, style.source);
234
+ }), [...modulePreload.scripts].map(script => {
235
+ const attributes = server$1.scriptAssetPreloadAttributes(script, {
236
+ baseUrl: url
237
+ });
238
+ return /*#__PURE__*/jsxRuntime.jsx("link", {
239
+ ...attributes
240
+ }, script.source);
241
+ })]
242
+ }),
225
243
  children: markup
226
244
  }));
227
245
  const html = prettify ? await prettifyHtml(minifiedHtml) : minifiedHtml;
@@ -1,10 +1,9 @@
1
1
  export { SERVER_ACTION_ID as HTML_SERVER_ACTION_ID, Html, HtmlContext, HtmlManager, Serialize, renderHtmlToString } from '@quilted/react-html/server';
2
2
  export { ServerAction, ServerRenderManager, ServerRenderManagerContext, extract, useServerAction } from '@quilted/react-server-render/server';
3
- export { createAssetManifest } from '@quilted/async/server';
3
+ export { createAssetManifest, scriptAssetAttributes, scriptAssetPreloadAttributes, styleAssetAttributes, styleAssetPreloadAttributes } from '@quilted/async/server';
4
4
  export { SERVER_ACTION_ID as ASYNC_ASSETS_SERVER_ACTION_ID, AsyncAssetContext, AsyncAssetManager } from '@quilted/react-async/server';
5
5
  export { createRequestRouterLocalization } from '@quilted/react-localize/request-router';
6
6
  export { EnhancedRequest, EnhancedResponse, Request, Response, createHeaders, createRequestRouter } from '@quilted/request-router';
7
7
  export { parseAcceptLanguageHeader } from '@quilted/react-localize';
8
- export { renderApp } from './render.mjs';
9
8
  export { ServerContext } from './ServerContext.mjs';
10
- export { createServerRender, renderAppToResponse } from './request-router.mjs';
9
+ export { createServerRender, renderAppToResponse, renderAppToStreamedResponse } from './request-router.mjs';