html-render-webpack-plugin 0.0.0-feat-dx-followups-20261021095350

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/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2018 Jahred Hope
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,464 @@
1
+ # html-render-webpack-plugin
2
+
3
+ [![npm](https://img.shields.io/npm/v/html-render-webpack-plugin.svg)](https://www.npmjs.com/package/html-render-webpack-plugin)
4
+
5
+ Render HTML files with JavaScript during a webpack build.
6
+
7
+ - Supports [multiple configurations](https://webpack.js.org/configuration/configuration-types/#exporting-multiple-configurations)
8
+ - Supports [code-splitting](https://webpack.js.org/guides/code-splitting/) and [dynamic imports](https://webpack.js.org/guides/code-splitting/#dynamic-imports)
9
+ - Renders every route to a static file, or on demand through an Express dev router
10
+ - Passes client build stats into the renderer so hashed asset names are correct
11
+
12
+ ## Requirements
13
+
14
+ - Node >= 22.13
15
+ - webpack ^5.0.0
16
+ - Express >= 4, only if you use `createDevRouter`
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ pnpm add webpack html-render-webpack-plugin
22
+ # Only needed for the development server:
23
+ pnpm add express
24
+ ```
25
+
26
+ Express is an optional peer dependency. Build-only usage does not require it.
27
+ The published type declarations include the Express request and router types, so
28
+ TypeScript users do not need to install `@types/express` separately.
29
+
30
+ ## Quick start
31
+
32
+ A single webpack compilation can render HTML when it targets Node and exports a
33
+ function. This is the smallest useful setup.
34
+
35
+ **src/render.js**
36
+
37
+ ```js
38
+ export default function render({ route }) {
39
+ return `<!doctype html>
40
+ <html lang="en">
41
+ <body>
42
+ <h1>Rendered ${route}</h1>
43
+ </body>
44
+ </html>`;
45
+ }
46
+ ```
47
+
48
+ **webpack.config.js**
49
+
50
+ ```js
51
+ import path from "node:path";
52
+
53
+ import { HtmlRenderPlugin } from "html-render-webpack-plugin";
54
+
55
+ const htmlRenderPlugin = new HtmlRenderPlugin({
56
+ routes: ["/"],
57
+ renderDirectory: path.resolve("dist"),
58
+ });
59
+
60
+ export default {
61
+ name: "render",
62
+ target: "node",
63
+ mode: "production",
64
+ entry: path.resolve("src/render.js"),
65
+ output: {
66
+ // Keep the Node renderer out of the folder you deploy.
67
+ path: path.resolve(".render"),
68
+ filename: "render.js",
69
+ // The plugin evaluates the default export, so expose it as a UMD2 module.
70
+ library: { type: "umd2", export: "default" },
71
+ },
72
+ plugins: [htmlRenderPlugin.rendererPlugin],
73
+ };
74
+ ```
75
+
76
+ The build writes `dist/index.html`. The renderer bundle is written to
77
+ `.render/` and is not part of the static site.
78
+
79
+ CommonJS configs can use:
80
+
81
+ ```js
82
+ const { HtmlRenderPlugin } = require("html-render-webpack-plugin");
83
+ ```
84
+
85
+ ## Multiple configurations
86
+
87
+ Use two compilations when the renderer needs information from a browser build,
88
+ such as a hashed script filename.
89
+
90
+ Add `htmlRenderPlugin.statsCollectorPlugin` to every compilation whose stats the
91
+ renderer needs. Add `htmlRenderPlugin.rendererPlugin` to the compilation that
92
+ renders HTML.
93
+
94
+ **webpack.config.js**
95
+
96
+ ```js
97
+ import path from "node:path";
98
+
99
+ import {
100
+ HtmlRenderPlugin,
101
+ getEntrypointScriptUrls,
102
+ } from "html-render-webpack-plugin";
103
+
104
+ const htmlRenderPlugin = new HtmlRenderPlugin({
105
+ routes: ["/", "/about"],
106
+ renderDirectory: path.resolve("dist"),
107
+ // Keep the renderer boundary small: pass URLs, not the whole stats object.
108
+ mapStatsToParams: ({ webpackStats }) => ({
109
+ scripts: getEntrypointScriptUrls(webpackStats),
110
+ }),
111
+ });
112
+
113
+ export default [
114
+ {
115
+ name: "client",
116
+ target: "web",
117
+ mode: "production",
118
+ entry: path.resolve("src/client.js"),
119
+ output: {
120
+ path: path.resolve("dist"),
121
+ filename: "assets/[name].[contenthash].js",
122
+ chunkFilename: "assets/[name].[contenthash].js",
123
+ publicPath: "/",
124
+ },
125
+ plugins: [htmlRenderPlugin.statsCollectorPlugin],
126
+ },
127
+ {
128
+ name: "render",
129
+ target: "node",
130
+ mode: "production",
131
+ // Optional: the plugin already waits for every compilation. Declaring the
132
+ // dependency makes the intended build order explicit.
133
+ dependencies: ["client"],
134
+ entry: path.resolve("src/render.js"),
135
+ output: {
136
+ path: path.resolve(".render"),
137
+ filename: "[name].js",
138
+ library: { type: "umd2", export: "default" },
139
+ },
140
+ plugins: [htmlRenderPlugin.rendererPlugin],
141
+ },
142
+ ];
143
+ ```
144
+
145
+ **src/render.js**
146
+
147
+ ```js
148
+ export default function render({ route, scripts }) {
149
+ return `<!doctype html>
150
+ <html lang="en">
151
+ <body>
152
+ <div id="app">Rendered ${route}</div>
153
+ ${scripts
154
+ .map((src) => `<script src="${src}" defer></script>`)
155
+ .join("\n ")}
156
+ </body>
157
+ </html>`;
158
+ }
159
+ ```
160
+
161
+ `getEntrypointScriptUrls(webpackStats, entrypoint = "main")` returns public URLs
162
+ for the JavaScript assets of an entrypoint. It handles hashed filenames,
163
+ `publicPath` values with or without a trailing slash, string assets and asset
164
+ objects. It accepts the stats of a single client compilation and the multi
165
+ compilation stats produced when several compilations use
166
+ `statsCollectorPlugin`. An unknown entrypoint name throws instead of returning an
167
+ empty list.
168
+
169
+ If you need more control, `mapStatsToParams` receives the route and the client
170
+ stats, and whatever it returns is merged into the renderer's parameters.
171
+
172
+ ## Routes
173
+
174
+ `routes` accepts strings or objects. A `route` may start with or without a
175
+ leading slash. Paths are appended with `index.html` unless they already end in
176
+ `.html`.
177
+
178
+ ```js
179
+ const routes = [
180
+ "/", // dist/index.html
181
+ "/about", // dist/about/index.html
182
+ "contact", // dist/contact/index.html
183
+ { route: "/blog/hello", title: "Hello", category: "news" },
184
+ ];
185
+ ```
186
+
187
+ Extra keys on a route object are passed to the renderer, which makes routes a
188
+ convenient place for page metadata:
189
+
190
+ ```js
191
+ new HtmlRenderPlugin({
192
+ routes: [
193
+ { route: "/", title: "Home", description: "Welcome" },
194
+ { route: "/about", title: "About", description: "How it works" },
195
+ ],
196
+ // mapStatsToParams also receives the route:
197
+ mapStatsToParams: ({ title, webpackStats }) => ({
198
+ title,
199
+ scripts: getEntrypointScriptUrls(webpackStats),
200
+ }),
201
+ });
202
+ ```
203
+
204
+ The renderer receives `{ route, title, scripts, webpackStats, ... }` depending on
205
+ what `mapStatsToParams` returns.
206
+
207
+ ## Options
208
+
209
+ ### `routes`
210
+
211
+ **Default:** `[""]`
212
+
213
+ Routes to render. A file is created for each route. `""` and `"/"` both render
214
+ to `index.html`.
215
+
216
+ ### `renderEntry`
217
+
218
+ **Default:** `"main"`
219
+
220
+ The webpack entry in the renderer compilation. Set this when the renderer uses
221
+ [object entry syntax](https://webpack.js.org/concepts/entry-points/#object-syntax).
222
+
223
+ ```js
224
+ new HtmlRenderPlugin({ renderEntry: "myRender" });
225
+ ```
226
+
227
+ ### `renderDirectory`
228
+
229
+ **Default:** `"dist"`
230
+
231
+ The directory to write HTML files to, resolved from the current working
232
+ directory. This can differ from the renderer compilation's `output.path`; that
233
+ is the recommended setup, so the Node renderer bundle is not deployed with the
234
+ static site.
235
+
236
+ ### `mapStatsToParams`
237
+
238
+ **Default:** `({ webpackStats }) => ({ webpackStats: webpackStats.toJson() })`
239
+
240
+ Builds the values passed to the render function for each route. The function
241
+ receives the route fields plus `webpackStats`, and its return value is merged
242
+ into the render parameters.
243
+
244
+ Prefer passing only what the renderer needs:
245
+
246
+ ```js
247
+ mapStatsToParams: ({ webpackStats }) => ({
248
+ scripts: getEntrypointScriptUrls(webpackStats),
249
+ });
250
+ ```
251
+
252
+ In a single-compilation setup the renderer's own stats are used. If you do not
253
+ need stats at all, return an empty object:
254
+
255
+ ```js
256
+ mapStatsToParams: () => ({});
257
+ ```
258
+
259
+ ### `transformFilePath`
260
+
261
+ **Default:** `(route) => route.route`
262
+
263
+ Changes the output path for a route.
264
+
265
+ ```js
266
+ new HtmlRenderPlugin({
267
+ routes: [
268
+ { route: "/about", language: "en-us" },
269
+ { route: "/about", language: "en-au" },
270
+ ],
271
+ transformFilePath: ({ route, language }) => `${language}${route}`,
272
+ });
273
+ ```
274
+
275
+ This writes `en-us/about/index.html` and `en-au/about/index.html`.
276
+
277
+ ### `renderConcurrency`
278
+
279
+ **Default:** `"serial"`
280
+
281
+ Use `"parallel"` when renders do a lot of asynchronous work.
282
+
283
+ ```js
284
+ new HtmlRenderPlugin({ renderConcurrency: "parallel" });
285
+ ```
286
+
287
+ ### `skipAssets`
288
+
289
+ **Default:** `false`
290
+
291
+ When `true`, routes are not rendered to files after the build. Use this in watch
292
+ mode with `createDevRouter` or `renderWhenReady`, where pages are rendered on
293
+ demand.
294
+
295
+ ### `transformExpressPath`
296
+
297
+ **Default:** `(route) => route.route`
298
+
299
+ Changes the path used by the dev router. Routes are normalized to a leading
300
+ slash, so `"about"` and `"/about"` both work. The default `""` route is served
301
+ at `/`. Return `undefined` to exclude a route from the dev router; an empty
302
+ string excludes every route except the default one.
303
+
304
+ ```js
305
+ new HtmlRenderPlugin({
306
+ transformExpressPath: (route) =>
307
+ route.route === "/draft" ? undefined : `/static${route.route}`,
308
+ });
309
+ ```
310
+
311
+ ### `getRouteFromRequest`
312
+
313
+ Used by the dev router to choose a route for a request. It must return one of the
314
+ configured routes, or `undefined` to pass the request to the next middleware.
315
+
316
+ ```js
317
+ new HtmlRenderPlugin({
318
+ routes: [
319
+ { route: "/books/1", id: "1" },
320
+ { route: "/books/2", id: "2" },
321
+ ],
322
+ getRouteFromRequest: (req, routes) =>
323
+ routes.find((route) => route.id === req.params.id),
324
+ });
325
+ ```
326
+
327
+ ### `extraGlobals`
328
+
329
+ Extra values to expose as free variables in the evaluated renderer bundle. Names
330
+ must be valid JavaScript identifiers and cannot be `exports`, `require`,
331
+ `module`, `__filename` or `__dirname`.
332
+
333
+ ## Development server
334
+
335
+ The dev router renders configured routes on demand with the same renderer bundle
336
+ used by the production build. Use it with Express and
337
+ [`webpack-dev-middleware`](https://github.com/webpack/webpack-dev-middleware) so
338
+ client assets are served from memory.
339
+
340
+ Set `skipAssets: true` on the plugin when using the dev router. Share the same
341
+ plugin instance between the webpack configuration and the server.
342
+
343
+ **webpack.config.js**
344
+
345
+ ```js
346
+ export const htmlRenderPlugin = new HtmlRenderPlugin({
347
+ routes: ["/", "/about"],
348
+ skipAssets: true,
349
+ });
350
+ ```
351
+
352
+ **dev-server.js**
353
+
354
+ ```js
355
+ import express from "express";
356
+ import webpack from "webpack";
357
+ import devMiddleware from "webpack-dev-middleware";
358
+
359
+ import config, { htmlRenderPlugin } from "./webpack.config.js";
360
+
361
+ const compiler = webpack(config);
362
+ const app = express();
363
+
364
+ // Mount the renderer first, then serve client assets from webpack.
365
+ app.use(htmlRenderPlugin.createDevRouter());
366
+ app.use(devMiddleware(compiler, { publicPath: "/" }));
367
+
368
+ app.listen(3000, () => {
369
+ console.log("http://localhost:3000");
370
+ });
371
+ ```
372
+
373
+ If you use webpack-dev-server v5 instead, mount the router in
374
+ `setupMiddlewares`:
375
+
376
+ ```js
377
+ devServer: {
378
+ setupMiddlewares(middlewares, devServer) {
379
+ devServer.app.use(htmlRenderPlugin.createDevRouter());
380
+ return middlewares;
381
+ },
382
+ }
383
+ ```
384
+
385
+ The dev router does not add hot module replacement. It rerenders a route when it
386
+ is requested after a rebuild.
387
+
388
+ ## Just-in-time rendering
389
+
390
+ `renderWhenReady` renders any route using the same renderer. It waits until the
391
+ build is ready, so it is safe to call during startup.
392
+
393
+ ```js
394
+ app.get("/books/:id", (req, res) => {
395
+ res.send(await htmlRenderPlugin.renderWhenReady({ route: "/books/_id" }));
396
+ });
397
+ ```
398
+
399
+ Only use routes that also exist in the production build. Errors contain a
400
+ `webpackStats` property when stats are available.
401
+
402
+ ## Output layout
403
+
404
+ A typical multi-compilation project looks like this:
405
+
406
+ ```text
407
+ dist/ # deploy this
408
+ index.html
409
+ about/index.html
410
+ assets/main.<hash>.js
411
+ assets/<chunk>.<hash>.js
412
+ .render/ # renderer bundle, do not deploy
413
+ render.js
414
+ ```
415
+
416
+ Keep the renderer output outside `renderDirectory`. Avoid `output.clean` across
417
+ compilations that share an output directory; clean the directories yourself
418
+ before the build instead.
419
+
420
+ ## TypeScript
421
+
422
+ The package ships declarations and exports the public option and route types:
423
+
424
+ ```ts
425
+ import {
426
+ HtmlRenderPlugin,
427
+ getEntrypointScriptUrls,
428
+ type BaseRoute,
429
+ type MapStatsToParams,
430
+ type Options,
431
+ } from "html-render-webpack-plugin";
432
+
433
+ interface Route extends BaseRoute {
434
+ title: string;
435
+ }
436
+
437
+ const mapStatsToParams: MapStatsToParams<Route> = ({
438
+ route,
439
+ title,
440
+ webpackStats,
441
+ }) => ({
442
+ route,
443
+ title,
444
+ scripts: getEntrypointScriptUrls(webpackStats),
445
+ });
446
+
447
+ const options: Options<Route> = {
448
+ routes: [{ route: "/", title: "Home" }],
449
+ mapStatsToParams,
450
+ };
451
+
452
+ const plugin = new HtmlRenderPlugin<Route>(options);
453
+ ```
454
+
455
+ ## Examples
456
+
457
+ The fixtures under [`tests/test-cases`](./tests/test-cases) are complete,
458
+ buildable examples, including single and multi-compilation setups, a dev server,
459
+ route metadata and asynchronous rendering.
460
+
461
+ ## Migration
462
+
463
+ Upgrading from v1? See the
464
+ [v1 to v2 migration guide](./MIGRATION_GUIDE_v1_to_v2.md).
@@ -0,0 +1,3 @@
1
+ export default class RenderError extends Error {
2
+ constructor(error: Error);
3
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class RenderError extends Error {
4
+ constructor(error) {
5
+ super(`html-render-webpack-plugin: An error occurred during render: \n${error}`);
6
+ this.name = "RenderError";
7
+ Error.captureStackTrace(this, this.constructor);
8
+ }
9
+ }
10
+ exports.default = RenderError;
11
+ //# sourceMappingURL=RenderError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RenderError.js","sourceRoot":"","sources":["../src/RenderError.ts"],"names":[],"mappings":";;AAAA,MAAqB,WAAY,SAAQ,KAAK;IAC5C,YAAY,KAAY;QACtB,KAAK,CACH,kEAAkE,KAAK,EAAE,CAC1E,CAAC;QAEF,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAE1B,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAClD,CAAC;CACF;AAVD,8BAUC"}
@@ -0,0 +1,46 @@
1
+ import type { WebpackStats } from "./common-types";
2
+ interface StatsAssetLike {
3
+ name?: string;
4
+ }
5
+ export interface WebpackStatsJson {
6
+ entrypoints?: Record<string, {
7
+ assets?: Array<string | StatsAssetLike>;
8
+ } | undefined>;
9
+ publicPath?: string;
10
+ /** Present on the object returned by `MultiStats.toJson()`. */
11
+ children?: WebpackStatsJson[];
12
+ }
13
+ /**
14
+ * The parts of `webpack.MultiStats` this module uses. webpack does not export a
15
+ * public type for `MultiStats`.
16
+ */
17
+ export interface MultiStatsLike {
18
+ toJson(options?: unknown): WebpackStatsJson | WebpackStatsJson[];
19
+ }
20
+ type StatsJsonInput = WebpackStatsJson | WebpackStatsJson[];
21
+ /**
22
+ * Get the public URLs of the JavaScript assets for one entrypoint.
23
+ *
24
+ * Accepts a single stats JSON object or an array of them. The object returned
25
+ * by `MultiStats.toJson()` for builds with more than one client compilation is
26
+ * supported through its `children` array.
27
+ *
28
+ * Pass `undefined` as the entrypoint to collect scripts from every entrypoint,
29
+ * which is useful for an error page that does not know which client entry failed.
30
+ * An unknown entrypoint name throws rather than returning an empty list.
31
+ */
32
+ export declare function getScriptUrlsFromStats(stats: StatsJsonInput, entrypoint?: string): string[];
33
+ /**
34
+ * Get the public URLs of the JavaScript assets for an entrypoint.
35
+ *
36
+ * This is the common bridge from client stats to a renderer: the renderer can
37
+ * emit script tags without receiving the whole webpack stats object. It works
38
+ * for a single client compilation and for multiple client compilations.
39
+ *
40
+ * @example
41
+ * mapStatsToParams: ({ webpackStats }) => ({
42
+ * scripts: getEntrypointScriptUrls(webpackStats, "main"),
43
+ * })
44
+ */
45
+ export declare function getEntrypointScriptUrls(webpackStats: WebpackStats | MultiStatsLike, entrypoint?: string): string[];
46
+ export {};
package/dist/assets.js ADDED
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getScriptUrlsFromStats = getScriptUrlsFromStats;
4
+ exports.getEntrypointScriptUrls = getEntrypointScriptUrls;
5
+ function getStatsList(stats) {
6
+ if (Array.isArray(stats)) {
7
+ return stats;
8
+ }
9
+ if (stats.children && stats.children.length > 0) {
10
+ return stats.children;
11
+ }
12
+ return [stats];
13
+ }
14
+ function getAssetName(asset) {
15
+ return typeof asset === "string" ? asset : asset.name;
16
+ }
17
+ function getPublicPath(stats) {
18
+ return typeof stats.publicPath === "string" && stats.publicPath !== "auto"
19
+ ? stats.publicPath
20
+ : "/";
21
+ }
22
+ function joinPublicPath(publicPath, assetName) {
23
+ const base = publicPath === "" || publicPath.endsWith("/")
24
+ ? publicPath
25
+ : `${publicPath}/`;
26
+ return `${base}${assetName.replace(/^\/+/, "")}`;
27
+ }
28
+ function getAssetNames(stats, entrypoint) {
29
+ var _a;
30
+ const entrypoints = (_a = stats.entrypoints) !== null && _a !== void 0 ? _a : {};
31
+ const groups = entrypoint === undefined
32
+ ? Object.values(entrypoints)
33
+ : [entrypoints[entrypoint]];
34
+ return groups
35
+ .flatMap((group) => { var _a; return (_a = group === null || group === void 0 ? void 0 : group.assets) !== null && _a !== void 0 ? _a : []; })
36
+ .map(getAssetName)
37
+ .filter((name) => typeof name === "string" && name.endsWith(".js"));
38
+ }
39
+ function assertEntrypointExists(statsList, entrypoint) {
40
+ const available = new Set(statsList.flatMap((stats) => { var _a; return Object.keys((_a = stats.entrypoints) !== null && _a !== void 0 ? _a : {}); }));
41
+ if (!available.has(entrypoint)) {
42
+ const known = available.size > 0 ? [...available].join(", ") : "none";
43
+ throw new Error(`Unable to find entrypoint "${entrypoint}" in webpack stats. Available entrypoints: ${known}.`);
44
+ }
45
+ }
46
+ /**
47
+ * Get the public URLs of the JavaScript assets for one entrypoint.
48
+ *
49
+ * Accepts a single stats JSON object or an array of them. The object returned
50
+ * by `MultiStats.toJson()` for builds with more than one client compilation is
51
+ * supported through its `children` array.
52
+ *
53
+ * Pass `undefined` as the entrypoint to collect scripts from every entrypoint,
54
+ * which is useful for an error page that does not know which client entry failed.
55
+ * An unknown entrypoint name throws rather than returning an empty list.
56
+ */
57
+ function getScriptUrlsFromStats(stats, entrypoint) {
58
+ const statsList = getStatsList(stats);
59
+ if (entrypoint !== undefined) {
60
+ assertEntrypointExists(statsList, entrypoint);
61
+ }
62
+ const urls = statsList.flatMap((statsJson) => {
63
+ const publicPath = getPublicPath(statsJson);
64
+ return getAssetNames(statsJson, entrypoint).map((name) => joinPublicPath(publicPath, name));
65
+ });
66
+ return [...new Set(urls)];
67
+ }
68
+ /**
69
+ * Get the public URLs of the JavaScript assets for an entrypoint.
70
+ *
71
+ * This is the common bridge from client stats to a renderer: the renderer can
72
+ * emit script tags without receiving the whole webpack stats object. It works
73
+ * for a single client compilation and for multiple client compilations.
74
+ *
75
+ * @example
76
+ * mapStatsToParams: ({ webpackStats }) => ({
77
+ * scripts: getEntrypointScriptUrls(webpackStats, "main"),
78
+ * })
79
+ */
80
+ function getEntrypointScriptUrls(webpackStats, entrypoint = "main") {
81
+ const statsJson = webpackStats.toJson({
82
+ all: false,
83
+ entrypoints: true,
84
+ publicPath: true,
85
+ });
86
+ return getScriptUrlsFromStats(statsJson, entrypoint);
87
+ }
88
+ //# sourceMappingURL=assets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets.js","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type * as originalFs from "fs";
2
+ import type { Request } from "express";
3
+ import type { Stats } from "webpack";
4
+ export type WebpackStats = Stats;
5
+ export type BaseRoute = {
6
+ route: string;
7
+ };
8
+ export type Render<Route = BaseRoute> = (route: Route) => Promise<string>;
9
+ export type OnRendererReady<Route = BaseRoute> = (callback: (render: Render<Route>) => Promise<void>) => void;
10
+ export type Renderer = (...params: any[]) => Promise<string>;
11
+ export type SourceModules = Record<string, string>;
12
+ export type RouteInput<Route = BaseRoute> = Route | string;
13
+ export type Trace = (...values: any[]) => void;
14
+ export type Specifier = string;
15
+ export type ExtraGlobals = Record<string, unknown>;
16
+ export type RenderConcurrency = "parallel" | "serial";
17
+ export type MapStatsToParams<Route extends BaseRoute = BaseRoute> = (params: {
18
+ webpackStats: WebpackStats;
19
+ } & Route) => Record<string, unknown>;
20
+ export type TransformPath<Route = BaseRoute> = (route: Route) => string;
21
+ /**
22
+ * Build the Express path for a route. Paths are normalized to a leading slash.
23
+ * Return `undefined` to exclude a route from the dev router.
24
+ */
25
+ export type TransformExpressPath<Route = BaseRoute> = (route: Route) => string | undefined;
26
+ export type GetRouteFromRequest<Route> = (req: Request, routes: Route[]) => Route | undefined;
27
+ export type FileSystem = typeof originalFs;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=common-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common-types.js","sourceRoot":"","sources":["../src/common-types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ import type { Router } from "express";
2
+ import { OnRendererReady, BaseRoute, WebpackStats, TransformExpressPath, GetRouteFromRequest } from "./common-types";
3
+ interface Params<Route> {
4
+ routes: Route[];
5
+ getRouteFromRequest?: GetRouteFromRequest<Route>;
6
+ onRendererReady: OnRendererReady<Route>;
7
+ transformExpressPath: TransformExpressPath<Route>;
8
+ getClientStats: () => WebpackStats;
9
+ }
10
+ declare const _default: <Route extends BaseRoute>({ routes, getRouteFromRequest, onRendererReady, transformExpressPath, getClientStats, }: Params<Route>) => Router;
11
+ export = _default;