Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | 1x 1x 1x 1x | import { pathToFileURL } from 'node:url';
import { createLoaderImport } from '@esmx/import';
import type { COMMAND, Esmx } from './core';
import {
RenderContext,
type RenderContextOptions,
type ServerRenderHandle
} from './render-context';
import { createMiddleware, type Middleware } from './utils/middleware';
/**
* Application instance interface.
*
* App is the application abstraction of the Esmx framework, providing a unified interface
* to manage application lifecycle, static assets, and server-side rendering.
*
* @example
* ```ts
* // entry.node.ts
* export default {
* // Development environment configuration
* async devApp(esmx) {
* return import('@esmx/rspack').then((m) =>
* m.createRspackHtmlApp(esmx, {
* config(rc) {
* // Custom Rspack configuration
* }
* })
* );
* }
* }
* ```
*/
export interface App {
/**
* Static asset processing middleware.
*
* Development environment:
* - Handles static asset requests from source code
* - Supports real-time compilation and hot reloading
* - Uses no-cache strategy
*
* Production environment:
* - Handles built static assets
* - Supports long-term caching for immutable files (.final.xxx)
* - Optimized asset loading strategy
*
* @example
* ```ts
* server.use(esmx.middleware);
* ```
*/
middleware: Middleware;
/**
* Server-side rendering function.
*
* Provides different implementations based on the runtime environment:
* - Production environment (start): Loads the built server entry file (entry.server) to execute rendering
* - Development environment (dev): Loads the server entry file from source code to execute rendering
*
* @param options - Rendering options
* @returns Returns the rendering context containing the rendering result
*
* @example
* ```ts
* const rc = await esmx.render({
* params: { url: '/page' }
* });
* res.end(rc.html);
* ```
*/
render: (options?: RenderContextOptions) => Promise<RenderContext>;
/**
* Production environment build function.
* Used for asset packaging and optimization.
*
* @returns Returns true for successful build, false for failed build
*/
build?: () => Promise<boolean>;
/**
* Resource cleanup function.
* Used for shutting down servers, disconnecting connections, etc.
*
* @returns Returns true for successful cleanup, false for failed cleanup
*/
destroy?: () => Promise<boolean>;
}
/**
* Create an application instance for production environment, not available in development environment.
*/
export async function createApp(esmx: Esmx, command: COMMAND): Promise<App> {
const render =
command === esmx.COMMAND.start
? await createStartRender(esmx) // Provides actual rendering function
: createErrorRender(esmx); // Provides error prompt rendering function
return {
middleware: createMiddleware(esmx),
render
};
}
/**
* Create production environment rendering function.
* Loads the built server entry file (entry.server) to execute rendering.
*
* @param esmx - Esmx instance
* @returns Returns the rendering function
* @internal
*
* @example
* ```ts
* // Server entry file (entry.server)
* export default async function render(rc: RenderContext) {
* rc.html = '<html>...</html>';
* }
* ```
*/
async function createStartRender(esmx: Esmx) {
const baseURL = pathToFileURL(esmx.resolvePath('dist/server')) as URL;
const importMap = await esmx.getImportMap('server');
const loaderImport = createLoaderImport(baseURL, importMap);
return async (options?: RenderContextOptions): Promise<RenderContext> => {
const rc = new RenderContext(esmx, options);
const result = await loaderImport(`${esmx.name}/src/entry.server`);
const serverRender: ServerRenderHandle = result[rc.entryName];
if (typeof serverRender === 'function') {
await serverRender(rc);
}
return rc;
};
}
function createErrorRender(esmx: Esmx) {
return (options?: RenderContextOptions) => {
throw new Error(
`App instance is only available in production and can only execute built artifacts.`
);
};
}
|