UNPKG

vite-plugin-generate-html

Version:

A Vite plugin to generate separate output files for JavaScript and CSS bundles with customizable attributes.

242 lines (179 loc) 5.94 kB
# Vite Plugin Generate HTML A Vite plugin that writes generated `<script>` and `<link>` tags to separate files during the build. The plugin reads Vite/Rollup output entry chunks, uses their final hashed asset filenames, and writes: - one file containing `<script>` tags for JavaScript entry chunks - one file containing `<link>` tags for CSS imported by those entry chunks This is useful when your application shell is rendered outside Vite, for example in `.html`, `.cshtml` (Razor), `.php`, or another server-rendered template, but you still need references to Vite's hashed build assets. It is inspired by Webpack's `HtmlWebpackPlugin` and is intended for similar use cases in Vite projects where generated asset tags need to be written into external template files. --- ## Installation ```bash npm install --save-dev vite-plugin-generate-html ``` ## Requirements - Node.js 18 or newer - npm 8 or newer --- ## Usage ```ts // vite.config.ts import { resolve } from "node:path"; import { defineConfig } from "vite"; import generateHtmlFiles from "vite-plugin-generate-html"; export default defineConfig({ build: { rollupOptions: { input: { app: resolve(__dirname, "src/main.ts"), }, }, }, plugins: [ generateHtmlFiles({ publicDir: "/dist/", jsEntryFile: resolve(__dirname, "../templates/javascript.html"), cssEntryFile: resolve(__dirname, "../templates/css.html"), }), ], }); ``` If `src/main.ts` imports CSS: ```ts import "./styles.css"; ``` the generated files can look like this after a Vite build. `javascript.html`: ```html <script type="module" src="/dist/app.abc123.js"></script> ``` `css.html`: ```html <link href="/dist/app.abc123.css" rel="stylesheet" media="all" /> ``` The plugin overwrites both configured output files on each build. --- ## Options ```ts interface VitePluginGenerateHtmlOptions { /** * URL prefix added before generated JavaScript and CSS filenames. * * @default "/dist/" */ publicDir?: string; /** * File path where generated `<script>` tags are written. */ jsEntryFile: string; /** * File path where generated `<link>` tags are written. */ cssEntryFile: string; /** * Custom attributes for generated tags by entry chunk name. */ output?: Array< Record< string, { attrs: string[]; linkAttrs: string[]; } > >; /** * Limit generation to specific entry chunk names. * By default, all entry chunks are handled. */ chunks?: string[]; } ``` ### `publicDir` `publicDir` is used as a URL prefix for generated asset references. It is not read from disk. For example, with `publicDir: "/assets/"` and an output chunk named `app.abc123.js`, the generated script tag uses: ```html <script type="module" src="/assets/app.abc123.js"></script> ``` ### `jsEntryFile` Required. The file path where generated `<script>` tags are written. ### `cssEntryFile` Required. The file path where generated `<link>` tags are written. Only CSS imported by handled Vite entry chunks is included. If a handled entry chunk has no imported CSS, no link tag is generated for that chunk. ### `output` Use `output` to customize attributes for specific entry chunk names. ```ts generateHtmlFiles({ publicDir: "/dist/", jsEntryFile: resolve(__dirname, "../templates/javascript.html"), cssEntryFile: resolve(__dirname, "../templates/css.html"), output: [ { app: { attrs: ['type="module"', "defer", 'data-entry="app"'], linkAttrs: ['rel="stylesheet"', 'media="all"'], }, }, ], }); ``` Generated output: ```html <script type="module" defer data-entry="app" src="/dist/app.abc123.js"></script> ``` ```html <link href="/dist/app.abc123.css" rel="stylesheet" media="all" /> ``` When `output` is provided, each handled entry chunk must have a matching key for script generation. If you only want to configure some entries, combine `output` with `chunks`. Default attributes are used when `output` is omitted: - `<script>`: `type="module"` - `<link>`: `rel="stylesheet" media="all"` ### `chunks` Use `chunks` to generate files for only specific entry chunk names. ```ts generateHtmlFiles({ publicDir: "/dist/", jsEntryFile: resolve(__dirname, "../templates/admin-javascript.html"), cssEntryFile: resolve(__dirname, "../templates/admin-css.html"), chunks: ["admin"], }); ``` This is helpful when a Vite build has multiple entry points and you want separate generated files for different pages or templates. --- ## Multiple Entry Points You can use the plugin more than once to write separate files for different entry chunks. ```ts plugins: [ generateHtmlFiles({ publicDir: "/dist/", jsEntryFile: resolve(__dirname, "../templates/app-js.html"), cssEntryFile: resolve(__dirname, "../templates/app-css.html"), chunks: ["app"], }), generateHtmlFiles({ publicDir: "/dist/", jsEntryFile: resolve(__dirname, "../templates/admin-js.html"), cssEntryFile: resolve(__dirname, "../templates/admin-css.html"), chunks: ["admin"], output: [ { admin: { attrs: ['type="module"', 'data-entry="admin"'], linkAttrs: ['rel="stylesheet"', 'media="all"'], }, }, ], }), ]; ``` --- ## Errors The plugin throws an error when: - `jsEntryFile` is missing - `cssEntryFile` is missing - `output` is not an array - no handled entry chunks are found - `output` is provided but a handled entry chunk has no matching configuration - `attrs` or `linkAttrs` is not an array for a matching entry --- ## License This project is licensed under the [MIT License](./LICENSE).