# Vite plugin tricks * [**`resolveConfig`**](https://github.com/brillout/vite-plugin-ssr/blob/v0.4.131/vite-plugin-ssr/node/plugin/plugins/config/index.ts): In `configResolved` with `enforce: 'pre'`, add a promise to resolve config object with the plugin's own config. This allows queueing some async operations AFTER resolving the config. In any later `configResolved` stage, use `await` on that async func. to get and memoize the "grand final" config object * [**buildConfig.ts**](https://github.com/brillout/vite-plugin-ssr/blob/v0.4.131/vite-plugin-ssr/node/plugin/plugins/buildConfig.ts): Normalize `rollupOptions.input` from `string | string []| { [entryName: string]: string }` to Object [**distFileNames.ts**](https://github.com/brillout/vite-plugin-ssr/blob/v0.4.131/vite-plugin-ssr/node/plugin/plugins/distFileNames.ts): Similar, but wrap single-element `output` to array ... for further tweaking; addition options can be attached with an Array.map * [**packageJsonFile.ts**](https://github.com/brillout/vite-plugin-ssr/blob/v0.4.131/vite-plugin-ssr/node/plugin/plugins/packageJsonFile.ts): Add a `package.json` to out dir so that ESM can be correctly detected * To discrimate between `build` and `dev`, let a variable `isDev = false` and set it to `true` in `configureServer` stage (only when a dev server is spinned up). It must be used in a later stage like `transform`. Seen in **extractExportNamesPlugin.ts**. > In `devConfig/index.ts` it is mentioned that ++"There doesn't seem to be a straightforward way to discriminate between `$ vite preview` and `$ vite dev`."++ The value of the `command` argument is "serve" in both cases. # HTML transformations > @ v4.4.7 **Hooks**: Default hooks are (where ... are collected through plugins in the resolved config): 1. Pre: `preImportMapHook` -> ... -> `htmlEnvHook` 2. Post: ... -> `postImportMapHook` Hooks can be specified with `order` property being one of {pre/normal/post} to workaround that `enforce` property does not support the value "normal". Import maps are `<script type="importmap">`. HTML env is replacement of `%VITE_PREFIXED_ENV%`. **[[html-proxy]]**: a reflection for adding/extracting some strings associated with the document, URL (matched against a regex!) being one form of * #0 `foo.html?html-proxy&index=<index>.js` * #1 `foo.html?html-proxy&inline-css&style-attr&index=<index>.css` * #2 `foo.html?html-proxy&inline-css&index=<index>.css` At the function `buildHtmlPlugin`, the working is tentatively described as following sections: ### To transform HTML * Pre-transform: apply pre hooks * Traverse over HTML AST generated through `parse5`, handling the cases: * **A script tag**: * public file: prefix public path, leave it as-is * module: add the JS to entry point as an import statement if external, extract the src if inline, reference through [[html-proxy]] form #0 --> merge all modules to an equivalent single entry * (not module && external && not public file): bail out (Vite only accepts ES modules) * (not module && inline): collect inline import URLs through regex (*), stored as `scriptUrls` > regex? seriously? * A tag that **has attrs that are meant to be URLs** (img src, link href, ...): These are the *only* "assets", besides JS, the HTML directly depends on. Others are indirectly through CSS. * For CSS, specifically `<link rel="stylesheet" src="...">`: Rewrite (eagerly) to JS import, stored in `styleUrls`. > Ineffective link tags are ignored (with attr `media` or `disabled`). > Original tag is not deleted. Which way to load it is determined later in (**-1). * For others, store them as `assetUrls` and rewrite that URL to public path *later* (**-2). * A tag **with "style" attr and inline style contains URL**: `url()` and `image-set()`: virtualize through [[html-proxy]] form #1, and add back a class. > Q: changes (demotes) specificity? * A **non-empty `<style>` tag**: Apply [[html-proxy]] form #2. * Rewrite assets in (**-2) to built URLs if it is not empty and NOT referencing named output passed to rollup. > This is complicated to explain here. See code! * Rewrite script URLs (*) to built URLs or public path. * Try to resolve stylesheet URLs in (**-1). success: Remove corresponding `<link>` failure: Undo; Remove the import statement already inserted. * Prepend module preload polyfill if the `build.modulePreload.polyfill` is set and there are async/deferred script tags. ### To generate a bundle: * Get base of HTML. * "inject chunk asset links". (***) An ES module can be inlined if it contains solely imports * "inject css link when cssCodeSplit is false". * Transform CSS stored through [[html-proxy]] of form #2. * Apply normal and post hooks. * "Resolve asset[/public] url references". * Emit the HTML * Remove all modules collected in (***) from bundle. ## Vite undocumented config: `ssrEmitAssets: true` https://github.com/vitejs/vite/blob/v4.3.9/packages/vite/src/node/build.ts#L228