diff --git a/README-zh-CN.md b/README-zh-CN.md index 5e19acc..c45bcae 100644 --- a/README-zh-CN.md +++ b/README-zh-CN.md @@ -64,7 +64,31 @@ export interface Options { * https://github.com/terser/html-minifier-terser?tab=readme-ov-file#options-quick-reference * @default defaultHtmlMinifierTerserOptions */ - htmlMinifierTerser?: htmlMinifierOptions | true | false + htmlMinifierTerser?: htmlMinifierOptions | boolean + + /** + * 尝试内联 html 用到的资源,如果在 JS 里被内联或未使用。 + * @default true + */ + tryInlineHtmlAssets?: boolean + + /** + * 移除已内联的资源文件。 + * @default true + */ + removeInlinedAssetFiles?: boolean + + /** + * 尝试内联 html 的图标,如果图标在 public 文件夹。 + * @default true + */ + tryInlineHtmlPublicIcon?: boolean + + /** + * 移除已内联的 html 图标文件。 + * @default true + */ + removeInlinedPublicIconFiles?: boolean } ``` @@ -75,19 +99,19 @@ vite v5.4.11 building for production... ✓ 45 modules transformed. rendering chunks (1)... -vite-plugin-singlefile-compression building... +vite-plugin-singlefile-compression 1.1.0 building... file:///D:/bddjr/Desktop/code/js/vite-plugin-singlefile-compression/test/dist/index.html - 97.52 KiB -> 50.98 KiB + 101.43 KiB -> 52.35 KiB Finish. -dist/index.html 52.19 kB -✓ built in 685ms +dist/index.html 53.60 kB +✓ built in 678ms ``` ```html -Vite App
+Vite App
``` ## Clone diff --git a/README.md b/README.md index e3e5bc3..5ddfbf7 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,31 @@ export interface Options { * https://github.com/terser/html-minifier-terser?tab=readme-ov-file#options-quick-reference * @default defaultHtmlMinifierTerserOptions */ - htmlMinifierTerser?: htmlMinifierOptions | true | false + htmlMinifierTerser?: htmlMinifierOptions | boolean + + /** + * Try inline html used assets, if inlined or not used in JS. + * @default true + */ + tryInlineHtmlAssets?: boolean + + /** + * Remove inlined asset files. + * @default true + */ + removeInlinedAssetFiles?: boolean + + /** + * Try inline html icon, if icon is in public dir. + * @default true + */ + tryInlineHtmlPublicIcon?: boolean + + /** + * Remove inlined html icon files. + * @default true + */ + removeInlinedPublicIconFiles?: boolean } ``` @@ -75,19 +99,19 @@ vite v5.4.11 building for production... ✓ 45 modules transformed. rendering chunks (1)... -vite-plugin-singlefile-compression building... +vite-plugin-singlefile-compression 1.1.0 building... file:///D:/bddjr/Desktop/code/js/vite-plugin-singlefile-compression/test/dist/index.html - 97.52 KiB -> 50.98 KiB + 101.43 KiB -> 52.35 KiB Finish. -dist/index.html 52.19 kB -✓ built in 685ms +dist/index.html 53.60 kB +✓ built in 678ms ``` ```html -Vite App
+Vite App
``` ## Clone diff --git a/package.json b/package.json index 65c5d3f..1873368 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vite-plugin-singlefile-compression", - "version": "1.0.5", + "version": "1.1.0", "main": "dist/index.js", "typings": "dist/index.d.ts", "files": [ @@ -23,7 +23,9 @@ "url": "https://github.com/bddjr/vite-plugin-singlefile-compression" }, "keywords": [ + "vite-plugin", "vite", + "plugin", "SFA", "single-file", "singlefile", diff --git a/src/index.ts b/src/index.ts index 4f5369a..60ba44c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -import { UserConfig, PluginOption } from "vite" +import { UserConfig, PluginOption, ResolvedBuildOptions, ResolvedConfig } from "vite" import { OutputChunk, OutputAsset, OutputBundle } from "rollup" import mime from 'mime' import pc from "picocolors" @@ -16,6 +16,38 @@ export interface Options { * @default defaultHtmlMinifierTerserOptions */ htmlMinifierTerser?: htmlMinifierOptions | boolean + + /** + * Try inline html used assets, if inlined or not used in JS. + * @default true + */ + tryInlineHtmlAssets?: boolean + + /** + * Remove inlined asset files. + * @default true + */ + removeInlinedAssetFiles?: boolean + + /** + * Try inline html icon, if icon is in public dir. + * @default true + */ + tryInlineHtmlPublicIcon?: boolean + + /** + * Remove inlined html icon files. + * @default true + */ + removeInlinedPublicIconFiles?: boolean +} + +interface innerOptions { + htmlMinifierTerser: htmlMinifierOptions | false + tryInlineHtmlAssets: boolean + removeInlinedAssetFiles: boolean + tryInlineHtmlPublicIcon: boolean + removeInlinedPublicIconFiles: boolean } export const defaultHtmlMinifierTerserOptions: htmlMinifierOptions = { @@ -27,27 +59,68 @@ export const defaultHtmlMinifierTerserOptions: htmlMinifierOptions = { minifyJS: false, } -export function singleFileCompression(options?: Options): PluginOption { - const htmlMinifierOptions = - options?.htmlMinifierTerser == null || options.htmlMinifierTerser === true - ? defaultHtmlMinifierTerserOptions - : options.htmlMinifierTerser +export function singleFileCompression(opt?: Options): PluginOption { + opt ||= {} + + const innerOpt: innerOptions = { + htmlMinifierTerser: + opt.htmlMinifierTerser == null || opt.htmlMinifierTerser === true + ? defaultHtmlMinifierTerserOptions + : opt.htmlMinifierTerser, + + tryInlineHtmlAssets: + opt.tryInlineHtmlAssets == null + ? true + : opt.tryInlineHtmlAssets, + + removeInlinedAssetFiles: + opt.removeInlinedAssetFiles == null + ? true + : opt.removeInlinedAssetFiles, + + tryInlineHtmlPublicIcon: + opt.tryInlineHtmlPublicIcon == null + ? true + : opt.tryInlineHtmlPublicIcon, + + removeInlinedPublicIconFiles: + opt.removeInlinedPublicIconFiles == null + ? true + : opt.removeInlinedPublicIconFiles + } + + let conf: ResolvedConfig return { name: "singleFileCompression", enforce: "post", config: setConfig, - generateBundle: (_, bundle) => generateBundle(bundle, htmlMinifierOptions), + configResolved(c) { conf = c }, + generateBundle: (_, bundle) => generateBundle(bundle, conf, innerOpt), } } export default singleFileCompression -const template = fs.readFileSync(path.join(import.meta.dirname, "template.js")).toString() +const template = fs.readFileSync( + path.join(import.meta.dirname, "template.js") +).toString().split('{' } ) if (!ok) continue - if (htmlMinifierOptions) - newHtml = await htmlMinify(newHtml, htmlMinifierOptions) + // minify html + if (options.htmlMinifierTerser) + newHtml = await htmlMinify(newHtml, options.htmlMinifierTerser) // finish htmlChunk.source = newHtml @@ -194,15 +349,27 @@ async function generateBundle(bundle: OutputBundle, htmlMinifierOptions: htmlMin // delete assets for (const name of thisDel) { - globalDel.add(name) + globalDelete.add(name) } } - // delete inlined assets - for (const name of globalDel) { - // do not delete not inlined asset - if (!globalDoNotDel.has(name)) - delete bundle[name] + if (options.removeInlinedAssetFiles) { + // delete inlined assets + for (const name of globalDelete) { + // do not delete not inlined asset + if (!globalDoNotDelete.has(name)) + delete bundle[name] + } + } + if (options.removeInlinedPublicIconFiles) { + // delete inlined public files + for (const name of globalRemoveDistFileNames) { + try { + fs.unlinkSync(path.join(config.build.outDir, name)) + } catch (e) { + console.error(e) + } + } } console.log(pc.green('Finish.\n')) } diff --git a/test/index.html b/test/index.html index 38d7e26..09bfa96 100644 --- a/test/index.html +++ b/test/index.html @@ -2,8 +2,8 @@ - + Vite App