Skip to content

htmlInject

HTML 内容注入插件,在 Vite 构建过程中根据配置规则将 HTML 内容注入到目标 HTML 文件中。支持多种注入位置(head/body 首尾、选择器前后/替换)、条件注入、模板变量替换和安全过滤。

导入方式

typescript
// 子模块独立导入(推荐)
import { htmlInject } from '@meng-xi/vite-plugin/plugins/html-inject'
import type { HtmlInjectOptions, InjectRule, InjectPosition, InjectCondition, SecurityConfig, InjectionLogEntry } from '@meng-xi/vite-plugin/plugins/html-inject'

// barrel 导入
import { htmlInject } from '@meng-xi/vite-plugin'

快速开始

typescript
import { defineConfig } from 'vite'
import { htmlInject } from '@meng-xi/vite-plugin'

export default defineConfig({
	plugins: [
		htmlInject({
			rules: [
				{
					id: 'meta-description',
					content: '<meta name="description" content="{{appName}}">',
					position: 'head-end',
					templateVars: { appName: 'My Application' }
				},
				{
					id: 'analytics',
					content: '<script src="/analytics.js"></script>',
					position: 'body-end',
					condition: { type: 'env', value: 'PRODUCTION' },
					allowScriptInjection: true
				}
			]
		})
	]
})

配置选项

选项类型默认值说明
targetFilestring'index.html'目标 HTML 文件路径
rulesInjectRule[]必填注入规则数组
securitySecurityConfig见下方安全配置
templateVarsRecord<string, string>-全局模板变量
logInjectionbooleantrue输出注入日志
enabledbooleantrue启用插件
verbosebooleantrue显示详细日志
errorStrategy'throw' | 'log' | 'ignore''throw'错误处理策略

InjectRule

选项类型默认值说明
idstring-规则唯一标识符,用于日志记录
contentstring必填要注入的 HTML 内容
positionInjectPosition必填注入位置
selectorstring-选择器字符串(selector 相关位置时必填)
selectorMatch'string' | 'regex''string'选择器匹配模式
prioritynumber100优先级,数值越小越先执行
conditionInjectCondition-注入条件
templateVarsRecord<string, string>-规则级模板变量(覆盖全局)
allowScriptInjectionbooleanfalse是否允许注入脚本等危险内容

InjectPosition

说明
head-start<head> 标签开始之后
head-end</head> 标签之前
body-start<body> 标签开始之后
body-end</body> 标签之前
before-selector指定选择器之前
after-selector指定选择器之后
replace-selector替换指定选择器匹配内容

InjectCondition

选项类型说明
type'env' | 'file-contains' | 'custom'条件类型
valuestring | ((...args: any[]) => boolean)条件值
negateboolean是否取反,默认 false

条件类型说明

类型value 类型说明
envstring基于环境变量判断
file-containsstring基于 HTML 文件内容判断
custom(...args: any[]) => boolean基于自定义函数判断

SecurityConfig

选项类型默认值说明
blockDangerousTagsbooleantrue阻止危险标签(script、iframe 等)
blockDangerousAttributesbooleantrue阻止危险属性(onclick、onload 等)
allowedTagsstring[]-允许通过的标签白名单
blockedTagsstring[]-自定义阻止标签列表
blockedAttributesstring[]-自定义阻止属性列表

InjectionLogEntry

选项类型说明
ruleIdstring规则标识符
positionInjectPosition注入位置
selectorstring使用的选择器
injectedboolean是否注入成功
reasonstring注入失败原因
timestampnumber日志时间戳

示例

基本注入

typescript
htmlInject({
	rules: [
		{
			id: 'meta-viewport',
			content: '<meta name="viewport" content="width=device-width, initial-scale=1.0">',
			position: 'head-end'
		}
	]
})

模板变量

使用 语法在 content 中引用变量,规则级 templateVars 会覆盖全局 templateVars

typescript
htmlInject({
	templateVars: {
		appName: 'My App',
		version: '1.0.0'
	},
	rules: [
		{
			id: 'meta-description',
			content: '<meta name="description" content="{{appName}} v{{version}}">',
			position: 'head-end'
		},
		{
			id: 'custom-meta',
			content: '<meta name="author" content="{{author}}">',
			position: 'head-end',
			templateVars: { author: 'MengXi Studio' }
		}
	]
})

条件注入

typescript
htmlInject({
	rules: [
		{
			id: 'analytics',
			content: '<script src="/analytics.js"></script>',
			position: 'body-end',
			condition: { type: 'env', value: 'PRODUCTION' },
			allowScriptInjection: true
		},
		{
			id: 'debug-banner',
			content: '<div class="debug-banner">Debug Mode</div>',
			position: 'body-start',
			condition: { type: 'env', value: 'DEBUG' }
		},
		{
			id: 'conditional-meta',
			content: '<meta name="robots" content="noindex">',
			position: 'head-end',
			condition: { type: 'env', value: 'STAGING', negate: true }
		}
	]
})

选择器注入

typescript
htmlInject({
	rules: [
		{
			id: 'before-app',
			content: '<div class="wrapper">',
			position: 'before-selector',
			selector: '<div id="app">'
		},
		{
			id: 'after-app',
			content: '</div>',
			position: 'after-selector',
			selector: '<div id="app">'
		},
		{
			id: 'replace-placeholder',
			content: '<div class="real-content">Loaded</div>',
			position: 'replace-selector',
			selector: '<div class="placeholder">'
		}
	]
})

正则选择器

typescript
htmlInject({
	rules: [
		{
			id: 'replace-old-meta',
			content: '<meta name="description" content="New Description">',
			position: 'replace-selector',
			selector: '<meta\\s+name="description"[^>]*>',
			selectorMatch: 'regex'
		}
	]
})

优先级控制

规则按 priority 升序执行,数值越小优先级越高:

typescript
htmlInject({
	rules: [
		{ id: 'charset', content: '<meta charset="UTF-8">', position: 'head-start', priority: 1 },
		{ id: 'viewport', content: '<meta name="viewport" content="...">', position: 'head-end', priority: 10 },
		{ id: 'analytics', content: '<script>...</script>', position: 'body-end', priority: 100 }
	]
})

安全配置

typescript
htmlInject({
	security: {
		blockDangerousTags: true,
		blockDangerousAttributes: true,
		allowedTags: ['iframe'],
		blockedTags: ['object'],
		blockedAttributes: ['data-custom']
	},
	rules: [
		{
			id: 'trusted-iframe',
			content: '<iframe src="/widget.html"></iframe>',
			position: 'body-end'
		}
	]
})

自定义目标文件

typescript
htmlInject({
	targetFile: 'src/views/home.html',
	rules: [
		{
			id: 'home-specific',
			content: '<div class="home-banner">Welcome</div>',
			position: 'body-start'
		}
	]
})

注意事项

  • 默认安全配置会阻止 <script><iframe><object> 等危险标签和 onclickonload 等事件属性
  • 如需注入脚本,必须设置 allowScriptInjection: true,请确保注入内容来源可信
  • targetFile 默认匹配所有 index.html 文件,支持相对路径和文件名匹配
  • 规则按 priority 升序执行,相同优先级的规则按数组顺序执行
  • 模板变量使用 语法,规则级变量覆盖全局变量
  • condition.negate: true 可对条件结果取反

Released under the MIT License.