vite-plugin-rebundle 1.2.7 → 1.2.8

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.
@@ -1,6 +1,9 @@
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
  };
@@ -19,12 +22,15 @@ export declare class Rebundle extends $utils.Unit {
19
22
  private onConfigResolved;
20
23
  private onBuildEnd;
21
24
  private onWriteBundle;
22
- private get outDir();
23
- private outPath;
24
- private outRead;
25
- private outWrite;
25
+ rebundleChunk(chunk: OutputChunk, bundle: OutputBundle): Promise<boolean | undefined>;
26
+ private removeChunk;
27
+ private readChunkFiles;
28
+ private get dist();
29
+ private resolve;
30
+ private read;
31
+ private write;
32
+ private remove;
26
33
  private ensureWs;
27
34
  private getOptions;
28
- private readChunkFiles;
29
35
  private removeDirectoryIfEmpty;
30
36
  }
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,119 +60,138 @@ 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 options = await this.getOptions();
95
+ const chunkPath = this.resolve(chunk.fileName);
96
+ const chunkBuildOptions = options[chunk.name] ?? {};
97
+ const chunkFiles = await this.readChunkFiles(chunk);
98
+ const chunkFilePaths = Object.keys(chunkFiles);
99
+ const chunkChanged = chunkFilePaths.some(path => chunkFiles[path] !== this.chunkFiles[path]);
100
+ // Update files cache
101
+ Object.assign(this.chunkFiles, chunkFiles);
102
+ // Not modified? -> Use pervious content
103
+ if (!chunkChanged) {
104
+ // Overwrite vite's code
105
+ const code = this.rebundledContent[chunk.fileName];
106
+ await this.write(chunk.fileName, code);
107
+ // Overwrite vite's sourcemap
135
108
  if (chunk.sourcemapFileName) {
136
- await $utils.safe($fs.unlink(this.outPath(chunk.sourcemapFileName)));
137
- delete bundle[chunk.sourcemapFileName];
109
+ const sourcemap = this.rebundledContent[chunk.sourcemapFileName];
110
+ if (sourcemap)
111
+ await this.write(chunk.sourcemapFileName, sourcemap);
138
112
  }
139
- // Remove containing directory if empty (recursively)
140
- const dir = $path.dirname(this.outPath(chunk.fileName));
141
- await this.removeDirectoryIfEmpty(dir);
113
+ return false;
142
114
  }
143
- // Notify about changed chunks
144
- if (ws && changedChunkNames.length > 0) {
145
- ws.clients.forEach(client => client.send(JSON.stringify(changedChunkNames)));
115
+ // Build with esbuild
116
+ const result = await $esbuild.build({
117
+ sourcemap: Boolean(this.config.build.sourcemap),
118
+ ...chunkBuildOptions,
119
+ outfile: chunkPath,
120
+ entryPoints: [chunkPath],
121
+ bundle: true,
122
+ allowOverwrite: true,
123
+ });
124
+ // Errors? -> Ignore, esbuild will show errors in console
125
+ if (result.errors.length > 0)
126
+ return;
127
+ // Log successful build
128
+ const { size } = await $fs.stat(chunkPath);
129
+ const _dist_ = $chalk.dim(`${this.dist}/`);
130
+ const _fileName_ = $chalk.cyan(chunk.fileName);
131
+ const _rebundle_ = $chalk.dim.cyan('[rebundle]');
132
+ const _size_ = $chalk.bold.dim(`${filesize(size)}`);
133
+ console.log(`${_dist_}${_fileName_} ${_rebundle_} ${_size_}`);
134
+ // Save code
135
+ const code = await this.read(chunk.fileName);
136
+ if (!code)
137
+ throw this.never;
138
+ this.rebundledContent[chunk.fileName] = code;
139
+ // Save sourcemap
140
+ if (chunk.sourcemapFileName) {
141
+ const sourcemap = await this.read(chunk.sourcemapFileName);
142
+ if (sourcemap)
143
+ this.rebundledContent[chunk.sourcemapFileName] = sourcemap;
146
144
  }
147
- };
145
+ return true;
146
+ }
147
+ async removeChunk(chunk, bundle) {
148
+ await this.remove(chunk.fileName);
149
+ delete bundle[chunk.fileName];
150
+ if (chunk.sourcemapFileName) {
151
+ await this.remove(chunk.sourcemapFileName);
152
+ delete bundle[chunk.sourcemapFileName];
153
+ }
154
+ // Recursively remove containing directory if empty
155
+ const dir = $path.dirname(this.resolve(chunk.fileName));
156
+ await this.removeDirectoryIfEmpty(dir);
157
+ }
158
+ async readChunkFiles(chunk) {
159
+ const files = {};
160
+ const usedPaths = [chunk.fileName, ...chunk.imports];
161
+ await Promise.all(usedPaths.map(async (path) => {
162
+ const content = await this.read(path);
163
+ if (!content)
164
+ throw this.never;
165
+ files[path] = content;
166
+ }));
167
+ return files;
168
+ }
148
169
  // ---------------------------------------------------------------------------
149
170
  // HELPERS
150
171
  // ---------------------------------------------------------------------------
151
- get outDir() {
172
+ get dist() {
152
173
  if (!this.config)
153
174
  throw this.never;
154
175
  return this.config.build.outDir;
155
176
  }
156
- outPath(path) {
157
- return $path.join(this.outDir, path);
177
+ resolve(path) {
178
+ return $path.join(this.dist, path);
158
179
  }
159
- async outRead(path) {
160
- return await $fs.readFile(this.outPath(path), 'utf-8');
180
+ async read(path) {
181
+ const [content] = await $utils.safe($fs.readFile(this.resolve(path), 'utf-8'));
182
+ return content;
161
183
  }
162
- async outWrite(path, content) {
163
- await $fs.writeFile(this.outPath(path), content, 'utf-8');
184
+ async write(path, content) {
185
+ await $fs.writeFile(this.resolve(path), content, 'utf-8');
186
+ }
187
+ async remove(path) {
188
+ await $utils.safe($fs.unlink(this.resolve(path)));
164
189
  }
165
190
  async ensureWs() {
166
191
  if (this.ws)
167
192
  return this.ws;
168
193
  if (!this.port)
169
194
  throw this.never;
170
- if (!this.config)
171
- throw this.never;
172
- if (!this.config.build.watch)
173
- return null;
174
195
  this.ws = new $ws.WebSocketServer({ port: this.port });
175
196
  return this.ws;
176
197
  }
@@ -179,13 +200,6 @@ export class Rebundle extends $utils.Unit {
179
200
  return this.options;
180
201
  return await this.options();
181
202
  }
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
203
  async removeDirectoryIfEmpty(dir) {
190
204
  const files = await $fs.readdir(dir);
191
205
  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.8",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "author": "imkost",