vite-plugin-rebundle 1.3.0 → 1.3.2
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/dist/rebundle.d.ts +41 -0
- package/dist/rebundle.js +182 -0
- package/package.json +15 -8
- package/src/rebundle.ts +12 -4
- package/src/index.ts +0 -9
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Unit } from '@eposlabs/utils';
|
|
2
|
+
import { InputOptions, OutputOptions } from 'rolldown';
|
|
3
|
+
import { OutputChunk, OutputBundle } from 'rollup';
|
|
4
|
+
import { Plugin } from 'vite';
|
|
5
|
+
|
|
6
|
+
declare const _code_: unique symbol;
|
|
7
|
+
declare const _sourcemap_: unique symbol;
|
|
8
|
+
type RolldownOptions = {
|
|
9
|
+
input: InputOptions;
|
|
10
|
+
output: OutputOptions;
|
|
11
|
+
};
|
|
12
|
+
type Options = {
|
|
13
|
+
[bundleName: string]: RolldownOptions;
|
|
14
|
+
};
|
|
15
|
+
declare class Rebundle extends Unit {
|
|
16
|
+
private options;
|
|
17
|
+
private config;
|
|
18
|
+
private originalFiles;
|
|
19
|
+
private rebundledFiles;
|
|
20
|
+
private hasError;
|
|
21
|
+
private port;
|
|
22
|
+
private ws;
|
|
23
|
+
constructor(options: Options);
|
|
24
|
+
get vite(): Plugin;
|
|
25
|
+
private onConfig;
|
|
26
|
+
private onConfigResolved;
|
|
27
|
+
private onBuildEnd;
|
|
28
|
+
private onWriteBundle;
|
|
29
|
+
rebundleChunk(chunk: OutputChunk, bundle: OutputBundle): Promise<boolean | undefined>;
|
|
30
|
+
private removeChunk;
|
|
31
|
+
private readChunkFiles;
|
|
32
|
+
private get dist();
|
|
33
|
+
private readFromDist;
|
|
34
|
+
private writeToDist;
|
|
35
|
+
private removeFromDist;
|
|
36
|
+
private ensureWs;
|
|
37
|
+
private removeDirectoryIfEmpty;
|
|
38
|
+
}
|
|
39
|
+
declare function rebundle(options?: Options): Plugin<any>;
|
|
40
|
+
|
|
41
|
+
export { type Options, Rebundle, type RolldownOptions, _code_, _sourcemap_, rebundle as default, rebundle };
|
package/dist/rebundle.js
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
// src/rebundle.ts
|
|
2
|
+
import { safe, Unit } from "@eposlabs/utils";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import { filesize } from "filesize";
|
|
5
|
+
import { readdir, readFile, rmdir, stat, unlink, writeFile } from "fs/promises";
|
|
6
|
+
import { dirname, extname, join } from "path";
|
|
7
|
+
import { getPort } from "portfinder";
|
|
8
|
+
import { rolldown } from "rolldown";
|
|
9
|
+
import { WebSocketServer } from "ws";
|
|
10
|
+
var _code_ = Symbol("rebundle:code");
|
|
11
|
+
var _sourcemap_ = Symbol("rebundle:sourcemap");
|
|
12
|
+
var Rebundle = class extends Unit {
|
|
13
|
+
options;
|
|
14
|
+
config = null;
|
|
15
|
+
originalFiles = {};
|
|
16
|
+
rebundledFiles = {};
|
|
17
|
+
hasError = false;
|
|
18
|
+
port = null;
|
|
19
|
+
ws = null;
|
|
20
|
+
constructor(options) {
|
|
21
|
+
super();
|
|
22
|
+
this.options = options;
|
|
23
|
+
}
|
|
24
|
+
get vite() {
|
|
25
|
+
return {
|
|
26
|
+
name: "vite-plugin-rebundle",
|
|
27
|
+
apply: "build",
|
|
28
|
+
enforce: "post",
|
|
29
|
+
config: this.onConfig,
|
|
30
|
+
configResolved: this.onConfigResolved,
|
|
31
|
+
buildEnd: this.onBuildEnd,
|
|
32
|
+
writeBundle: this.onWriteBundle
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// VITE HOOKS
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
onConfig = async () => {
|
|
39
|
+
this.port = await getPort({ port: 3100 });
|
|
40
|
+
return {
|
|
41
|
+
define: {
|
|
42
|
+
"import.meta.env.REBUNDLE_PORT": JSON.stringify(this.port)
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
onConfigResolved = async (config) => {
|
|
47
|
+
this.config = config;
|
|
48
|
+
const info = this.config.logger.info;
|
|
49
|
+
this.config.logger.info = (message, options) => {
|
|
50
|
+
const path = message.split(/\s+/)[0];
|
|
51
|
+
if (extname(path) === ".js") return;
|
|
52
|
+
info(message, options);
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
onBuildEnd = (error) => {
|
|
56
|
+
this.hasError = !!error;
|
|
57
|
+
};
|
|
58
|
+
onWriteBundle = async (_output, bundle) => {
|
|
59
|
+
if (this.hasError) return;
|
|
60
|
+
if (!this.config) throw this.never;
|
|
61
|
+
const chunks = Object.values(bundle).filter((chunkOrAsset) => chunkOrAsset.type === "chunk");
|
|
62
|
+
const entryChunks = chunks.filter((chunk) => chunk.isEntry);
|
|
63
|
+
const nonEntryChunks = chunks.filter((chunk) => !chunk.isEntry);
|
|
64
|
+
const modifiedChunkNames = [];
|
|
65
|
+
await Promise.all(
|
|
66
|
+
entryChunks.map(async (chunk) => {
|
|
67
|
+
const modified = await this.rebundleChunk(chunk, bundle);
|
|
68
|
+
if (modified) modifiedChunkNames.push(chunk.name);
|
|
69
|
+
})
|
|
70
|
+
);
|
|
71
|
+
for (const chunk of nonEntryChunks) {
|
|
72
|
+
await this.removeChunk(chunk, bundle);
|
|
73
|
+
}
|
|
74
|
+
if (this.config.build.watch && modifiedChunkNames.length > 0) {
|
|
75
|
+
const ws = await this.ensureWs();
|
|
76
|
+
ws.clients.forEach((client) => client.send(JSON.stringify(modifiedChunkNames)));
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// CHUNK METHODS
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
async rebundleChunk(chunk, bundle) {
|
|
83
|
+
if (!this.config) throw this.never;
|
|
84
|
+
delete bundle[chunk.fileName];
|
|
85
|
+
const chunkPath = join(this.dist, chunk.fileName);
|
|
86
|
+
const chunkOptions = this.options[chunk.name] ?? {};
|
|
87
|
+
const chunkFiles = await this.readChunkFiles(chunk);
|
|
88
|
+
const chunkFilePaths = Object.keys(chunkFiles);
|
|
89
|
+
const chunkModified = chunkFilePaths.some((path) => chunkFiles[path] !== this.originalFiles[path]);
|
|
90
|
+
if (!chunkModified) {
|
|
91
|
+
const code2 = this.rebundledFiles[chunk.fileName];
|
|
92
|
+
await this.writeToDist(chunk.fileName, code2);
|
|
93
|
+
if (chunk.sourcemapFileName) {
|
|
94
|
+
const sourcemap = this.rebundledFiles[chunk.sourcemapFileName];
|
|
95
|
+
if (sourcemap) await this.writeToDist(chunk.sourcemapFileName, sourcemap);
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
const build = await rolldown({ ...chunkOptions.input, input: chunkPath });
|
|
101
|
+
await build.write({ sourcemap: !!this.config.build.sourcemap, ...chunkOptions.output, file: chunkPath });
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.error(error);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const { size } = await stat(chunkPath);
|
|
107
|
+
const _dist_ = chalk.dim(`${this.dist}/`);
|
|
108
|
+
const _fileName_ = chalk.cyan(chunk.fileName);
|
|
109
|
+
const _rebundle_ = chalk.dim.cyan("[rebundle]");
|
|
110
|
+
const _size_ = chalk.bold.dim(`${filesize(size)}`);
|
|
111
|
+
console.log(`${_dist_}${_fileName_} ${_rebundle_} ${_size_}`);
|
|
112
|
+
const code = await this.readFromDist(chunk.fileName);
|
|
113
|
+
if (!code) throw this.never;
|
|
114
|
+
this.rebundledFiles[chunk.fileName] = code;
|
|
115
|
+
if (chunk.sourcemapFileName) {
|
|
116
|
+
const sourcemap = await this.readFromDist(chunk.sourcemapFileName);
|
|
117
|
+
if (sourcemap) this.rebundledFiles[chunk.sourcemapFileName] = sourcemap;
|
|
118
|
+
}
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
async removeChunk(chunk, bundle) {
|
|
122
|
+
await this.removeFromDist(chunk.fileName);
|
|
123
|
+
delete bundle[chunk.fileName];
|
|
124
|
+
if (chunk.sourcemapFileName) {
|
|
125
|
+
await this.removeFromDist(chunk.sourcemapFileName);
|
|
126
|
+
delete bundle[chunk.sourcemapFileName];
|
|
127
|
+
}
|
|
128
|
+
const dir = dirname(join(this.dist, chunk.fileName));
|
|
129
|
+
await this.removeDirectoryIfEmpty(dir);
|
|
130
|
+
}
|
|
131
|
+
async readChunkFiles(chunk) {
|
|
132
|
+
const files = {};
|
|
133
|
+
const usedPaths = [chunk.fileName, ...chunk.imports];
|
|
134
|
+
await Promise.all(
|
|
135
|
+
usedPaths.map(async (path) => {
|
|
136
|
+
const content = await this.readFromDist(path);
|
|
137
|
+
files[path] = content ?? "";
|
|
138
|
+
})
|
|
139
|
+
);
|
|
140
|
+
return files;
|
|
141
|
+
}
|
|
142
|
+
// ---------------------------------------------------------------------------
|
|
143
|
+
// HELPERS
|
|
144
|
+
// ---------------------------------------------------------------------------
|
|
145
|
+
get dist() {
|
|
146
|
+
if (!this.config) throw this.never;
|
|
147
|
+
return this.config.build.outDir;
|
|
148
|
+
}
|
|
149
|
+
async readFromDist(path) {
|
|
150
|
+
const [content] = await safe(readFile(join(this.dist, path), "utf-8"));
|
|
151
|
+
return content;
|
|
152
|
+
}
|
|
153
|
+
async writeToDist(path, content) {
|
|
154
|
+
await writeFile(join(this.dist, path), content, "utf-8");
|
|
155
|
+
}
|
|
156
|
+
async removeFromDist(path) {
|
|
157
|
+
await safe(unlink(join(this.dist, path)));
|
|
158
|
+
}
|
|
159
|
+
async ensureWs() {
|
|
160
|
+
if (this.ws) return this.ws;
|
|
161
|
+
if (!this.port) throw this.never;
|
|
162
|
+
this.ws = new WebSocketServer({ port: this.port });
|
|
163
|
+
return this.ws;
|
|
164
|
+
}
|
|
165
|
+
async removeDirectoryIfEmpty(dir) {
|
|
166
|
+
const files = await readdir(dir);
|
|
167
|
+
if (files.length > 0) return;
|
|
168
|
+
await rmdir(dir);
|
|
169
|
+
await this.removeDirectoryIfEmpty(dirname(dir));
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
function rebundle(options = {}) {
|
|
173
|
+
return new Rebundle(options).vite;
|
|
174
|
+
}
|
|
175
|
+
var rebundle_default = rebundle;
|
|
176
|
+
export {
|
|
177
|
+
Rebundle,
|
|
178
|
+
_code_,
|
|
179
|
+
_sourcemap_,
|
|
180
|
+
rebundle_default as default,
|
|
181
|
+
rebundle
|
|
182
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-rebundle",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "imkost",
|
|
@@ -10,24 +10,31 @@
|
|
|
10
10
|
"vite-plugin"
|
|
11
11
|
],
|
|
12
12
|
"scripts": {
|
|
13
|
+
"build": "tsup src --format esm --dts --clean",
|
|
13
14
|
"lint": "tsc --noEmit",
|
|
14
|
-
"release": "sh -c 'npm version ${1:-patch} && npm publish' --"
|
|
15
|
+
"release": "sh -c 'npm version ${1:-patch} && npm run build && npm publish' --"
|
|
15
16
|
},
|
|
16
17
|
"exports": {
|
|
17
|
-
"
|
|
18
|
+
".": {
|
|
19
|
+
"import": "./dist/rebundle.js"
|
|
20
|
+
},
|
|
21
|
+
"./ts": {
|
|
22
|
+
"import": "./src/rebundle.ts"
|
|
23
|
+
}
|
|
18
24
|
},
|
|
19
25
|
"files": [
|
|
20
|
-
"src"
|
|
26
|
+
"src",
|
|
27
|
+
"dist"
|
|
21
28
|
],
|
|
22
29
|
"dependencies": {
|
|
23
|
-
"@eposlabs/utils": "^1.
|
|
30
|
+
"@eposlabs/utils": "^1.1.1",
|
|
24
31
|
"@types/ws": "^8.18.1",
|
|
25
32
|
"chalk": "^5.6.2",
|
|
26
|
-
"filesize": "^11.0.
|
|
33
|
+
"filesize": "^11.0.13",
|
|
27
34
|
"portfinder": "^1.0.38",
|
|
28
35
|
"rolldown": "^1.0.0-beta.40",
|
|
29
|
-
"rollup": "^4.
|
|
30
|
-
"vite": "^7.1.
|
|
36
|
+
"rollup": "^4.52.2",
|
|
37
|
+
"vite": "^7.1.7",
|
|
31
38
|
"ws": "^8.18.3"
|
|
32
39
|
}
|
|
33
40
|
}
|
package/src/rebundle.ts
CHANGED
|
@@ -12,11 +12,13 @@ import { WebSocketServer } from 'ws'
|
|
|
12
12
|
export const _code_ = Symbol('rebundle:code')
|
|
13
13
|
export const _sourcemap_ = Symbol('rebundle:sourcemap')
|
|
14
14
|
|
|
15
|
+
export type RolldownOptions = {
|
|
16
|
+
input: InputOptions
|
|
17
|
+
output: OutputOptions
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
export type Options = {
|
|
16
|
-
[bundleName: string]:
|
|
17
|
-
input: InputOptions
|
|
18
|
-
output: OutputOptions
|
|
19
|
-
}
|
|
21
|
+
[bundleName: string]: RolldownOptions
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
export class Rebundle extends Unit {
|
|
@@ -234,3 +236,9 @@ export class Rebundle extends Unit {
|
|
|
234
236
|
await this.removeDirectoryIfEmpty(dirname(dir))
|
|
235
237
|
}
|
|
236
238
|
}
|
|
239
|
+
|
|
240
|
+
export function rebundle(options: Options = {}) {
|
|
241
|
+
return new Rebundle(options).vite
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export default rebundle
|