vite-plugin-rebundle 1.0.0 → 1.1.1
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/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/rebundle.d.ts +15 -16
- package/dist/rebundle.js +93 -97
- package/package.json +9 -9
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
export default function rebundle(options?:
|
|
1
|
+
import { type OptionsInput } from './rebundle.js';
|
|
2
|
+
export default function rebundle(options?: OptionsInput): import("vite").Plugin<any>;
|
package/dist/index.js
CHANGED
package/dist/rebundle.d.ts
CHANGED
|
@@ -1,25 +1,24 @@
|
|
|
1
|
+
import * as $utils from '@eposlabs/utils';
|
|
1
2
|
import type { BuildOptions } from 'esbuild';
|
|
2
3
|
import type { Plugin } from 'vite';
|
|
3
|
-
export type Options =
|
|
4
|
-
|
|
5
|
-
[chunkName: string]: BuildOptions;
|
|
6
|
-
};
|
|
4
|
+
export type Options = {
|
|
5
|
+
[chunkName: string]: BuildOptions;
|
|
7
6
|
};
|
|
8
|
-
export type
|
|
9
|
-
|
|
10
|
-
};
|
|
11
|
-
export declare class Rebundle {
|
|
7
|
+
export type OptionsInput = Options | (() => Options | Promise<Options>);
|
|
8
|
+
export declare class Rebundle extends $utils.Unit {
|
|
12
9
|
private options;
|
|
13
10
|
private config;
|
|
14
|
-
private
|
|
15
|
-
private
|
|
16
|
-
constructor(options:
|
|
17
|
-
get
|
|
18
|
-
private onConfig;
|
|
11
|
+
private chunkFiles;
|
|
12
|
+
private rebundledContent;
|
|
13
|
+
constructor(options: OptionsInput);
|
|
14
|
+
get vite(): Plugin;
|
|
19
15
|
private onConfigResolved;
|
|
20
16
|
private onWriteBundle;
|
|
21
17
|
private get outDir();
|
|
22
|
-
private
|
|
23
|
-
private
|
|
24
|
-
private
|
|
18
|
+
private outPath;
|
|
19
|
+
private outRead;
|
|
20
|
+
private outWrite;
|
|
21
|
+
private getOptions;
|
|
22
|
+
private readChunkFiles;
|
|
23
|
+
private removeDirectoryIfEmpty;
|
|
25
24
|
}
|
package/dist/rebundle.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import $chalk from 'chalk';
|
|
2
1
|
import * as $esbuild from 'esbuild';
|
|
3
|
-
import * as $merge from 'merge-anything';
|
|
4
2
|
import * as $fs from 'node:fs/promises';
|
|
5
3
|
import * as $path from 'node:path';
|
|
6
|
-
|
|
4
|
+
import * as $utils from '@eposlabs/utils';
|
|
5
|
+
import $chalk from 'chalk';
|
|
6
|
+
export class Rebundle extends $utils.Unit {
|
|
7
7
|
options;
|
|
8
8
|
config = null;
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
chunkFiles = {};
|
|
10
|
+
rebundledContent = {};
|
|
11
11
|
constructor(options) {
|
|
12
|
+
super();
|
|
12
13
|
this.options = options;
|
|
13
14
|
}
|
|
14
|
-
get
|
|
15
|
+
get vite() {
|
|
15
16
|
return {
|
|
16
17
|
name: 'vite-plugin-rebundle',
|
|
17
18
|
apply: 'build',
|
|
18
19
|
enforce: 'post',
|
|
19
|
-
config: this.onConfig,
|
|
20
20
|
configResolved: this.onConfigResolved,
|
|
21
21
|
writeBundle: this.onWriteBundle,
|
|
22
22
|
};
|
|
@@ -24,23 +24,9 @@ export class Rebundle {
|
|
|
24
24
|
// ---------------------------------------------------------------------------
|
|
25
25
|
// HOOKS
|
|
26
26
|
// ---------------------------------------------------------------------------
|
|
27
|
-
onConfig = (config) => {
|
|
28
|
-
// Save user's `emptyOutDir` value
|
|
29
|
-
this.emptyOutDir = config.build?.emptyOutDir ?? true;
|
|
30
|
-
// Make `emptyOutDir = false` to prevent Vite from deleting rebundled output files
|
|
31
|
-
return {
|
|
32
|
-
build: {
|
|
33
|
-
emptyOutDir: false,
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
};
|
|
37
27
|
onConfigResolved = async (config) => {
|
|
38
28
|
// Save resolved config
|
|
39
29
|
this.config = config;
|
|
40
|
-
// Cleanup output directory if user's `emptyOutDir` is `true`
|
|
41
|
-
if (this.emptyOutDir) {
|
|
42
|
-
await $fs.rmdir(this.outDir, { recursive: true });
|
|
43
|
-
}
|
|
44
30
|
// Hide .js files from output logs
|
|
45
31
|
const info = this.config.logger.info;
|
|
46
32
|
this.config.logger.info = (message, options) => {
|
|
@@ -51,87 +37,86 @@ export class Rebundle {
|
|
|
51
37
|
};
|
|
52
38
|
};
|
|
53
39
|
onWriteBundle = async (output, bundle) => {
|
|
40
|
+
const options = await this.getOptions();
|
|
54
41
|
// Get entry js chunks
|
|
55
42
|
const entryJsChunks = Object.values(bundle)
|
|
56
43
|
.filter(chunkOrAsset => chunkOrAsset.type === 'chunk')
|
|
57
44
|
.filter(chunk => chunk.isEntry && $path.extname(chunk.fileName) === '.js');
|
|
58
|
-
// Get non-entry chunks (.js, .js.map)
|
|
59
|
-
const nonEntryChunks = Object.values(bundle)
|
|
60
|
-
.filter(chunkOrAsset => chunkOrAsset.type === 'chunk')
|
|
61
|
-
.filter(chunk => !chunk.isEntry);
|
|
62
45
|
// Rebundle entry js chunks with esbuild
|
|
63
46
|
await Promise.all(entryJsChunks.map(async (chunk) => {
|
|
64
47
|
if (!this.config)
|
|
65
48
|
throw this.never;
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
const
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const name = $chalk.cyan(chunk.fileName);
|
|
99
|
-
const tag = $chalk.dim.cyan('rebundle');
|
|
100
|
-
console.log(`${dir}${name} ${tag}`);
|
|
101
|
-
});
|
|
49
|
+
const chunkPath = this.outPath(chunk.fileName);
|
|
50
|
+
const chunkBuildOptions = options[chunk.name] ?? {};
|
|
51
|
+
const chunkFiles = await this.readChunkFiles(chunk);
|
|
52
|
+
const chunkFilePaths = Object.keys(chunkFiles);
|
|
53
|
+
const chunkChanged = chunkFilePaths.some(path => chunkFiles[path] !== this.chunkFiles[path]);
|
|
54
|
+
// Update files cache
|
|
55
|
+
Object.assign(this.chunkFiles, chunkFiles);
|
|
56
|
+
// Modified? -> Rebundle
|
|
57
|
+
if (chunkChanged) {
|
|
58
|
+
// Build with esbuild
|
|
59
|
+
await $esbuild.build({
|
|
60
|
+
sourcemap: Boolean(this.config.build.sourcemap),
|
|
61
|
+
...chunkBuildOptions,
|
|
62
|
+
outfile: chunkPath,
|
|
63
|
+
entryPoints: [chunkPath],
|
|
64
|
+
bundle: true,
|
|
65
|
+
minify: false,
|
|
66
|
+
allowOverwrite: true,
|
|
67
|
+
plugins: [
|
|
68
|
+
...(chunkBuildOptions.plugins ?? []),
|
|
69
|
+
{
|
|
70
|
+
name: 'logger',
|
|
71
|
+
setup: build => {
|
|
72
|
+
build.onEnd(result => {
|
|
73
|
+
if (result.errors.length > 0)
|
|
74
|
+
return;
|
|
75
|
+
const outDir = $chalk.dim(`${this.outDir}/`);
|
|
76
|
+
const fileName = $chalk.cyan(chunk.fileName);
|
|
77
|
+
const rebundleTag = $chalk.dim.cyan('rebundle');
|
|
78
|
+
console.log(`${outDir}${fileName} ${rebundleTag}`);
|
|
79
|
+
});
|
|
80
|
+
},
|
|
102
81
|
},
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
82
|
+
],
|
|
83
|
+
});
|
|
84
|
+
// Save chunk content
|
|
85
|
+
this.rebundledContent[chunk.fileName] = await this.outRead(chunk.fileName);
|
|
86
|
+
// Save sourcemap content
|
|
87
|
+
if (chunk.sourcemapFileName) {
|
|
88
|
+
this.rebundledContent[chunk.sourcemapFileName] = await this.outRead(chunk.sourcemapFileName);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Overwrite chunk
|
|
92
|
+
await this.outWrite(chunk.fileName, this.rebundledContent[chunk.fileName]);
|
|
93
|
+
chunk.code = this.rebundledContent[chunk.fileName];
|
|
94
|
+
// Overwrite sourcemap
|
|
108
95
|
if (chunk.sourcemapFileName) {
|
|
109
|
-
const
|
|
110
|
-
if (
|
|
96
|
+
const sourcemapAsset = bundle[chunk.sourcemapFileName];
|
|
97
|
+
if (sourcemapAsset.type !== 'asset')
|
|
111
98
|
throw this.never;
|
|
112
|
-
|
|
113
|
-
|
|
99
|
+
await this.outWrite(chunk.sourcemapFileName, this.rebundledContent[chunk.sourcemapFileName]);
|
|
100
|
+
sourcemapAsset.source = this.rebundledContent[chunk.sourcemapFileName];
|
|
114
101
|
}
|
|
115
102
|
}));
|
|
103
|
+
// Get non-entry chunks (.js, .js.map)
|
|
104
|
+
const nonEntryChunks = Object.values(bundle)
|
|
105
|
+
.filter(chunkOrAsset => chunkOrAsset.type === 'chunk')
|
|
106
|
+
.filter(chunk => !chunk.isEntry);
|
|
116
107
|
// Remove all non-entry chunks
|
|
117
108
|
for (const chunk of nonEntryChunks) {
|
|
118
|
-
// Remove
|
|
119
|
-
|
|
120
|
-
await $fs.unlink(path);
|
|
109
|
+
// Remove chunk
|
|
110
|
+
await $fs.unlink(this.outPath(chunk.fileName));
|
|
121
111
|
delete bundle[chunk.fileName];
|
|
122
|
-
// Remove sourcemap
|
|
112
|
+
// Remove sourcemap
|
|
123
113
|
if (chunk.sourcemapFileName) {
|
|
124
|
-
|
|
125
|
-
await $fs.unlink(sourcemapPath);
|
|
114
|
+
await $fs.unlink(this.outPath(chunk.sourcemapFileName));
|
|
126
115
|
delete bundle[chunk.sourcemapFileName];
|
|
127
116
|
}
|
|
128
|
-
// Remove containing directory if empty
|
|
129
|
-
const dir = $path.dirname(
|
|
130
|
-
|
|
131
|
-
if (files.length === 0) {
|
|
132
|
-
console.warn(await $fs.stat(dir));
|
|
133
|
-
await $fs.rmdir(dir);
|
|
134
|
-
}
|
|
117
|
+
// Remove containing directory if empty (recursively)
|
|
118
|
+
const dir = $path.dirname(this.outPath(chunk.fileName));
|
|
119
|
+
await this.removeDirectoryIfEmpty(dir);
|
|
135
120
|
}
|
|
136
121
|
};
|
|
137
122
|
// ---------------------------------------------------------------------------
|
|
@@ -142,21 +127,32 @@ export class Rebundle {
|
|
|
142
127
|
throw this.never;
|
|
143
128
|
return this.config.build.outDir;
|
|
144
129
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
130
|
+
outPath(path) {
|
|
131
|
+
return $path.join(this.outDir, path);
|
|
132
|
+
}
|
|
133
|
+
async outRead(path) {
|
|
134
|
+
return await $fs.readFile(this.outPath(path), 'utf-8');
|
|
135
|
+
}
|
|
136
|
+
async outWrite(path, content) {
|
|
137
|
+
await $fs.writeFile(this.outPath(path), content, 'utf-8');
|
|
153
138
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
return
|
|
139
|
+
async getOptions() {
|
|
140
|
+
if (typeof this.options !== 'function')
|
|
141
|
+
return this.options;
|
|
142
|
+
return await this.options();
|
|
143
|
+
}
|
|
144
|
+
async readChunkFiles(chunk) {
|
|
145
|
+
const files = {};
|
|
146
|
+
await Promise.all([chunk.fileName, ...chunk.imports].map(async (path) => {
|
|
147
|
+
files[path] = await this.outRead(path);
|
|
148
|
+
}));
|
|
149
|
+
return files;
|
|
158
150
|
}
|
|
159
|
-
|
|
160
|
-
|
|
151
|
+
async removeDirectoryIfEmpty(dir) {
|
|
152
|
+
const files = await $fs.readdir(dir);
|
|
153
|
+
if (files.length > 0)
|
|
154
|
+
return;
|
|
155
|
+
await $fs.rmdir(dir);
|
|
156
|
+
await this.removeDirectoryIfEmpty($path.dirname(dir));
|
|
161
157
|
}
|
|
162
158
|
}
|
package/package.json
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-rebundle",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "imkost",
|
|
7
7
|
"description": "Vite plugin that forces single-file output per entry. Ensures each entry point is bundled into a standalone file without code-splitting.",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"vite",
|
|
10
|
+
"vite-plugin"
|
|
11
|
+
],
|
|
8
12
|
"scripts": {
|
|
9
13
|
"dev": "rm -rf dist && tsc --watch",
|
|
10
14
|
"build": "rm -rf dist && tsc",
|
|
11
15
|
"lint": "eslint src",
|
|
12
|
-
"release": "npm
|
|
13
|
-
"release:
|
|
14
|
-
"release:minor": "npm version minor && npm run release"
|
|
16
|
+
"release": "npm version patch && npm run release:raw",
|
|
17
|
+
"release:raw": "npm run build && npm publish",
|
|
18
|
+
"release:minor": "npm version minor && npm run release:raw"
|
|
15
19
|
},
|
|
16
20
|
"exports": {
|
|
17
21
|
"import": "./dist/index.js"
|
|
@@ -19,12 +23,8 @@
|
|
|
19
23
|
"files": [
|
|
20
24
|
"dist"
|
|
21
25
|
],
|
|
22
|
-
"keywords": [
|
|
23
|
-
"vite",
|
|
24
|
-
"vite-plugin"
|
|
25
|
-
],
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"chalk": "^5.6.0",
|
|
28
|
-
"
|
|
28
|
+
"esbuild": "^0.25.9"
|
|
29
29
|
}
|
|
30
30
|
}
|