vite-plugin-singlefile-compression 2.1.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +109 -84
- package/dist/index.d.ts +6 -6
- package/dist/index.js +25 -17
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -4,7 +4,9 @@ Compress all assets and embeds them into `dist/index.html`, making it convenient
|
|
|
4
4
|
|
|
5
5
|
The recipient can open it directly in the browser without manually unzipping the file.
|
|
6
6
|
|
|
7
|
-
Using [DecompressionStream](https://developer.mozilla.org/docs/Web/API/DecompressionStream) + [base128-ascii](https://www.npmjs.com/package/base128-ascii).
|
|
7
|
+
Using [DecompressionStream](https://developer.mozilla.org/en-US/docs/Web/API/DecompressionStream) + [base128-ascii](https://www.npmjs.com/package/base128-ascii).
|
|
8
|
+
|
|
9
|
+
Preview: https://bddjr.github.io/vite-plugin-singlefile-compression/
|
|
8
10
|
|
|
9
11
|
## Setup
|
|
10
12
|
|
|
@@ -43,107 +45,130 @@ singleFileCompression({
|
|
|
43
45
|
}),
|
|
44
46
|
```
|
|
45
47
|
|
|
46
|
-
|
|
48
|
+
### rename
|
|
49
|
+
|
|
50
|
+
Rename index.html
|
|
51
|
+
|
|
52
|
+
type: `string`
|
|
53
|
+
|
|
54
|
+
### enableCompress
|
|
55
|
+
|
|
56
|
+
Enable compress.
|
|
57
|
+
|
|
58
|
+
default: `true`
|
|
59
|
+
|
|
60
|
+
type: `boolean`
|
|
61
|
+
|
|
62
|
+
### useBase128
|
|
63
|
+
|
|
64
|
+
Use Base128 to encode compressed script.
|
|
65
|
+
If false, use Base64.
|
|
66
|
+
https://www.npmjs.com/package/base128-ascii
|
|
67
|
+
|
|
68
|
+
default: `true`
|
|
69
|
+
|
|
70
|
+
type: `boolean`
|
|
71
|
+
|
|
72
|
+
### compressFormat
|
|
73
|
+
|
|
74
|
+
Compress format.
|
|
75
|
+
|
|
76
|
+
https://developer.mozilla.org/en-US/docs/Web/API/DecompressionStream/DecompressionStream
|
|
77
|
+
|
|
78
|
+
default: `"deflate-raw"`
|
|
79
|
+
|
|
80
|
+
type:
|
|
81
|
+
- `"deflate-raw"`
|
|
82
|
+
- `"deflate"`
|
|
83
|
+
- `"gzip"`
|
|
84
|
+
- `"brotli"`
|
|
85
|
+
- `"zstd"`
|
|
86
|
+
- `"deflateRaw"`
|
|
87
|
+
- `"gz"`
|
|
88
|
+
- `"br"`
|
|
89
|
+
- `"brotliCompress"`
|
|
90
|
+
- `"zstandard"`
|
|
91
|
+
- `"zst"`
|
|
92
|
+
|
|
93
|
+
### compressor
|
|
94
|
+
|
|
95
|
+
Custom compressor.
|
|
96
|
+
|
|
97
|
+
type: `(buf: zlib.InputType) => (Buffer | Uint8Array | Promise<Buffer | Uint8Array>)`
|
|
98
|
+
|
|
99
|
+
### htmlMinifierTerser
|
|
100
|
+
|
|
101
|
+
https://github.com/terser/html-minifier-terser?tab=readme-ov-file#options-quick-reference
|
|
102
|
+
|
|
103
|
+
default: `defaultHtmlMinifierTerserOptions`
|
|
104
|
+
|
|
105
|
+
type:
|
|
106
|
+
- `HtmlMinifierOptions`
|
|
107
|
+
- `boolean`
|
|
108
|
+
|
|
109
|
+
### tryInlineHtmlAssets
|
|
110
|
+
|
|
111
|
+
Try inline html used assets, if inlined or not used in JS.
|
|
112
|
+
|
|
113
|
+
default: `true`
|
|
114
|
+
|
|
115
|
+
type: `boolean`
|
|
116
|
+
|
|
117
|
+
### removeInlinedAssetFiles
|
|
118
|
+
|
|
119
|
+
Remove inlined asset files.
|
|
120
|
+
|
|
121
|
+
default: `true`
|
|
122
|
+
|
|
123
|
+
type: `boolean`
|
|
124
|
+
|
|
125
|
+
### tryInlineHtmlPublicIcon
|
|
126
|
+
|
|
127
|
+
Try inline html icon, if icon is in public dir.
|
|
128
|
+
|
|
129
|
+
default: `true`
|
|
130
|
+
|
|
131
|
+
type: `boolean`
|
|
132
|
+
|
|
133
|
+
### removeInlinedPublicIconFiles
|
|
134
|
+
|
|
135
|
+
Remove inlined html icon files.
|
|
136
|
+
|
|
137
|
+
default: `true`
|
|
138
|
+
|
|
139
|
+
type: `boolean`
|
|
140
|
+
|
|
141
|
+
### useImportMetaPolyfill
|
|
142
|
+
|
|
143
|
+
Use import.meta polyfill.
|
|
144
|
+
|
|
145
|
+
default: `true`
|
|
146
|
+
|
|
147
|
+
type: `boolean`
|
|
47
148
|
|
|
48
|
-
```ts
|
|
49
|
-
export interface Options {
|
|
50
|
-
/**
|
|
51
|
-
* Enable compress.
|
|
52
|
-
* @default true
|
|
53
|
-
*/
|
|
54
|
-
enableCompress?: boolean
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Use Base128 to encode compressed script.
|
|
58
|
-
* If false, use Base64.
|
|
59
|
-
* https://www.npmjs.com/package/base128-ascii
|
|
60
|
-
* @default true
|
|
61
|
-
*/
|
|
62
|
-
useBase128?: boolean
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Compress format.
|
|
66
|
-
*
|
|
67
|
-
* https://developer.mozilla.org/en-US/docs/Web/API/DecompressionStream/DecompressionStream
|
|
68
|
-
*
|
|
69
|
-
* @type {"deflate-raw" | "deflate" | "gzip" | "brotli" | "zstd" | "deflateRaw" | "gz" | "br" | "brotliCompress" | "zstandard" | "zst"}
|
|
70
|
-
*
|
|
71
|
-
* @default "deflate-raw"
|
|
72
|
-
*/
|
|
73
|
-
compressFormat?: CompressFormat | CompressFormatAlias
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Custom compressor.
|
|
77
|
-
*/
|
|
78
|
-
compressor?: Compressor
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Rename index.html
|
|
82
|
-
*/
|
|
83
|
-
rename?: string
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* https://github.com/terser/html-minifier-terser?tab=readme-ov-file#options-quick-reference
|
|
87
|
-
* @default defaultHtmlMinifierTerserOptions
|
|
88
|
-
*/
|
|
89
|
-
htmlMinifierTerser?: HtmlMinifierOptions | boolean
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Try inline html used assets, if inlined or not used in JS.
|
|
93
|
-
* @default true
|
|
94
|
-
*/
|
|
95
|
-
tryInlineHtmlAssets?: boolean
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Remove inlined asset files.
|
|
99
|
-
* @default true
|
|
100
|
-
*/
|
|
101
|
-
removeInlinedAssetFiles?: boolean
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Try inline html icon, if icon is in public dir.
|
|
105
|
-
* @default true
|
|
106
|
-
*/
|
|
107
|
-
tryInlineHtmlPublicIcon?: boolean
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Remove inlined html icon files.
|
|
111
|
-
* @default true
|
|
112
|
-
*/
|
|
113
|
-
removeInlinedPublicIconFiles?: boolean
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Use import.meta polyfill.
|
|
117
|
-
* @default true
|
|
118
|
-
*/
|
|
119
|
-
useImportMetaPolyfill?: boolean
|
|
120
|
-
}
|
|
121
|
-
```
|
|
122
149
|
|
|
123
150
|
## Effect
|
|
124
151
|
|
|
125
152
|
Preview: https://bddjr.github.io/vite-plugin-singlefile-compression/
|
|
126
153
|
|
|
127
154
|
```
|
|
128
|
-
vite v8.0.
|
|
155
|
+
vite v8.0.3 building client environment for production...
|
|
129
156
|
✓ 42 modules transformed.
|
|
130
157
|
rendering chunks (1)...
|
|
131
158
|
|
|
132
|
-
vite-plugin-singlefile-compression 2.
|
|
159
|
+
vite-plugin-singlefile-compression 2.2.0 deflate-raw base128-ascii
|
|
133
160
|
|
|
134
161
|
file:///D:/code/js/vite-plugin-singlefile-compression/test/dist/index.html
|
|
135
|
-
|
|
162
|
+
122.739 kB -> 50.220 kB
|
|
136
163
|
|
|
137
164
|
Finish.
|
|
138
165
|
|
|
139
166
|
computing gzip size...
|
|
140
|
-
dist/index.html 50.
|
|
167
|
+
dist/index.html 50.22 kB │ gzip: 43.77 kB
|
|
141
168
|
|
|
142
|
-
✓ built in
|
|
169
|
+
✓ built in 317ms
|
|
143
170
|
```
|
|
144
171
|
|
|
145
|
-

|
|
146
|
-
|
|
147
172
|
## Clone
|
|
148
173
|
|
|
149
174
|
```
|
|
@@ -153,5 +178,5 @@ npm i
|
|
|
153
178
|
cd test
|
|
154
179
|
npm i
|
|
155
180
|
cd ..
|
|
156
|
-
|
|
181
|
+
npm run build
|
|
157
182
|
```
|
package/dist/index.d.ts
CHANGED
|
@@ -18,12 +18,16 @@ declare const compressFormatAlias: Readonly<{
|
|
|
18
18
|
zstandard: "zstd";
|
|
19
19
|
zst: "zstd";
|
|
20
20
|
}>;
|
|
21
|
-
type Compressor = ((buf: zlib.InputType) => (Buffer | Uint8Array));
|
|
22
|
-
type CompressFormat = keyof typeof compressors;
|
|
21
|
+
type Compressor = ((buf: zlib.InputType) => (Buffer | Uint8Array | Promise<Buffer | Uint8Array>));
|
|
22
|
+
type CompressFormat = keyof typeof compressors | CompressionFormat;
|
|
23
23
|
type CompressFormatAlias = keyof typeof compressFormatAlias;
|
|
24
24
|
//#endregion
|
|
25
25
|
//#region _dist/options.d.ts
|
|
26
26
|
interface Options {
|
|
27
|
+
/**
|
|
28
|
+
* Rename index.html
|
|
29
|
+
*/
|
|
30
|
+
rename?: string;
|
|
27
31
|
/**
|
|
28
32
|
* Enable compress.
|
|
29
33
|
* @default true
|
|
@@ -50,10 +54,6 @@ interface Options {
|
|
|
50
54
|
* Custom compressor.
|
|
51
55
|
*/
|
|
52
56
|
compressor?: Compressor;
|
|
53
|
-
/**
|
|
54
|
-
* Rename index.html
|
|
55
|
-
*/
|
|
56
|
-
rename?: string;
|
|
57
57
|
/**
|
|
58
58
|
* https://github.com/terser/html-minifier-terser?tab=readme-ov-file#options-quick-reference
|
|
59
59
|
* @default defaultHtmlMinifierTerserOptions
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import zlib from "zlib";
|
|
|
9
9
|
import svgToTinyDataUri from "mini-svg-data-uri";
|
|
10
10
|
import mime from "mime";
|
|
11
11
|
//#region _dist/getVersion.js
|
|
12
|
-
var version = "2.
|
|
12
|
+
var version = "2.2.0";
|
|
13
13
|
//#endregion
|
|
14
14
|
//#region _dist/compress.js
|
|
15
15
|
const compressors = {
|
|
@@ -46,11 +46,18 @@ function switchCompressor(format) {
|
|
|
46
46
|
if (typeof f == "function") return f;
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
+
try {
|
|
50
|
+
const cs = new CompressionStream(format);
|
|
51
|
+
return (buf) => new Response(new ReadableStream({ start(controller) {
|
|
52
|
+
controller.enqueue(buf);
|
|
53
|
+
controller.close();
|
|
54
|
+
} }).pipeThrough(cs)).bytes();
|
|
55
|
+
} catch {}
|
|
49
56
|
throw Error(`Could not get compressor: Unknown compress format '${format}', please set your compressor function.`);
|
|
50
57
|
}
|
|
51
|
-
function compress(format, buf, useBase128, compressor) {
|
|
58
|
+
async function compress(format, buf, useBase128, compressor) {
|
|
52
59
|
if (typeof compressor != "function") compressor = switchCompressor(format);
|
|
53
|
-
const outBuf = compressor(buf);
|
|
60
|
+
const outBuf = await compressor(buf);
|
|
54
61
|
if (useBase128) return base128.encode(outBuf).toJSTemplateLiterals();
|
|
55
62
|
if (Buffer.isBuffer(outBuf)) return outBuf.toString("base64");
|
|
56
63
|
if (typeof outBuf.toBase64 == "function") return outBuf.toBase64();
|
|
@@ -60,7 +67,7 @@ function compress(format, buf, useBase128, compressor) {
|
|
|
60
67
|
//#region _dist/templateRaw.js
|
|
61
68
|
var raw = {
|
|
62
69
|
"assets": "{let e={\"\":\"\"};for(let o in e)for(let s of document.querySelectorAll(`[src=\"data:${o}\"]`))s.src=e[o]}",
|
|
63
|
-
"base128": "var a=\"<script>\",
|
|
70
|
+
"base128": "var a=\"<script>\",c=a.length,r=new Uint8Array(c/8*7),p=0,n=0,e,t=o=>(e=a.charCodeAt(p++))>127?e=0:e,i=Response;for(;p<c;)r[n++]=t()<<1|t()>>6,r[n++]=e<<2|t()>>5,r[n++]=e<<3|t()>>4,r[n++]=e<<4|t()>>3,r[n++]=e<<5|t()>>2,r[n++]=e<<6|t()>>1,r[n++]=e<<7|t();new i(new i(r).body.pipeThrough(new DecompressionStream(\"<format>\")),{headers:{\"Content-Type\":\"text/javascript\"}}).blob().then(o=>(import(o=URL.createObjectURL(o)),URL.revokeObjectURL(o)))",
|
|
64
71
|
"base64": "fetch(\"data:;base64,<script>\").then(e=>new Response(e.body.pipeThrough(new DecompressionStream(\"<format>\")),{headers:{\"Content-Type\":\"text/javascript\"}}).blob()).then(e=>(import(e=URL.createObjectURL(e)),URL.revokeObjectURL(e)))",
|
|
65
72
|
"css": "document.head.appendChild(document.createElement(\"style\")).innerHTML=\"<style>\"",
|
|
66
73
|
"icon": "document.querySelector(\"link[rel=icon]\").href=\"<icon>\"",
|
|
@@ -82,8 +89,8 @@ const files = {
|
|
|
82
89
|
importmeta: split2(raw.importmeta, "\"<path>\"")
|
|
83
90
|
};
|
|
84
91
|
const template = {
|
|
85
|
-
base(script, format, useBase128, compressor) {
|
|
86
|
-
script = compress(format, script, useBase128, compressor);
|
|
92
|
+
async base(script, format, useBase128, compressor) {
|
|
93
|
+
script = await compress(format, script, useBase128, compressor);
|
|
87
94
|
if (useBase128) return files.base128.replace("<format>", format).split("\"<script>\"", 2).join(script);
|
|
88
95
|
return files.base64.replace("<format>", format).split("<script>", 2).join(script);
|
|
89
96
|
},
|
|
@@ -108,7 +115,8 @@ function bufferToDataURL(name, b) {
|
|
|
108
115
|
//#endregion
|
|
109
116
|
//#region _dist/kB.js
|
|
110
117
|
function kB(size) {
|
|
111
|
-
|
|
118
|
+
const s = String(size).padStart(4, "0");
|
|
119
|
+
return `${s.slice(0, -3)}.${s.slice(-3)} kB`;
|
|
112
120
|
}
|
|
113
121
|
//#endregion
|
|
114
122
|
//#region _dist/options.js
|
|
@@ -123,16 +131,16 @@ const defaultHtmlMinifierTerserOptions = {
|
|
|
123
131
|
function getInnerOptions(opt) {
|
|
124
132
|
opt ||= {};
|
|
125
133
|
return {
|
|
126
|
-
enableCompress: opt.enableCompress ?? true,
|
|
127
134
|
rename: opt.rename == null ? void 0 : String(opt.rename),
|
|
135
|
+
enableCompress: opt.enableCompress ?? true,
|
|
136
|
+
useBase128: opt.useBase128 ?? true,
|
|
137
|
+
compressFormat: opt.compressFormat ? compressFormatAlias.hasOwnProperty(opt.compressFormat) ? compressFormatAlias[opt.compressFormat] : String(opt.compressFormat) : "deflate-raw",
|
|
138
|
+
compressor: typeof opt.compressor == "function" ? opt.compressor : void 0,
|
|
128
139
|
htmlMinifierTerser: opt.htmlMinifierTerser == null || opt.htmlMinifierTerser === true ? defaultHtmlMinifierTerserOptions : opt.htmlMinifierTerser,
|
|
129
140
|
tryInlineHtmlAssets: opt.tryInlineHtmlAssets ?? true,
|
|
130
141
|
removeInlinedAssetFiles: opt.removeInlinedAssetFiles ?? true,
|
|
131
142
|
tryInlineHtmlPublicIcon: opt.tryInlineHtmlPublicIcon ?? true,
|
|
132
143
|
removeInlinedPublicIconFiles: opt.removeInlinedPublicIconFiles ?? true,
|
|
133
|
-
useBase128: opt.useBase128 ?? true,
|
|
134
|
-
compressFormat: opt.compressFormat ? compressFormatAlias.hasOwnProperty(opt.compressFormat) ? compressFormatAlias[opt.compressFormat] : String(opt.compressFormat) : "deflate-raw",
|
|
135
|
-
compressor: typeof opt.compressor == "function" ? opt.compressor : void 0,
|
|
136
144
|
useImportMetaPolyfill: opt.useImportMetaPolyfill ?? true
|
|
137
145
|
};
|
|
138
146
|
}
|
|
@@ -147,7 +155,7 @@ function singleFileCompression(opt) {
|
|
|
147
155
|
let conf;
|
|
148
156
|
const innerOptions = getInnerOptions(opt);
|
|
149
157
|
return {
|
|
150
|
-
name: "
|
|
158
|
+
name: "vite-plugin-singlefile-compression",
|
|
151
159
|
enforce: "post",
|
|
152
160
|
config(...args) {
|
|
153
161
|
return setConfig.call(this, innerOptions, ...args);
|
|
@@ -155,8 +163,8 @@ function singleFileCompression(opt) {
|
|
|
155
163
|
configResolved(c) {
|
|
156
164
|
conf = c;
|
|
157
165
|
},
|
|
158
|
-
generateBundle(outputOptions, bundle) {
|
|
159
|
-
return generateBundle(bundle, conf, innerOptions);
|
|
166
|
+
generateBundle(outputOptions, bundle, isWrite) {
|
|
167
|
+
return generateBundle.call(this, bundle, conf, innerOptions);
|
|
160
168
|
}
|
|
161
169
|
};
|
|
162
170
|
}
|
|
@@ -175,7 +183,7 @@ function setConfig(opt, config, env) {
|
|
|
175
183
|
}
|
|
176
184
|
}
|
|
177
185
|
async function generateBundle(bundle, config, options) {
|
|
178
|
-
console.log(pc.reset("\n\n") + pc.cyan("vite-plugin-singlefile-compression " + version) + " " + (options.enableCompress ? pc.green(options.compressFormat + " " + (options.useBase128 ? "base128-ascii" : "base64")) : pc.red("disable
|
|
186
|
+
console.log(pc.reset("\n\n") + pc.cyan("vite-plugin-singlefile-compression " + version) + " " + (options.enableCompress ? pc.green(options.compressFormat + " " + (options.useBase128 ? "base128-ascii" : "base64")) : pc.red("disable-compress")));
|
|
179
187
|
if (options.rename && options.rename != "index.html" && Object.prototype.hasOwnProperty.call(bundle, "index.html") && !Object.prototype.hasOwnProperty.call(bundle, options.rename)) {
|
|
180
188
|
bundle[options.rename] = bundle["index.html"];
|
|
181
189
|
bundle[options.rename].fileName = options.rename;
|
|
@@ -297,7 +305,7 @@ async function generateBundle(bundle, config, options) {
|
|
|
297
305
|
newJSCode.push(code);
|
|
298
306
|
} else inlineHtmlAssets();
|
|
299
307
|
let outputScript = newJSCode.join(";");
|
|
300
|
-
if (options.enableCompress) outputScript = template.base(outputScript, options.compressFormat, options.useBase128, options.compressor);
|
|
308
|
+
if (options.enableCompress) outputScript = await template.base(outputScript, options.compressFormat, options.useBase128, options.compressor);
|
|
301
309
|
else outputScript = outputScript.replaceAll("<\/script", "<\\/script");
|
|
302
310
|
htmlChunk.source = htmlChunk.source.split(fakeScript, 2).join(outputScript);
|
|
303
311
|
console.log(" " + pc.gray(kB(oldSize) + " -> ") + pc.cyanBright(kB(htmlChunk.source.length)) + "\n");
|
|
@@ -307,7 +315,7 @@ async function generateBundle(bundle, config, options) {
|
|
|
307
315
|
for (const name of globalDelete) if (!globalDoNotDelete.has(name)) delete bundle[name];
|
|
308
316
|
}
|
|
309
317
|
if (options.removeInlinedPublicIconFiles) for (const name of globalRemoveDistFileNames) try {
|
|
310
|
-
fs.
|
|
318
|
+
fs.rmSync(path.join(config.build.outDir, name), { force: true });
|
|
311
319
|
} catch (e) {
|
|
312
320
|
console.error(e);
|
|
313
321
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-singlefile-compression",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"author": "bddjr",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Compress all assets and embeds them into dist/index.html, making it convenient to share as a single HTML file.",
|
|
@@ -48,19 +48,20 @@
|
|
|
48
48
|
],
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@types/html-minifier-terser": ">=7.0.2",
|
|
51
|
+
"@types/node": "*",
|
|
51
52
|
"base128-ascii": ">=2.1.11",
|
|
52
53
|
"html-minifier-terser": ">=7.2.0",
|
|
53
54
|
"jsdom": ">=28.1.0",
|
|
54
55
|
"mime": ">=4.1.0",
|
|
55
56
|
"mini-svg-data-uri": ">=1.4.4",
|
|
56
|
-
"picocolors": ">=1.1.1"
|
|
57
|
+
"picocolors": ">=1.1.1",
|
|
58
|
+
"vite": ">=3.0.0"
|
|
57
59
|
},
|
|
58
60
|
"devDependencies": {
|
|
61
|
+
"@bddjr/rimraf": "^0.1.0",
|
|
59
62
|
"@types/jsdom": ">=28.0.0",
|
|
60
63
|
"@types/node": "^22.19.15",
|
|
61
64
|
"esbuild": "^0.27.4",
|
|
62
|
-
"marked": "^17.0.4",
|
|
63
|
-
"rimraf": ">=6.1.3",
|
|
64
65
|
"rolldown": ">=1.0.0-rc.9",
|
|
65
66
|
"rolldown-plugin-dts": "^0.22.5",
|
|
66
67
|
"rollup": ">=4.59.0",
|