vite-plugin-rebundle 1.2.7 → 1.2.10

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 CHANGED
@@ -1,2 +1,2 @@
1
- import { type OptionsInput } from './rebundle.js';
2
- export default function rebundle(options?: OptionsInput): import("vite").Plugin<any>;
1
+ import { type Options } from './rebundle.js';
2
+ export default function rebundle(options?: Options): import("vite").Plugin<any>;
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Rebundle } from './rebundle.js';
2
2
  export default function rebundle(options = {}) {
3
- return new Rebundle(options).vite;
3
+ const rb = new Rebundle(options);
4
+ return rb.vite;
4
5
  }
@@ -1,10 +1,12 @@
1
1
  import * as $utils from '@eposlabs/utils';
2
2
  import type { BuildOptions } from 'esbuild';
3
+ import type { OutputBundle, OutputChunk } from 'rollup';
3
4
  import type { Plugin } from 'vite';
5
+ export declare const _code_: unique symbol;
6
+ export declare const _sourcemap_: unique symbol;
4
7
  export type Options = {
5
8
  [chunkName: string]: BuildOptions;
6
9
  };
7
- export type OptionsInput = Options | (() => Options | Promise<Options>);
8
10
  export declare class Rebundle extends $utils.Unit {
9
11
  private options;
10
12
  private config;
@@ -13,18 +15,20 @@ export declare class Rebundle extends $utils.Unit {
13
15
  private hasError;
14
16
  private port;
15
17
  private ws;
16
- constructor(options: OptionsInput);
18
+ constructor(options: Options);
17
19
  get vite(): Plugin;
18
20
  private onConfig;
19
21
  private onConfigResolved;
20
22
  private onBuildEnd;
21
23
  private onWriteBundle;
22
- private get outDir();
23
- private outPath;
24
- private outRead;
25
- private outWrite;
26
- private ensureWs;
27
- private getOptions;
24
+ rebundleChunk(chunk: OutputChunk, bundle: OutputBundle): Promise<boolean | undefined>;
25
+ private removeChunk;
28
26
  private readChunkFiles;
27
+ private get dist();
28
+ private resolve;
29
+ private read;
30
+ private write;
31
+ private remove;
32
+ private ensureWs;
29
33
  private removeDirectoryIfEmpty;
30
34
  }
package/dist/rebundle.js CHANGED
@@ -6,6 +6,8 @@ import * as $utils from '@eposlabs/utils';
6
6
  import * as $ws from 'ws';
7
7
  import $chalk from 'chalk';
8
8
  import $portfinder from 'portfinder';
9
+ export const _code_ = Symbol('rebundle:code');
10
+ export const _sourcemap_ = Symbol('rebundle:sourcemap');
9
11
  export class Rebundle extends $utils.Unit {
10
12
  options;
11
13
  config = null;
@@ -30,7 +32,7 @@ export class Rebundle extends $utils.Unit {
30
32
  };
31
33
  }
32
34
  // ---------------------------------------------------------------------------
33
- // HOOKS
35
+ // VITE HOOKS
34
36
  // ---------------------------------------------------------------------------
35
37
  onConfig = async () => {
36
38
  this.port = await $portfinder.getPort({ port: 3100 });
@@ -43,7 +45,7 @@ export class Rebundle extends $utils.Unit {
43
45
  onConfigResolved = async (config) => {
44
46
  // Save resolved config
45
47
  this.config = config;
46
- // Hide .js files from output logs (rollup only, not supported in rolldown)
48
+ // Hide js files from output logs (rollup only, not supported in rolldown)
47
49
  const info = this.config.logger.info;
48
50
  this.config.logger.info = (message, options) => {
49
51
  const path = message.split(/\s+/)[0];
@@ -58,134 +60,140 @@ export class Rebundle extends $utils.Unit {
58
60
  onWriteBundle = async (_output, bundle) => {
59
61
  if (this.hasError)
60
62
  return;
61
- const ws = await this.ensureWs();
62
- const options = await this.getOptions();
63
- const changedChunkNames = [];
64
- // Get entry js chunks
65
- const entryJsChunks = Object.values(bundle)
66
- .filter(chunkOrAsset => chunkOrAsset.type === 'chunk')
67
- .filter(chunk => chunk.isEntry && $path.extname(chunk.fileName) === '.js');
68
- // Rebundle entry js chunks with esbuild
69
- await Promise.all(entryJsChunks.map(async (chunk) => {
70
- if (!this.config)
71
- throw this.never;
72
- // Delete chunk from bundle to hide log in vite-rolldown.
73
- // Call for rollup as well for consistency.
74
- delete bundle[chunk.fileName];
75
- const chunkPath = this.outPath(chunk.fileName);
76
- const chunkBuildOptions = options[chunk.name] ?? {};
77
- const chunkFiles = await this.readChunkFiles(chunk);
78
- const chunkFilePaths = Object.keys(chunkFiles);
79
- const chunkChanged = chunkFilePaths.some(path => chunkFiles[path] !== this.chunkFiles[path]);
80
- // Update files cache
81
- Object.assign(this.chunkFiles, chunkFiles);
82
- // Modified? -> Rebundle
83
- if (chunkChanged) {
84
- // Build with esbuild
85
- const result = await $esbuild.build({
86
- sourcemap: Boolean(this.config.build.sourcemap),
87
- ...chunkBuildOptions,
88
- outfile: chunkPath,
89
- entryPoints: [chunkPath],
90
- bundle: true,
91
- minify: false,
92
- keepNames: true,
93
- allowOverwrite: true,
94
- });
95
- if (result.errors.length > 0)
96
- return;
97
- // Log successful build
98
- const { size } = await $fs.stat(chunkPath);
99
- const _outDir_ = $chalk.dim(`${this.outDir}/`);
100
- const _fileName_ = $chalk.cyan(chunk.fileName);
101
- const _rebundle_ = $chalk.dim.cyan('[rebundle]');
102
- const _size_ = $chalk.bold.dim(`${filesize(size)}`);
103
- console.log(`${_outDir_}${_fileName_} ${_rebundle_} ${_size_}`);
104
- // Mark chunk as changed
105
- changedChunkNames.push(chunk.name);
106
- // Save chunk content
107
- this.rebundledContent[chunk.fileName] = await this.outRead(chunk.fileName);
108
- // Save sourcemap content
109
- if (chunk.sourcemapFileName) {
110
- this.rebundledContent[chunk.sourcemapFileName] = await this.outRead(chunk.sourcemapFileName);
111
- }
112
- }
113
- // Overwrite chunk
114
- await this.outWrite(chunk.fileName, this.rebundledContent[chunk.fileName]);
115
- chunk.code = this.rebundledContent[chunk.fileName];
116
- // Overwrite sourcemap
117
- if (chunk.sourcemapFileName) {
118
- const sourcemapAsset = bundle[chunk.sourcemapFileName];
119
- if (sourcemapAsset.type !== 'asset')
120
- throw this.never;
121
- await this.outWrite(chunk.sourcemapFileName, this.rebundledContent[chunk.sourcemapFileName]);
122
- sourcemapAsset.source = this.rebundledContent[chunk.sourcemapFileName];
123
- }
63
+ if (!this.config)
64
+ throw this.never;
65
+ const chunks = Object.values(bundle).filter(chunkOrAsset => chunkOrAsset.type === 'chunk');
66
+ const entryChunks = chunks.filter(chunk => chunk.isEntry);
67
+ const nonEntryChunks = chunks.filter(chunk => !chunk.isEntry);
68
+ // Rebundle entry chunks
69
+ const modifiedChunkNames = [];
70
+ await Promise.all(entryChunks.map(async (chunk) => {
71
+ const modified = await this.rebundleChunk(chunk, bundle);
72
+ if (modified)
73
+ modifiedChunkNames.push(chunk.name);
124
74
  }));
125
- // Get non-entry chunks (.js, .js.map)
126
- const nonEntryChunks = Object.values(bundle)
127
- .filter(chunkOrAsset => chunkOrAsset.type === 'chunk')
128
- .filter(chunk => !chunk.isEntry);
129
- // Remove all non-entry chunks
75
+ // Remove non-entry chunks
130
76
  for (const chunk of nonEntryChunks) {
131
- // Remove chunk
132
- await $utils.safe($fs.unlink(this.outPath(chunk.fileName)));
133
- delete bundle[chunk.fileName];
134
- // Remove sourcemap
77
+ await this.removeChunk(chunk, bundle);
78
+ }
79
+ // Notify about modified chunks
80
+ if (this.config.build.watch && modifiedChunkNames.length > 0) {
81
+ const ws = await this.ensureWs();
82
+ ws.clients.forEach(client => client.send(JSON.stringify(modifiedChunkNames)));
83
+ }
84
+ };
85
+ // ---------------------------------------------------------------------------
86
+ // CHUNK METHODS
87
+ // ---------------------------------------------------------------------------
88
+ async rebundleChunk(chunk, bundle) {
89
+ if (!this.config)
90
+ throw this.never;
91
+ // Delete chunk from bundle to hide log for vite-rolldown.
92
+ // Call for rollup as well for consistency.
93
+ delete bundle[chunk.fileName];
94
+ const chunkPath = this.resolve(chunk.fileName);
95
+ const chunkBuildOptions = this.options[chunk.name] ?? {};
96
+ const chunkFiles = await this.readChunkFiles(chunk);
97
+ const chunkFilePaths = Object.keys(chunkFiles);
98
+ const chunkChanged = chunkFilePaths.some(path => chunkFiles[path] !== this.chunkFiles[path]);
99
+ // Update files cache
100
+ Object.assign(this.chunkFiles, chunkFiles);
101
+ // Not modified? -> Use pervious content
102
+ if (!chunkChanged) {
103
+ // Overwrite vite's code
104
+ const code = this.rebundledContent[chunk.fileName];
105
+ await this.write(chunk.fileName, code);
106
+ // Overwrite vite's sourcemap
135
107
  if (chunk.sourcemapFileName) {
136
- await $utils.safe($fs.unlink(this.outPath(chunk.sourcemapFileName)));
137
- delete bundle[chunk.sourcemapFileName];
108
+ const sourcemap = this.rebundledContent[chunk.sourcemapFileName];
109
+ if (sourcemap)
110
+ await this.write(chunk.sourcemapFileName, sourcemap);
138
111
  }
139
- // Remove containing directory if empty (recursively)
140
- const dir = $path.dirname(this.outPath(chunk.fileName));
141
- await this.removeDirectoryIfEmpty(dir);
112
+ return false;
142
113
  }
143
- // Notify about changed chunks
144
- if (ws && changedChunkNames.length > 0) {
145
- ws.clients.forEach(client => client.send(JSON.stringify(changedChunkNames)));
114
+ // Build with esbuild
115
+ const result = await $esbuild.build({
116
+ sourcemap: Boolean(this.config.build.sourcemap),
117
+ ...chunkBuildOptions,
118
+ outfile: chunkPath,
119
+ entryPoints: [chunkPath],
120
+ bundle: true,
121
+ allowOverwrite: true,
122
+ });
123
+ // Errors? -> Ignore, esbuild will show errors in console
124
+ if (result.errors.length > 0)
125
+ return;
126
+ // Log successful build
127
+ const { size } = await $fs.stat(chunkPath);
128
+ const _dist_ = $chalk.dim(`${this.dist}/`);
129
+ const _fileName_ = $chalk.cyan(chunk.fileName);
130
+ const _rebundle_ = $chalk.dim.cyan('[rebundle]');
131
+ const _size_ = $chalk.bold.dim(`${filesize(size)}`);
132
+ console.log(`${_dist_}${_fileName_} ${_rebundle_} ${_size_}`);
133
+ // Save code
134
+ const code = await this.read(chunk.fileName);
135
+ if (!code)
136
+ throw this.never;
137
+ this.rebundledContent[chunk.fileName] = code;
138
+ // Save sourcemap
139
+ if (chunk.sourcemapFileName) {
140
+ const sourcemap = await this.read(chunk.sourcemapFileName);
141
+ if (sourcemap)
142
+ this.rebundledContent[chunk.sourcemapFileName] = sourcemap;
146
143
  }
147
- };
144
+ return true;
145
+ }
146
+ async removeChunk(chunk, bundle) {
147
+ await this.remove(chunk.fileName);
148
+ delete bundle[chunk.fileName];
149
+ if (chunk.sourcemapFileName) {
150
+ await this.remove(chunk.sourcemapFileName);
151
+ delete bundle[chunk.sourcemapFileName];
152
+ }
153
+ // Recursively remove containing directory if empty
154
+ const dir = $path.dirname(this.resolve(chunk.fileName));
155
+ await this.removeDirectoryIfEmpty(dir);
156
+ }
157
+ async readChunkFiles(chunk) {
158
+ const files = {};
159
+ const usedPaths = [chunk.fileName, ...chunk.imports];
160
+ await Promise.all(usedPaths.map(async (path) => {
161
+ const content = await this.read(path);
162
+ if (!content)
163
+ throw this.never;
164
+ files[path] = content;
165
+ }));
166
+ return files;
167
+ }
148
168
  // ---------------------------------------------------------------------------
149
169
  // HELPERS
150
170
  // ---------------------------------------------------------------------------
151
- get outDir() {
171
+ get dist() {
152
172
  if (!this.config)
153
173
  throw this.never;
154
174
  return this.config.build.outDir;
155
175
  }
156
- outPath(path) {
157
- return $path.join(this.outDir, path);
176
+ resolve(path) {
177
+ return $path.join(this.dist, path);
178
+ }
179
+ async read(path) {
180
+ const [content] = await $utils.safe($fs.readFile(this.resolve(path), 'utf-8'));
181
+ return content;
158
182
  }
159
- async outRead(path) {
160
- return await $fs.readFile(this.outPath(path), 'utf-8');
183
+ async write(path, content) {
184
+ await $fs.writeFile(this.resolve(path), content, 'utf-8');
161
185
  }
162
- async outWrite(path, content) {
163
- await $fs.writeFile(this.outPath(path), content, 'utf-8');
186
+ async remove(path) {
187
+ await $utils.safe($fs.unlink(this.resolve(path)));
164
188
  }
165
189
  async ensureWs() {
166
190
  if (this.ws)
167
191
  return this.ws;
168
192
  if (!this.port)
169
193
  throw this.never;
170
- if (!this.config)
171
- throw this.never;
172
- if (!this.config.build.watch)
173
- return null;
174
194
  this.ws = new $ws.WebSocketServer({ port: this.port });
175
195
  return this.ws;
176
196
  }
177
- async getOptions() {
178
- if (typeof this.options !== 'function')
179
- return this.options;
180
- return await this.options();
181
- }
182
- async readChunkFiles(chunk) {
183
- const files = {};
184
- await Promise.all([chunk.fileName, ...chunk.imports].map(async (path) => {
185
- files[path] = await this.outRead(path);
186
- }));
187
- return files;
188
- }
189
197
  async removeDirectoryIfEmpty(dir) {
190
198
  const files = await $fs.readdir(dir);
191
199
  if (files.length > 0)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-rebundle",
3
- "version": "1.2.7",
3
+ "version": "1.2.10",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "author": "imkost",