Skip to content

easy-vite/plugin-html

Repository files navigation

@easy-vite/plugin-html

A modern Vite plugin for HTML — EJS templating, minification, MPA support, custom entry/template & .env injection. Framework-agnostic (Vue / React / Svelte). Built for Vite 8 (Rolldown + Oxc).

English | 中文

npm version downloads license vite peer node

✨ Highlights

Rebuilt from vite-plugin-html for the Vite 8 era — ESM-first, zero-clutter runtime deps, powered by the same stack Vite itself uses (Rolldown + Oxc).

Core capabilities

  • 🗜️ HTML minification — powered by html-minifier-terser
  • 📝 EJS templating — variables, partials & loops directly in index.html
  • 📄 Multi-page apps (MPA) — multiple entries & templates, first-class
  • 🚪 Custom entry / template — point to any path
  • 🔐 .env injection — via Vite-native loadEnv
  • 🏷️ Tag injection — inject <script> / <link> / custom tags anywhere
  • 🧩 Framework-agnostic — Vue / React / Svelte / plain HTML

Built on a modern toolchain

  • ⚡ Vite 8 (Rolldown + Oxc) — backward compatible to Vite 5
  • 🪶 Only 7 runtime deps (was 12+) — dropped fs-extra, dotenv, consola, etc.
  • 📦 Dual ESM / CJS export + full TypeScript types
  • 🛠️ oxlint + oxfmt replacing eslint / prettier

Install (pnpm or yarn or npm)

node version: >=20.19

vite version: >=5.0.0

pnpm add @easy-vite/plugin-html -D

or

yarn add @easy-vite/plugin-html -D

or

npm i @easy-vite/plugin-html -D

Usage

  • Add EJS tags to index.html, e.g.
<head>
  <meta charset="UTF-8" />
  <link rel="icon" href="/favicon.ico" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title><%- title %></title>
  <%- injectScript %>
</head>
  • Configure in vite.config.ts, this method can introduce the required functions as needed
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { createHtmlPlugin } from '@easy-vite/plugin-html'

export default defineConfig({
  plugins: [
    vue(),
    createHtmlPlugin({
      minify: true,
      /**
       * After writing entry here, you will not need to add script tags in `index.html`, the original tags need to be deleted
       * @default src/main.ts
       */
      entry: 'src/main.ts',
      /**
       * If you want to store `index.html` in the specified folder, you can modify it, otherwise no configuration is required
       * @default index.html
       */
      template: 'public/index.html',
      /**
       * Data that needs to be injected into the index.html ejs template
       */
      inject: {
        data: {
          title: 'index',
          injectScript: `<script src="./inject.js"></script>`,
        },
        tags: [
          {
            injectTo: 'body-prepend',
            tag: 'div',
            attrs: { id: 'tag' },
          },
        ],
      },
    }),
  ],
})

Multi-page application configuration

import { defineConfig } from 'vite'
import { createHtmlPlugin } from '@easy-vite/plugin-html'

export default defineConfig({
  plugins: [
    createHtmlPlugin({
      minify: true,
      pages: [
        {
          entry: 'src/main.ts',
          filename: 'index.html',
          template: 'public/index.html',
          injectOptions: {
            data: {
              title: 'index',
              injectScript: `<script src="./inject.js"></script>`,
            },
            tags: [
              {
                injectTo: 'body-prepend',
                tag: 'div',
                attrs: { id: 'tag1' },
              },
            ],
          },
        },
        {
          entry: 'src/other-main.ts',
          filename: 'other.html',
          template: 'public/other.html',
          injectOptions: {
            data: {
              title: 'other page',
              injectScript: `<script src="./inject.js"></script>`,
            },
            tags: [
              {
                injectTo: 'body-prepend',
                tag: 'div',
                attrs: { id: 'tag2' },
              },
            ],
          },
        },
      ],
    }),
  ],
})

Parameter Description

createHtmlPlugin(options: UserOptions)

UserOptions

Parameter Types Default Description
entry string src/main.ts entry file path
template string index.html relative path to the template
inject InjectOptions - Data injected into HTML
minify boolean|MinifyOptions - whether to compress html
pages PageOption - Multi-page configuration

InjectOptions

Parameter Types Default Description
data Record<string, any> - injected data
ejsOptions EJSOptions - ejs configuration OptionsEJSOptions
tags HtmlTagDescriptor - List of tags to inject

data can be accessed in html using the ejs template syntax

Env inject

By default, the contents of the .env file will be injected into index.html, similar to vite's loadEnv function

PageOption

Parameter Types Default Description
filename string - html file name
template string index.html relative path to the template
entry string src/main.ts entry file path
injectOptions InjectOptions - Data injected into HTML

MinifyOptions

Default compression configuration

collapseWhitespace: true,
keepClosingSlash: true,
removeComments: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
useShortDoctype: true,
minifyCSS: true,

Run the playground

pnpm install

# SPA — auto build core (watch) and start the playground dev server
pnpm dev:basic

# MPA
pnpm dev:mpa

# Custom entry / template
pnpm dev:entry

Development

pnpm install
pnpm build:core # build the plugin (vite lib + tsc type declarations)
pnpm test       # run unit tests (vitest)
pnpm lint       # lint with oxlint
pnpm format     # format with oxfmt

Requires Node >=20.19 and pnpm >=10. Linting is powered by oxlint and formatting by oxfmt.

License

MIT

About

现代化的 Vite HTML 处理插件 —— EJS 模板、HTML 压缩、多页应用支持、自定义 entry/template、.env 注入。框架无关,面向 Vite 8(Rolldown + Oxc)

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors