wxt 0.6.1 → 0.6.3

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.cts CHANGED
@@ -2,6 +2,7 @@ import * as vite from 'vite';
2
2
  import { Manifest, Scripting } from 'webextension-polyfill';
3
3
  import { UnimportOptions } from 'unimport';
4
4
  import { LogLevel } from 'consola';
5
+ import { PluginVisualizerOptions } from 'rollup-plugin-visualizer';
5
6
 
6
7
  /**
7
8
  * Extends [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController).
@@ -31,6 +32,18 @@ declare class ContentScriptContext extends AbortController {
31
32
  * removeInvalidatedListener();
32
33
  */
33
34
  onInvalidated(cb: () => void): () => void;
35
+ /**
36
+ * Return a promise that never resolves. Useful if you have an async function that shouldn't run
37
+ * after the context is expired.
38
+ *
39
+ * @example
40
+ * const getValueFromStorage = async () => {
41
+ * if (ctx.isInvalid) return ctx.block();
42
+ *
43
+ * // ...
44
+ * }
45
+ */
46
+ block<T>(): Promise<T>;
34
47
  /**
35
48
  * Wrapper around `window.setInterval` that automatically clears the interval when invalidated.
36
49
  */
@@ -49,6 +62,18 @@ declare class ContentScriptContext extends AbortController {
49
62
  * invalidated.
50
63
  */
51
64
  requestIdleCallback(callback: IdleRequestCallback, options?: IdleRequestOptions): number;
65
+ /**
66
+ * Call `target.addEventListener` and remove the event listener when the context is invalidated.
67
+ *
68
+ * @example
69
+ * ctx.addEventListener(window, "mousemove", () => {
70
+ * // ...
71
+ * });
72
+ * ctx.addEventListener(document, "visibilitychange", () => {
73
+ * // ...
74
+ * });
75
+ */
76
+ addEventListener(target: any, type: string, handler: (event: Event) => void, options?: AddEventListenerOptions): void;
52
77
  /**
53
78
  * Abort the abort controller and execute all `onInvalidated` listeners.
54
79
  */
@@ -221,6 +246,20 @@ interface InlineConfig {
221
246
  * })
222
247
  */
223
248
  transformManifest?: (manifest: Manifest.WebExtensionManifest) => void;
249
+ analysis?: {
250
+ /**
251
+ * Explicitly include bundle analysis when running `wxt build`. This can be overridden by the
252
+ * command line `--analysis` option.
253
+ */
254
+ enabled?: boolean;
255
+ /**
256
+ * When running `wxt build --analyze` or setting `analysis.enabled` to true, customize how the
257
+ * bundle will be visualized. See
258
+ * [`rollup-plugin-visualizer`](https://github.com/btd/rollup-plugin-visualizer#how-to-use-generated-files)
259
+ * for more details.
260
+ */
261
+ template?: PluginVisualizerOptions['template'];
262
+ };
224
263
  }
225
264
  interface WxtInlineViteConfig extends Omit<vite.InlineConfig, 'root' | 'configFile' | 'mode' | 'build'> {
226
265
  build?: Omit<vite.BuildOptions, 'outDir'>;
@@ -499,7 +538,7 @@ type EntrypointGroup = Entrypoint | Entrypoint[];
499
538
  */
500
539
  declare function clean(root?: string): Promise<void>;
501
540
 
502
- var version = "0.6.1";
541
+ var version = "0.6.3";
503
542
 
504
543
  declare function defineConfig(config: UserConfig): UserConfig;
505
544
 
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import * as vite from 'vite';
2
2
  import { Manifest, Scripting } from 'webextension-polyfill';
3
3
  import { UnimportOptions } from 'unimport';
4
4
  import { LogLevel } from 'consola';
5
+ import { PluginVisualizerOptions } from 'rollup-plugin-visualizer';
5
6
 
6
7
  /**
7
8
  * Extends [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController).
@@ -31,6 +32,18 @@ declare class ContentScriptContext extends AbortController {
31
32
  * removeInvalidatedListener();
32
33
  */
33
34
  onInvalidated(cb: () => void): () => void;
35
+ /**
36
+ * Return a promise that never resolves. Useful if you have an async function that shouldn't run
37
+ * after the context is expired.
38
+ *
39
+ * @example
40
+ * const getValueFromStorage = async () => {
41
+ * if (ctx.isInvalid) return ctx.block();
42
+ *
43
+ * // ...
44
+ * }
45
+ */
46
+ block<T>(): Promise<T>;
34
47
  /**
35
48
  * Wrapper around `window.setInterval` that automatically clears the interval when invalidated.
36
49
  */
@@ -49,6 +62,18 @@ declare class ContentScriptContext extends AbortController {
49
62
  * invalidated.
50
63
  */
51
64
  requestIdleCallback(callback: IdleRequestCallback, options?: IdleRequestOptions): number;
65
+ /**
66
+ * Call `target.addEventListener` and remove the event listener when the context is invalidated.
67
+ *
68
+ * @example
69
+ * ctx.addEventListener(window, "mousemove", () => {
70
+ * // ...
71
+ * });
72
+ * ctx.addEventListener(document, "visibilitychange", () => {
73
+ * // ...
74
+ * });
75
+ */
76
+ addEventListener(target: any, type: string, handler: (event: Event) => void, options?: AddEventListenerOptions): void;
52
77
  /**
53
78
  * Abort the abort controller and execute all `onInvalidated` listeners.
54
79
  */
@@ -221,6 +246,20 @@ interface InlineConfig {
221
246
  * })
222
247
  */
223
248
  transformManifest?: (manifest: Manifest.WebExtensionManifest) => void;
249
+ analysis?: {
250
+ /**
251
+ * Explicitly include bundle analysis when running `wxt build`. This can be overridden by the
252
+ * command line `--analysis` option.
253
+ */
254
+ enabled?: boolean;
255
+ /**
256
+ * When running `wxt build --analyze` or setting `analysis.enabled` to true, customize how the
257
+ * bundle will be visualized. See
258
+ * [`rollup-plugin-visualizer`](https://github.com/btd/rollup-plugin-visualizer#how-to-use-generated-files)
259
+ * for more details.
260
+ */
261
+ template?: PluginVisualizerOptions['template'];
262
+ };
224
263
  }
225
264
  interface WxtInlineViteConfig extends Omit<vite.InlineConfig, 'root' | 'configFile' | 'mode' | 'build'> {
226
265
  build?: Omit<vite.BuildOptions, 'outDir'>;
@@ -499,7 +538,7 @@ type EntrypointGroup = Entrypoint | Entrypoint[];
499
538
  */
500
539
  declare function clean(root?: string): Promise<void>;
501
540
 
502
- var version = "0.6.1";
541
+ var version = "0.6.3";
503
542
 
504
543
  declare function defineConfig(config: UserConfig): UserConfig;
505
544
 
package/dist/index.js CHANGED
@@ -406,6 +406,17 @@ function cssEntrypoints(entrypoint, config) {
406
406
  };
407
407
  }
408
408
 
409
+ // src/core/vite-plugins/bundleAnalysis.ts
410
+ import { visualizer } from "rollup-plugin-visualizer";
411
+ var increment = 0;
412
+ function bundleAnalysis() {
413
+ return visualizer({
414
+ emitFile: true,
415
+ template: "raw-data",
416
+ filename: `stats-${increment++}.json`
417
+ });
418
+ }
419
+
409
420
  // src/core/utils/globals.ts
410
421
  function getGlobals(config) {
411
422
  return [
@@ -527,6 +538,10 @@ async function getInternalConfig(inlineConfig, command) {
527
538
  transformManifest(manifest) {
528
539
  userConfig.transformManifest?.(manifest);
529
540
  inlineConfig.transformManifest?.(manifest);
541
+ },
542
+ analysis: {
543
+ enabled: mergedConfig.analysis?.enabled ?? false,
544
+ template: mergedConfig.analysis?.template ?? "treemap"
530
545
  }
531
546
  };
532
547
  finalConfig.vite = (env2) => resolveInternalViteConfig(env2, mergedConfig, finalConfig);
@@ -580,7 +595,11 @@ function mergeInlineConfig(inlineConfig, userConfig) {
580
595
  runner,
581
596
  srcDir: inlineConfig.srcDir ?? userConfig.srcDir,
582
597
  vite: viteConfig,
583
- zip
598
+ zip,
599
+ analysis: {
600
+ enabled: inlineConfig.analysis?.enabled ?? userConfig.analysis?.enabled,
601
+ template: inlineConfig.analysis?.template ?? userConfig.analysis?.template
602
+ }
584
603
  };
585
604
  }
586
605
  function resolveInternalZipConfig(root, mergedConfig) {
@@ -625,6 +644,9 @@ async function resolveInternalViteConfig(env, mergedConfig, finalConfig) {
625
644
  internalVite.plugins.push(devServerGlobals(finalConfig));
626
645
  internalVite.plugins.push(tsconfigPaths(finalConfig));
627
646
  internalVite.plugins.push(noopBackground());
647
+ if (finalConfig.analysis.enabled) {
648
+ internalVite.plugins.push(bundleAnalysis());
649
+ }
628
650
  internalVite.define ??= {};
629
651
  for (const global of getGlobals(finalConfig)) {
630
652
  internalVite.define[global.name] = JSON.stringify(global.value);
@@ -633,7 +655,7 @@ async function resolveInternalViteConfig(env, mergedConfig, finalConfig) {
633
655
  }
634
656
 
635
657
  // src/index.ts
636
- import pc4 from "picocolors";
658
+ import pc5 from "picocolors";
637
659
 
638
660
  // src/core/utils/arrays.ts
639
661
  function every(array, predicate) {
@@ -768,9 +790,12 @@ async function getPublicFiles(config) {
768
790
  }
769
791
 
770
792
  // src/core/build/buildEntrypoints.ts
771
- async function buildEntrypoints(groups, config) {
793
+ import pc from "picocolors";
794
+ async function buildEntrypoints(groups, config, spinner) {
772
795
  const steps = [];
773
- for (const group of groups) {
796
+ for (let i = 0; i < groups.length; i++) {
797
+ const group = groups[i];
798
+ spinner.text = pc.dim(`[${i + 1}/${groups.length}]`) + ` ${[group].flat().map((e) => e.name).join(pc.dim(", "))}`;
774
799
  const step = Array.isArray(group) ? await buildMultipleEntrypoints(group, config) : await buildSingleEntrypoint(group, config);
775
800
  steps.push(step);
776
801
  }
@@ -974,7 +999,7 @@ async function findEntrypoints(config) {
974
999
  relativePaths.map(async (relativePath) => {
975
1000
  const path7 = resolve8(config.entrypointsDir, relativePath);
976
1001
  const matchingGlob = pathGlobs.find(
977
- (glob4) => minimatch(relativePath, glob4)
1002
+ (glob5) => minimatch(relativePath, glob5)
978
1003
  );
979
1004
  if (matchingGlob == null) {
980
1005
  return config.logger.warn(
@@ -1863,7 +1888,7 @@ function addHostPermission(manifest, hostPermission) {
1863
1888
  }
1864
1889
 
1865
1890
  // src/core/build.ts
1866
- import pc2 from "picocolors";
1891
+ import pc3 from "picocolors";
1867
1892
  import * as vite4 from "vite";
1868
1893
  import fs14 from "fs-extra";
1869
1894
 
@@ -1919,7 +1944,7 @@ import { resolve as resolve12 } from "path";
1919
1944
 
1920
1945
  // src/core/log/printFileList.ts
1921
1946
  import path5 from "node:path";
1922
- import pc from "picocolors";
1947
+ import pc2 from "picocolors";
1923
1948
  import fs13 from "fs-extra";
1924
1949
  import { filesize } from "filesize";
1925
1950
 
@@ -1965,21 +1990,21 @@ async function printFileList(log, header, baseDir, files) {
1965
1990
  totalSize += stats.size;
1966
1991
  const size = String(filesize(stats.size));
1967
1992
  return [
1968
- `${pc.gray(prefix)} ${pc.dim(parts[0])}${color(parts[1])}`,
1969
- pc.dim(size)
1993
+ `${pc2.gray(prefix)} ${pc2.dim(parts[0])}${color(parts[1])}`,
1994
+ pc2.dim(size)
1970
1995
  ];
1971
1996
  })
1972
1997
  );
1973
- fileRows.push([`${pc.cyan("\u03A3 Total size:")} ${String(filesize(totalSize))}`]);
1998
+ fileRows.push([`${pc2.cyan("\u03A3 Total size:")} ${String(filesize(totalSize))}`]);
1974
1999
  printTable(log, header, fileRows);
1975
2000
  }
1976
- var DEFAULT_COLOR = pc.blue;
2001
+ var DEFAULT_COLOR = pc2.blue;
1977
2002
  var CHUNK_COLORS = {
1978
- ".js.map": pc.gray,
1979
- ".html": pc.green,
1980
- ".css": pc.magenta,
1981
- ".js": pc.cyan,
1982
- ".zip": pc.yellow
2003
+ ".js.map": pc2.gray,
2004
+ ".html": pc2.green,
2005
+ ".css": pc2.magenta,
2006
+ ".js": pc2.cyan,
2007
+ ".zip": pc2.yellow
1983
2008
  };
1984
2009
  function getChunkColor(filename) {
1985
2010
  return Object.entries(CHUNK_COLORS).find(([key]) => filename.endsWith(key))?.[1] ?? DEFAULT_COLOR;
@@ -2016,11 +2041,13 @@ function getChunkSortWeight(filename) {
2016
2041
  }
2017
2042
 
2018
2043
  // src/core/build.ts
2044
+ import { execSync } from "node:child_process";
2045
+ import glob3 from "fast-glob";
2019
2046
  async function buildInternal(config) {
2020
2047
  const verb = config.command === "serve" ? "Pre-rendering" : "Building";
2021
2048
  const target = `${config.browser}-mv${config.manifestVersion}`;
2022
2049
  config.logger.info(
2023
- `${verb} ${pc2.cyan(target)} for ${pc2.cyan(config.mode)} with ${pc2.green(
2050
+ `${verb} ${pc3.cyan(target)} for ${pc3.cyan(config.mode)} with ${pc3.green(
2024
2051
  `Vite ${vite4.version}`
2025
2052
  )}`
2026
2053
  );
@@ -2037,19 +2064,28 @@ async function buildInternal(config) {
2037
2064
  output,
2038
2065
  config
2039
2066
  );
2067
+ if (config.analysis.enabled) {
2068
+ await combineAnalysisStats(config);
2069
+ config.logger.info(
2070
+ `Analysis complete:
2071
+ ${pc3.gray("\u2514\u2500")} ${pc3.yellow("stats.html")}`
2072
+ );
2073
+ }
2040
2074
  return output;
2041
2075
  }
2042
2076
  async function rebuild(config, entrypointGroups, existingOutput = {
2043
2077
  steps: [],
2044
2078
  publicAssets: []
2045
2079
  }) {
2080
+ const { default: ora } = await import("ora");
2081
+ const spinner = ora(`Preparing...`).start();
2046
2082
  const allEntrypoints = await findEntrypoints(config);
2047
2083
  await generateTypesDir(allEntrypoints, config).catch((err) => {
2048
2084
  config.logger.warn("Failed to update .wxt directory:", err);
2049
2085
  if (config.command === "build")
2050
2086
  throw err;
2051
2087
  });
2052
- const newOutput = await buildEntrypoints(entrypointGroups, config);
2088
+ const newOutput = await buildEntrypoints(entrypointGroups, config, spinner);
2053
2089
  const mergedOutput = {
2054
2090
  steps: [...existingOutput.steps, ...newOutput.steps],
2055
2091
  publicAssets: [...existingOutput.publicAssets, ...newOutput.publicAssets]
@@ -2064,6 +2100,7 @@ async function rebuild(config, entrypointGroups, existingOutput = {
2064
2100
  ...newOutput
2065
2101
  };
2066
2102
  await writeManifest(newManifest, finalOutput, config);
2103
+ spinner.clear().stop();
2067
2104
  return {
2068
2105
  output: {
2069
2106
  manifest: newManifest,
@@ -2076,6 +2113,17 @@ async function rebuild(config, entrypointGroups, existingOutput = {
2076
2113
  manifest: newManifest
2077
2114
  };
2078
2115
  }
2116
+ async function combineAnalysisStats(config) {
2117
+ const unixFiles = await glob3(`stats-*.json`, {
2118
+ cwd: config.outDir,
2119
+ absolute: true
2120
+ });
2121
+ const absolutePaths = unixFiles.map(unnormalizePath);
2122
+ execSync(
2123
+ `rollup-plugin-visualizer ${absolutePaths.join(" ")} --template ${config.analysis.template}`,
2124
+ { cwd: config.root, stdio: "inherit" }
2125
+ );
2126
+ }
2079
2127
 
2080
2128
  // src/core/server.ts
2081
2129
  import * as vite5 from "vite";
@@ -2265,10 +2313,10 @@ function reloadHtmlPages(groups, server, config) {
2265
2313
 
2266
2314
  // src/core/clean.ts
2267
2315
  import path6 from "node:path";
2268
- import glob3 from "fast-glob";
2316
+ import glob4 from "fast-glob";
2269
2317
  import fs15 from "fs-extra";
2270
2318
  import { consola as consola2 } from "consola";
2271
- import pc3 from "picocolors";
2319
+ import pc4 from "picocolors";
2272
2320
  async function clean(root = process.cwd()) {
2273
2321
  consola2.info("Cleaning Project");
2274
2322
  const tempDirs = [
@@ -2277,8 +2325,8 @@ async function clean(root = process.cwd()) {
2277
2325
  "**/.wxt",
2278
2326
  ".output/*"
2279
2327
  ];
2280
- consola2.debug("Looking for:", tempDirs.map(pc3.cyan).join(", "));
2281
- const directories = await glob3(tempDirs, {
2328
+ consola2.debug("Looking for:", tempDirs.map(pc4.cyan).join(", "));
2329
+ const directories = await glob4(tempDirs, {
2282
2330
  cwd: path6.resolve(root),
2283
2331
  absolute: true,
2284
2332
  onlyDirectories: true,
@@ -2290,16 +2338,16 @@ async function clean(root = process.cwd()) {
2290
2338
  }
2291
2339
  consola2.debug(
2292
2340
  "Found:",
2293
- directories.map((dir) => pc3.cyan(path6.relative(root, dir))).join(", ")
2341
+ directories.map((dir) => pc4.cyan(path6.relative(root, dir))).join(", ")
2294
2342
  );
2295
2343
  for (const directory of directories) {
2296
2344
  await fs15.rm(directory, { force: true, recursive: true });
2297
- consola2.debug("Deleted " + pc3.cyan(path6.relative(root, directory)));
2345
+ consola2.debug("Deleted " + pc4.cyan(path6.relative(root, directory)));
2298
2346
  }
2299
2347
  }
2300
2348
 
2301
2349
  // package.json
2302
- var version2 = "0.6.1";
2350
+ var version2 = "0.6.3";
2303
2351
 
2304
2352
  // src/core/utils/defineConfig.ts
2305
2353
  function defineConfig(config) {
@@ -2347,13 +2395,13 @@ async function createServer2(config) {
2347
2395
  if (changes.type === "no-change")
2348
2396
  return;
2349
2397
  internalConfig.logger.info(
2350
- `Changed: ${Array.from(new Set(fileChanges.map((change) => change[1]))).map((file) => pc4.dim(relative7(internalConfig.root, file))).join(", ")}`
2398
+ `Changed: ${Array.from(new Set(fileChanges.map((change) => change[1]))).map((file) => pc5.dim(relative7(internalConfig.root, file))).join(", ")}`
2351
2399
  );
2352
2400
  const rebuiltNames = changes.rebuildGroups.flat().map((entry) => {
2353
- return pc4.cyan(
2401
+ return pc5.cyan(
2354
2402
  relative7(internalConfig.outDir, getEntrypointOutputFile(entry, ""))
2355
2403
  );
2356
- }).join(pc4.dim(", "));
2404
+ }).join(pc5.dim(", "));
2357
2405
  internalConfig = await getLatestInternalConfig();
2358
2406
  internalConfig.server = server;
2359
2407
  const { output: newOutput } = await rebuild(