Licence
MIT
Version
0.5.2
Deps
1
Size
30 kB
Vulns
0
Weekly
76
@zhoumutou/vite-plugin-inline
一个将构建产物中的 CSS 与 JavaScript 资源内联到 HTML 的 Vite 插件。常见情况下会输出单个、可独立部署的 HTML;若动态 chunk 需要保留外链,或插件为了安全回退保留入口脚本,则会继续输出必要的外部 JavaScript 文件。
English | 中文
特性
- 将所有
<link rel="stylesheet">内联为<style>放入 HTML - 将入口 JS 以内联方式注入为单个
<script type="module">- 若入口仍存在静态 import,会在内存中重打包以移除这些静态 import
- 可选:通过
inlineDynamicImports将动态 import 也一并合并进内联脚本
- 从最终产物中删除已成功内联的 JS/CSS 文件及其 sourcemap
- 清理指向已内联 chunk 的
<link rel="modulepreload"> - 保留被替换的 emitted HTML 标签上的部分属性(
style保留nonce/id/media;script保留nonce/id) - 内联内容会转义
</script>与</style>,避免提前闭合
安装
# npm
npm install @zhoumutou/vite-plugin-inline -D
# yarn
yarn add @zhoumutou/vite-plugin-inline -D
# pnpm
pnpm add @zhoumutou/vite-plugin-inline -D使用
import inline from '@zhoumutou/vite-plugin-inline'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
inline({
// 可选配置
// removeComments: true, // 移除内联 CSS 的块级注释
// cdataJs: false, // 为内联 JS 包裹 <![CDATA[ ... ]]>
// inlineDynamicImports: false, // 合并动态导入到内联脚本
}),
],
})开发
pnpm install
pnpm check
pnpm test
pnpm build当前发布产物为 ESM-only。
选项
interface Options {
/**
* 是否移除内联 CSS 的块级注释(/* ... */)。
* JS 不做直接注释处理;当发生重打包时,上游最小化流程仍可能移除注释。
* @default true
*/
removeComments?: boolean
/**
* 是否使用 <![CDATA[ ... ]]> 包裹内联 JS,以兼容 XML/XHTML。
* @default false
*/
cdataJs?: boolean
/**
* 是否在内存重打包时,将动态导入也合并进最终的内联脚本。
* 为 true 时,不会再额外产出 JS chunk。
* @default false
*/
inlineDynamicImports?: boolean
}工作原理
- 扫描输出的 HTML:
- 将
<link rel="stylesheet" href="*.css">替换为<style>...</style> - 查找属于本次 bundle 的主
<script src="*.mjs|*.js">(优先type="module")
- 将
- 生成内联 JS:
- 若入口无静态 import,直接复用已产出的 chunk 代码
- 若存在静态 import,则在内存中重打包以移除它们
- 当
inlineDynamicImports为true时,同时合并动态 import - 若动态 import 保持外链,插件会重写内联入口中的导入路径,确保仍能正确指向产物中的 chunk
- 若重打包失败,会保留原始外链入口 script 并给出 warning,而不是输出一个可能损坏的内联模块
- 用内联内容替换原标签,然后:
- 从 bundle 中删除实际已被内联的 JS/CSS 及其
.map - 移除指向已内联 chunk 的
<link rel="modulepreload">
- 从 bundle 中删除实际已被内联的 JS/CSS 及其
示例
输入 HTML:
<link rel="stylesheet" href="style.css" />
<script type="module" src="main.js"></script>输出 HTML:
<style>
/* inlined CSS content */
</style>
<script type="module">
/* inlined (optionally rebundled) JS content */
</script>注意与限制
- 资源定位:
- 插件会优先基于每个 HTML 文件的相对路径(以及可用时的 Vite
base)来解析资源,只在必要时才回退到基本名匹配。 - 若只剩下没有路径上下文的重复基本名,仍可能出现歧义。
- 插件会优先基于每个 HTML 文件的相对路径(以及可用时的 Vite
- 动态导入:
- 当
inlineDynamicImports=false(默认)时,动态 chunk 仍为外部文件;插件不会删除它们。 - 若入口同时包含静态与动态 import,且
inlineDynamicImports=false,插件会保留原始外链入口 script,并发出 warning,避免产出损坏的内联模块。
- 当
- 注释保留:
removeComments: false只会关闭本插件自己的 CSS 注释剥离,不会自动关闭 Vite 或 Rolldown 的最小化。如果构建链本身仍在压缩 CSS,注释可能在标签替换前就已经被移除了。
- 非 CSS/JS 资源:
- 图片、字体、JSON 等不会被内联。
- 外部 URL:
- 不属于当前 bundle 的绝对 URL 或协议相对地址的 CSS/JS 资源会保持原样,不会被误内联。
- HTML 解析:
- 基于正则替换;复杂模版场景可能需要自行调整。
- 安全/CSP:
- 插件会保留它实际替换到的 emitted HTML 标签上的属性。若 Vite 在 HTML 转换阶段已经移除了源 HTML 中的 script 属性,插件无法在后续阶段再恢复它。
- 内联内容转义避免提前结束标签。
类似插件 / 灵感
感谢以上项目的启发。
许可
MIT