wxt 0.21.0 → 0.21.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.
Files changed (153) hide show
  1. package/README.md +0 -1
  2. package/bin/wxt-publish-extension.mjs +4 -3
  3. package/dist/browser.d.mts +7 -6
  4. package/dist/browser.mjs +6 -5
  5. package/dist/builtin-modules/favicon-permission.mjs +28 -0
  6. package/dist/builtin-modules/index.mjs +3 -4
  7. package/dist/builtin-modules/unimport.mjs +1 -3
  8. package/dist/cli/cli-utils.mjs +8 -9
  9. package/dist/cli/commands.mjs +1 -3
  10. package/dist/cli/index.mjs +1 -3
  11. package/dist/core/build.d.mts +9 -8
  12. package/dist/core/build.mjs +10 -11
  13. package/dist/core/builders/vite/index.mjs +123 -75
  14. package/dist/core/builders/vite/plugins/bundleAnalysis.mjs +1 -3
  15. package/dist/core/builders/vite/plugins/cssEntrypoints.mjs +6 -6
  16. package/dist/core/builders/vite/plugins/defineImportMeta.mjs +3 -4
  17. package/dist/core/builders/vite/plugins/devHtmlPrerender.mjs +34 -26
  18. package/dist/core/builders/vite/plugins/devServerGlobals.mjs +3 -3
  19. package/dist/core/builders/vite/plugins/entrypointGroupGlobals.mjs +2 -6
  20. package/dist/core/builders/vite/plugins/extensionApiMock.mjs +13 -8
  21. package/dist/core/builders/vite/plugins/globals.mjs +1 -3
  22. package/dist/core/builders/vite/plugins/iifeAnonymous.mjs +1 -2
  23. package/dist/core/builders/vite/plugins/iifeFooter.mjs +14 -7
  24. package/dist/core/builders/vite/plugins/index.mjs +17 -19
  25. package/dist/core/builders/vite/plugins/noopBackground.mjs +14 -9
  26. package/dist/core/builders/vite/plugins/removeEntrypointMainFunction.mjs +10 -12
  27. package/dist/core/builders/vite/plugins/resolveAppConfig.mjs +14 -10
  28. package/dist/core/builders/vite/plugins/resolveVirtualModules.mjs +15 -13
  29. package/dist/core/builders/vite/plugins/tsconfigPaths.mjs +1 -2
  30. package/dist/core/builders/vite/plugins/wxtPluginLoader.mjs +22 -17
  31. package/dist/core/clean.d.mts +3 -14
  32. package/dist/core/clean.mjs +19 -13
  33. package/dist/core/create-server.d.mts +6 -5
  34. package/dist/core/create-server.mjs +21 -117
  35. package/dist/core/define-config.mjs +1 -2
  36. package/dist/core/define-web-ext-config.d.mts +3 -6
  37. package/dist/core/define-web-ext-config.mjs +3 -12
  38. package/dist/core/generate-wxt-dir.mjs +53 -35
  39. package/dist/core/index.d.mts +3 -2
  40. package/dist/core/index.mjs +11 -11
  41. package/dist/core/initialize.mjs +28 -29
  42. package/dist/core/keyboard-shortcuts.mjs +4 -8
  43. package/dist/core/package-managers/bun.mjs +1 -3
  44. package/dist/core/package-managers/deno.mjs +1 -2
  45. package/dist/core/package-managers/index.mjs +1 -3
  46. package/dist/core/package-managers/npm.mjs +3 -5
  47. package/dist/core/package-managers/pnpm.mjs +1 -3
  48. package/dist/core/package-managers/yarn.mjs +1 -3
  49. package/dist/core/prepare.mjs +1 -3
  50. package/dist/core/resolve-config.mjs +63 -43
  51. package/dist/core/runners/manual.mjs +2 -6
  52. package/dist/core/runners/safari.mjs +3 -4
  53. package/dist/core/runners/web-ext.mjs +8 -11
  54. package/dist/core/runners/wsl.mjs +3 -4
  55. package/dist/core/utils/arrays.mjs +4 -11
  56. package/dist/core/utils/building/build-entrypoints.mjs +10 -11
  57. package/dist/core/utils/building/detect-dev-changes.mjs +37 -19
  58. package/dist/core/utils/building/find-entrypoints.mjs +40 -21
  59. package/dist/core/utils/building/group-entrypoints.mjs +3 -4
  60. package/dist/core/utils/building/index.mjs +7 -8
  61. package/dist/core/utils/building/internal-build.mjs +21 -21
  62. package/dist/core/utils/building/rebuild.mjs +10 -10
  63. package/dist/core/utils/cache.mjs +6 -8
  64. package/dist/core/utils/constants.mjs +3 -4
  65. package/dist/core/utils/content-scripts.mjs +3 -4
  66. package/dist/core/utils/content-security-policy.mjs +2 -5
  67. package/dist/core/utils/create-file-reloader.mjs +158 -0
  68. package/dist/core/utils/entrypoints.d.mts +10 -0
  69. package/dist/core/utils/entrypoints.mjs +6 -10
  70. package/dist/core/utils/env.mjs +24 -19
  71. package/dist/core/utils/environments/browser-environment.mjs +1 -3
  72. package/dist/core/utils/environments/environment.mjs +1 -2
  73. package/dist/core/utils/environments/extension-environment.mjs +1 -3
  74. package/dist/core/utils/environments/index.mjs +3 -4
  75. package/dist/core/utils/eslint.mjs +1 -2
  76. package/dist/core/utils/fs.mjs +23 -14
  77. package/dist/core/utils/globals.mjs +1 -2
  78. package/dist/core/utils/i18n.mjs +2 -3
  79. package/dist/core/utils/index.d.mts +2 -0
  80. package/dist/core/utils/index.mjs +3 -3
  81. package/dist/core/utils/log/index.mjs +5 -6
  82. package/dist/core/utils/log/printBuildSummary.mjs +1 -3
  83. package/dist/core/utils/log/printFileList.mjs +25 -21
  84. package/dist/core/utils/log/printHeader.mjs +3 -5
  85. package/dist/core/utils/log/printTable.mjs +1 -2
  86. package/dist/core/utils/manifest.mjs +39 -46
  87. package/dist/core/utils/number.mjs +1 -2
  88. package/dist/core/utils/package.mjs +3 -5
  89. package/dist/core/utils/paths.d.mts +2 -2
  90. package/dist/core/utils/paths.mjs +7 -9
  91. package/dist/core/utils/strings.mjs +4 -7
  92. package/dist/core/utils/syntax-errors.mjs +3 -5
  93. package/dist/core/utils/theme-icons.mjs +71 -0
  94. package/dist/core/utils/time.mjs +1 -13
  95. package/dist/core/utils/transform.mjs +9 -7
  96. package/dist/core/utils/validation.mjs +1 -2
  97. package/dist/core/utils/virtual-modules.mjs +9 -15
  98. package/dist/core/wxt.mjs +11 -12
  99. package/dist/core/zip.d.mts +1 -0
  100. package/dist/core/zip.mjs +25 -20
  101. package/dist/index.d.mts +4 -4
  102. package/dist/index.mjs +3 -3
  103. package/dist/modules.d.mts +64 -61
  104. package/dist/modules.mjs +70 -66
  105. package/dist/testing/fake-browser.mjs +1 -2
  106. package/dist/testing/wxt-vitest-plugin.d.mts +4 -2
  107. package/dist/testing/wxt-vitest-plugin.mjs +5 -7
  108. package/dist/types.d.mts +636 -450
  109. package/dist/utils/app-config.d.mts +1 -0
  110. package/dist/utils/app-config.mjs +3 -3
  111. package/dist/utils/content-script-context.d.mts +49 -39
  112. package/dist/utils/content-script-context.mjs +37 -32
  113. package/dist/utils/content-script-ui/iframe.d.mts +14 -15
  114. package/dist/utils/content-script-ui/iframe.mjs +1 -3
  115. package/dist/utils/content-script-ui/integrated.d.mts +8 -7
  116. package/dist/utils/content-script-ui/integrated.mjs +1 -3
  117. package/dist/utils/content-script-ui/shadow-root.d.mts +37 -25
  118. package/dist/utils/content-script-ui/shadow-root.mjs +5 -8
  119. package/dist/utils/content-script-ui/shared.mjs +1 -3
  120. package/dist/utils/content-script-ui/types.d.mts +29 -34
  121. package/dist/utils/content-script-ui/types.mjs +1 -1
  122. package/dist/utils/define-app-config.d.mts +4 -3
  123. package/dist/utils/define-app-config.mjs +5 -5
  124. package/dist/utils/define-background.mjs +1 -2
  125. package/dist/utils/define-content-script.mjs +1 -2
  126. package/dist/utils/define-unlisted-script.mjs +1 -2
  127. package/dist/utils/define-wxt-plugin.mjs +1 -2
  128. package/dist/utils/inject-script.d.mts +2 -2
  129. package/dist/utils/inject-script.mjs +4 -5
  130. package/dist/utils/internal/custom-events.mjs +3 -4
  131. package/dist/utils/internal/location-watcher.mjs +4 -6
  132. package/dist/utils/internal/logger.mjs +2 -5
  133. package/dist/utils/match-patterns.mjs +2 -3
  134. package/dist/utils/split-shadow-root-css.d.mts +6 -2
  135. package/dist/utils/split-shadow-root-css.mjs +7 -4
  136. package/dist/utils/storage.mjs +2 -3
  137. package/dist/version.mjs +2 -3
  138. package/dist/virtual/background-entrypoint.mjs +4 -16
  139. package/dist/virtual/content-script-isolated-world-entrypoint.mjs +2 -7
  140. package/dist/virtual/content-script-main-world-entrypoint.mjs +2 -7
  141. package/dist/virtual/mock-browser.d.mts +1 -1
  142. package/dist/virtual/mock-browser.mjs +2 -4
  143. package/dist/virtual/reload-html.mjs +3 -10
  144. package/dist/virtual/unlisted-script-entrypoint.mjs +2 -7
  145. package/package.json +55 -49
  146. package/LICENSE +0 -21
  147. package/dist/core/builders/vite/plugins/download.mjs +0 -25
  148. package/dist/core/runners/index.mjs +0 -17
  149. package/dist/core/utils/minimatch-multiple.mjs +0 -28
  150. package/dist/core/utils/network.mjs +0 -38
  151. package/dist/core/utils/wsl.mjs +0 -12
  152. package/dist/testing/index.d.mts +0 -3
  153. package/dist/testing/index.mjs +0 -4
package/README.md CHANGED
@@ -54,7 +54,6 @@ Or see the [installation guide](https://wxt.dev/guide/installation.html) to get
54
54
  - 📦 [Module system](https://wxt.dev/guide/essentials/wxt-modules.html#overview) for reusing code between extensions
55
55
  - 🖍️ Quickly bootstrap a new project
56
56
  - 📏 Bundle analysis
57
- - ⬇️ Download and bundle remote URL imports
58
57
 
59
58
  ## Sponsors
60
59
 
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * A alias around `publish-extension` that is always installed on the path without having to install
4
- * `publish-browser-extension` as a direct dependency (like for PNPM, which doesn't link
5
- * sub-dependency binaries to "node_modules/.bin")
3
+ * A alias around `publish-extension` that is always installed on the path
4
+ * without having to install `publish-browser-extension` as a direct dependency
5
+ * (like for PNPM, which doesn't link sub-dependency binaries to
6
+ * "node_modules/.bin")
6
7
  */
7
8
  await import('publish-browser-extension/cli');
@@ -3,12 +3,16 @@ import { Browser, browser as browser$1 } from "@wxt-dev/browser";
3
3
 
4
4
  //#region src/browser.d.ts
5
5
  /**
6
- * This interface is empty because it is generated per-project when running `wxt prepare`. See:
6
+ * This interface is empty because it is generated per-project when running `wxt
7
+ * prepare`. See:
8
+ *
7
9
  * - `.wxt/types/paths.d.ts`
8
10
  */
9
11
  interface WxtRuntime {}
10
12
  /**
11
- * This interface is empty because it is generated per-project when running `wxt prepare`. See:
13
+ * This interface is empty because it is generated per-project when running `wxt
14
+ * prepare`. See:
15
+ *
12
16
  * - `.wxt/types/i18n.d.ts`
13
17
  */
14
18
  interface WxtI18n {}
@@ -20,10 +24,7 @@ type ScriptInjection<Args extends any[], Result> = Browser.scripting.ScriptInjec
20
24
  type InjectionResult<Result> = Array<Browser.scripting.InjectionResult<Awaited<Result>>>;
21
25
  interface WxtScripting {
22
26
  executeScript: {
23
- /**
24
- * @see {@link Browser.scripting.executeScript}
25
- */
26
- <Args extends any[], Result>(injection: ScriptInjection<Args, Result>): Promise<InjectionResult<Result>>;
27
+ /** @see {@link Browser.scripting.executeScript} */<Args extends any[], Result>(injection: ScriptInjection<Args, Result>): Promise<InjectionResult<Result>>;
27
28
  <Args extends any[], Result>(injection: ScriptInjection<Args, Result>, callback: (results: InjectionResult<Result>) => void): void;
28
29
  };
29
30
  }
package/dist/browser.mjs CHANGED
@@ -1,18 +1,19 @@
1
1
  import { browser as browser$1 } from "@wxt-dev/browser";
2
-
3
2
  //#region src/browser.ts
4
3
  /**
5
- * Contains the `browser` export which you should use to access the extension APIs in your project:
4
+ * Contains the `browser` export which you should use to access the extension
5
+ * APIs in your project:
6
+ *
6
7
  * ```ts
7
8
  * import { browser } from 'wxt/browser';
8
9
  *
9
10
  * browser.runtime.onInstalled.addListener(() => {
10
11
  * // ...
11
- * })
12
+ * });
12
13
  * ```
14
+ *
13
15
  * @module wxt/browser
14
16
  */
15
17
  const browser = browser$1;
16
-
17
18
  //#endregion
18
- export { browser };
19
+ export { browser };
@@ -0,0 +1,28 @@
1
+ import { defineWxtModule } from "../modules.mjs";
2
+ //#region src/builtin-modules/favicon-permission.ts
3
+ /**
4
+ * Adds a template-literal type for the `_favicon/` paths served by Chrome's
5
+ * favicon API when the `favicon` permission is declared. With this module,
6
+ * `browser.runtime.getURL('/_favicon/?pageUrl=...')` type-checks without
7
+ * needing a `@ts-expect-error`.
8
+ *
9
+ * Extensions that load favicons from a content script must still add their own
10
+ * `web_accessible_resources` entry — this module intentionally does not touch
11
+ * the manifest. See the review thread on #1570 for context.
12
+ *
13
+ * @see https://developer.chrome.com/docs/extensions/how-to/ui/favicons
14
+ */
15
+ var favicon_permission_default = defineWxtModule({
16
+ name: "wxt:built-in:favicon-permission",
17
+ setup(wxt) {
18
+ wxt.hooks.hook("prepare:publicPaths", (_, paths) => {
19
+ if (!wxt.config.manifest.permissions?.includes("favicon")) return;
20
+ paths.push({
21
+ type: "templateLiteral",
22
+ path: "_favicon/?${string}"
23
+ });
24
+ });
25
+ }
26
+ });
27
+ //#endregion
28
+ export { favicon_permission_default as default };
@@ -1,7 +1,6 @@
1
+ import favicon_permission_default from "./favicon-permission.mjs";
1
2
  import unimport_default from "./unimport.mjs";
2
-
3
3
  //#region src/builtin-modules/index.ts
4
- const builtinModules = [unimport_default];
5
-
4
+ const builtinModules = [unimport_default, favicon_permission_default];
6
5
  //#endregion
7
- export { builtinModules };
6
+ export { builtinModules };
@@ -1,7 +1,6 @@
1
1
  import { addViteConfig, defineWxtModule } from "../modules.mjs";
2
2
  import { createUnimport, toExports } from "unimport";
3
3
  import UnimportPlugin from "unimport/unplugin";
4
-
5
4
  //#region src/builtin-modules/unimport.ts
6
5
  var unimport_default = defineWxtModule({
7
6
  name: "wxt:built-in:unimport",
@@ -86,6 +85,5 @@ export default {
86
85
  `
87
86
  };
88
87
  }
89
-
90
88
  //#endregion
91
- export { unimport_default as default };
89
+ export { unimport_default as default };
@@ -1,15 +1,15 @@
1
- import { formatDuration } from "../core/utils/time.mjs";
2
1
  import { filterTruthy, toArray } from "../core/utils/arrays.mjs";
3
2
  import { registerWxt } from "../core/wxt.mjs";
3
+ import { formatDuration } from "../core/utils/time.mjs";
4
4
  import { printHeader } from "../core/utils/log/printHeader.mjs";
5
5
  import "../core/utils/log/index.mjs";
6
6
  import { ValidationError } from "../core/utils/validation.mjs";
7
- import consola, { LogLevels } from "consola";
8
7
  import spawn from "nano-spawn";
9
-
8
+ import consola, { LogLevels } from "consola";
10
9
  //#region src/cli/cli-utils.ts
11
10
  /**
12
- * Wrap an action handler to add a timer, error handling, and maybe enable debug mode.
11
+ * Wrap an action handler to add a timer, error handling, and maybe enable debug
12
+ * mode.
13
13
  */
14
14
  function wrapAction(cb, options) {
15
15
  return async (...args) => {
@@ -28,8 +28,8 @@ function wrapAction(cb, options) {
28
28
  };
29
29
  }
30
30
  /**
31
- * Array flags, when not passed, are either `undefined` or `[undefined]`. This function filters out
32
- * the
31
+ * Array flags, when not passed, are either `undefined` or `[undefined]`. This
32
+ * function filters out the
33
33
  */
34
34
  function getArrayFromFlags(flags, name) {
35
35
  const result = filterTruthy(toArray(flags[name]));
@@ -44,7 +44,7 @@ const aliasCommandNames = /* @__PURE__ */ new Set();
44
44
  * @param docsUrl URL to the docs for the aliased CLI tool
45
45
  */
46
46
  function createAliasedCommand(base, name, alias, bin, docsUrl) {
47
- const aliasedCommand = base.command(name, `Alias for ${alias} (${docsUrl})`).allowUnknownOptions().action(async () => {
47
+ const aliasedCommand = base.command(`${name} [...args]`, `Alias for ${alias} (${docsUrl})`).allowUnknownOptions().action(async () => {
48
48
  try {
49
49
  await registerWxt("build");
50
50
  await spawn(bin, process.argv.slice(process.argv.indexOf(aliasedCommand.name) + 1), { stdio: "inherit" });
@@ -57,6 +57,5 @@ function createAliasedCommand(base, name, alias, bin, docsUrl) {
57
57
  function isAliasedCommand(command) {
58
58
  return !!command && aliasCommandNames.has(command.name);
59
59
  }
60
-
61
60
  //#endregion
62
- export { createAliasedCommand, getArrayFromFlags, isAliasedCommand, wrapAction };
61
+ export { createAliasedCommand, getArrayFromFlags, isAliasedCommand, wrapAction };
@@ -7,7 +7,6 @@ import { zip } from "../core/zip.mjs";
7
7
  import "../core/index.mjs";
8
8
  import { createAliasedCommand, getArrayFromFlags, wrapAction } from "./cli-utils.mjs";
9
9
  import cac from "cac";
10
-
11
10
  //#region src/cli/commands.ts
12
11
  const cli = cac("wxt");
13
12
  cli.option("--debug", "enable debug mode");
@@ -76,6 +75,5 @@ cli.command("init [directory]", "initialize a new project").option("-t, --templa
76
75
  });
77
76
  }, { disableFinishedLog: true }));
78
77
  createAliasedCommand(cli, "submit", "publish-extension", "wxt-publish-extension", "https://www.npmjs.com/publish-browser-extension");
79
-
80
78
  //#endregion
81
- export { cli as default };
79
+ export { cli as default };
@@ -1,7 +1,6 @@
1
1
  import { version } from "../version.mjs";
2
2
  import { isAliasedCommand } from "./cli-utils.mjs";
3
3
  import cli from "./commands.mjs";
4
-
5
4
  //#region src/cli/index.ts
6
5
  cli.parse(process.argv, { run: false });
7
6
  if (!isAliasedCommand(cli.matchedCommand)) {
@@ -10,6 +9,5 @@ if (!isAliasedCommand(cli.matchedCommand)) {
10
9
  cli.parse(process.argv, { run: false });
11
10
  }
12
11
  await cli.runMatchedCommand();
13
-
14
12
  //#endregion
15
- export { };
13
+ export {};
@@ -2,17 +2,18 @@ import { BuildOutput, InlineConfig } from "../types.mjs";
2
2
 
3
3
  //#region src/core/build.d.ts
4
4
  /**
5
- * Bundles the extension for production. Returns a promise of the build result. Discovers the `wxt.config.ts` file in
6
- * the root directory, and merges that config with what is passed in.
5
+ * Bundles the extension for production. Returns a promise of the build result.
6
+ * Discovers the `wxt.config.ts` file in the root directory, and merges that
7
+ * config with what is passed in.
7
8
  *
8
9
  * @example
9
- * // Use config from `wxt.config.ts`
10
- * const res = await build()
10
+ * // Use config from `wxt.config.ts`
11
+ * const res = await build();
11
12
  *
12
- * // or override config `from wxt.config.ts`
13
- * const res = await build({
14
- * // Override config...
15
- * })
13
+ * // or override config `from wxt.config.ts`
14
+ * const res = await build({
15
+ * // Override config...
16
+ * });
16
17
  */
17
18
  declare function build(config?: InlineConfig): Promise<BuildOutput>;
18
19
  //#endregion
@@ -1,25 +1,24 @@
1
1
  import { registerWxt } from "./wxt.mjs";
2
2
  import { internalBuild } from "./utils/building/internal-build.mjs";
3
3
  import "./utils/building/index.mjs";
4
-
5
4
  //#region src/core/build.ts
6
5
  /**
7
- * Bundles the extension for production. Returns a promise of the build result. Discovers the `wxt.config.ts` file in
8
- * the root directory, and merges that config with what is passed in.
6
+ * Bundles the extension for production. Returns a promise of the build result.
7
+ * Discovers the `wxt.config.ts` file in the root directory, and merges that
8
+ * config with what is passed in.
9
9
  *
10
10
  * @example
11
- * // Use config from `wxt.config.ts`
12
- * const res = await build()
11
+ * // Use config from `wxt.config.ts`
12
+ * const res = await build();
13
13
  *
14
- * // or override config `from wxt.config.ts`
15
- * const res = await build({
16
- * // Override config...
17
- * })
14
+ * // or override config `from wxt.config.ts`
15
+ * const res = await build({
16
+ * // Override config...
17
+ * });
18
18
  */
19
19
  async function build(config) {
20
20
  await registerWxt("build", config);
21
21
  return await internalBuild();
22
22
  }
23
-
24
23
  //#endregion
25
- export { build };
24
+ export { build };
@@ -1,9 +1,12 @@
1
1
  import { normalizePath } from "../../utils/paths.mjs";
2
- import "../../utils/index.mjs";
3
2
  import { getEntrypointBundlePath, isHtmlEntrypoint } from "../../utils/entrypoints.mjs";
3
+ import "../../utils/index.mjs";
4
+ import { toArray } from "../../utils/arrays.mjs";
5
+ import { createExtensionEnvironment } from "../../utils/environments/extension-environment.mjs";
6
+ import "../../utils/environments/index.mjs";
7
+ import { safeVarName } from "../../utils/strings.mjs";
4
8
  import { devHtmlPrerender } from "./plugins/devHtmlPrerender.mjs";
5
9
  import { devServerGlobals } from "./plugins/devServerGlobals.mjs";
6
- import { download } from "./plugins/download.mjs";
7
10
  import { resolveVirtualModules } from "./plugins/resolveVirtualModules.mjs";
8
11
  import { tsconfigPaths } from "./plugins/tsconfigPaths.mjs";
9
12
  import { noopBackground } from "./plugins/noopBackground.mjs";
@@ -18,21 +21,14 @@ import { resolveAppConfig } from "./plugins/resolveAppConfig.mjs";
18
21
  import { iifeFooter } from "./plugins/iifeFooter.mjs";
19
22
  import { iifeAnonymous } from "./plugins/iifeAnonymous.mjs";
20
23
  import "./plugins/index.mjs";
21
- import { toArray } from "../../utils/arrays.mjs";
22
- import { safeVarName } from "../../utils/strings.mjs";
23
- import { createExtensionEnvironment } from "../../utils/environments/extension-environment.mjs";
24
- import "../../utils/environments/index.mjs";
25
- import fs from "fs-extra";
26
- import { dirname, extname, join, relative } from "node:path";
27
- import { ViteNodeServer } from "vite-node/server";
28
- import { ViteNodeRunner } from "vite-node/client";
29
- import { installSourcemapsSupport } from "vite-node/source-map";
30
-
24
+ import { mkdir, readdir, rename, rmdir, stat } from "node:fs/promises";
25
+ import { dirname, extname, join, relative, resolve } from "node:path";
31
26
  //#region src/core/builders/vite/index.ts
32
27
  async function createViteBuilder(wxtConfig, hooks, getWxtDevServer) {
33
28
  const vite = await import("vite");
34
29
  /**
35
- * Returns the base vite config shared by all builds based on the inline and user config.
30
+ * Returns the base vite config shared by all builds based on the inline and
31
+ * user config.
36
32
  */
37
33
  const getBaseConfig = async (baseConfigOptions) => {
38
34
  const config = await wxtConfig.vite(wxtConfig.env);
@@ -49,17 +45,30 @@ async function createViteBuilder(wxtConfig, hooks, getWxtDevServer) {
49
45
  if (config.build.minify == null && wxtConfig.command === "serve") config.build.minify = false;
50
46
  if (config.build.sourcemap == null && wxtConfig.command === "serve") config.build.sourcemap = "inline";
51
47
  config.server ??= {};
52
- config.server.watch = { ignored: [`${wxtConfig.outBaseDir}/**`, `${wxtConfig.wxtDir}/**`] };
48
+ config.server.watch = {
49
+ ...wxtConfig.watchOptions,
50
+ ignored: [
51
+ `${wxtConfig.outBaseDir}/**`,
52
+ `${wxtConfig.wxtDir}/**`,
53
+ ...getRunnerProfileWatchIgnores(wxtConfig),
54
+ ...toArray(wxtConfig.watchOptions.ignored ?? [])
55
+ ]
56
+ };
53
57
  config.legacy ??= {};
54
58
  config.legacy.skipWebSocketTokenCheck = true;
59
+ if (isRolldownVersion(vite.version)) {} else {
60
+ config.esbuild ??= {};
61
+ if (config.esbuild) config.esbuild.charset = "ascii";
62
+ }
55
63
  const server = getWxtDevServer?.();
56
64
  config.plugins ??= [];
57
- config.plugins.push(download(wxtConfig), devHtmlPrerender(wxtConfig, server), resolveVirtualModules(wxtConfig), devServerGlobals(wxtConfig, server), tsconfigPaths(wxtConfig), noopBackground(), globals(wxtConfig), defineImportMeta(), wxtPluginLoader(wxtConfig), resolveAppConfig(wxtConfig));
65
+ config.plugins.push(devHtmlPrerender(wxtConfig, server), resolveVirtualModules(wxtConfig), devServerGlobals(wxtConfig, server), tsconfigPaths(wxtConfig), noopBackground(), globals(wxtConfig), defineImportMeta(), wxtPluginLoader(wxtConfig), resolveAppConfig(wxtConfig));
58
66
  if (wxtConfig.analysis.enabled && !baseConfigOptions?.excludeAnalysisPlugin) config.plugins.push(bundleAnalysis(wxtConfig));
59
67
  return config;
60
68
  };
61
69
  /**
62
- * Return the basic config for building an entrypoint in [lib mode](https://vitejs.dev/guide/build.html#library-mode).
70
+ * Return the basic config for building an entrypoint in [lib
71
+ * mode](https://vitejs.dev/guide/build.html#library-mode).
63
72
  */
64
73
  const getLibModeConfig = (entrypoint) => {
65
74
  const entry = getRollupEntry(entrypoint);
@@ -69,7 +78,7 @@ async function createViteBuilder(wxtConfig, hooks, getWxtDevServer) {
69
78
  if (entrypoint.type === "content-script" || entrypoint.type === "unlisted-script") {
70
79
  if (typeof entrypoint.options.globalName === "string") iifeReturnValueName = entrypoint.options.globalName;
71
80
  else if (typeof entrypoint.options.globalName === "function") iifeReturnValueName = entrypoint.options.globalName(entrypoint);
72
- if (entrypoint.options.globalName === false) plugins.push(iifeAnonymous(iifeReturnValueName));
81
+ if (!entrypoint.options.globalName) plugins.push(iifeAnonymous(iifeReturnValueName));
73
82
  else plugins.push(iifeFooter(iifeReturnValueName));
74
83
  }
75
84
  return {
@@ -84,8 +93,8 @@ async function createViteBuilder(wxtConfig, hooks, getWxtDevServer) {
84
93
  },
85
94
  rollupOptions: { output: {
86
95
  entryFileNames: getEntrypointBundlePath(entrypoint, wxtConfig.outDir, ".js"),
87
- assetFileNames: ({ name }) => {
88
- if (entrypoint.type === "content-script" && name?.endsWith("css")) return `content-scripts/${entrypoint.name}.[ext]`;
96
+ assetFileNames: (assetInfo) => {
97
+ if (entrypoint.type === "content-script" && getRollupAssetNames(assetInfo).some((name) => name.endsWith("css"))) return `content-scripts/${entrypoint.name}.[ext]`;
89
98
  else return `assets/${entrypoint.name}.[ext]`;
90
99
  }
91
100
  } }
@@ -94,7 +103,8 @@ async function createViteBuilder(wxtConfig, hooks, getWxtDevServer) {
94
103
  };
95
104
  };
96
105
  /**
97
- * Return the basic config for building multiple entrypoints in [multi-page mode](https://vitejs.dev/guide/build.html#multi-page-app).
106
+ * Return the basic config for building multiple entrypoints in [multi-page
107
+ * mode](https://vitejs.dev/guide/build.html#multi-page-app).
98
108
  */
99
109
  const getMultiPageConfig = (entrypoints) => {
100
110
  const htmlEntrypoints = new Set(entrypoints.filter(isHtmlEntrypoint).map((e) => e.name));
@@ -118,7 +128,8 @@ async function createViteBuilder(wxtConfig, hooks, getWxtDevServer) {
118
128
  };
119
129
  };
120
130
  /**
121
- * Return the basic config for building a single CSS entrypoint in [multi-page mode](https://vitejs.dev/guide/build.html#multi-page-app).
131
+ * Return the basic config for building a single CSS entrypoint in [multi-page
132
+ * mode](https://vitejs.dev/guide/build.html#multi-page-app).
122
133
  */
123
134
  const getCssConfig = (entrypoint) => {
124
135
  return {
@@ -133,59 +144,60 @@ async function createViteBuilder(wxtConfig, hooks, getWxtDevServer) {
133
144
  } }
134
145
  };
135
146
  };
136
- const createViteNodeImporter = async (paths) => {
147
+ const createImporterEnvironment = async (paths) => {
137
148
  const baseConfig = await getBaseConfig({ excludeAnalysisPlugin: true });
138
149
  baseConfig.optimizeDeps ??= {};
139
150
  baseConfig.optimizeDeps.noDiscovery = true;
140
151
  baseConfig.optimizeDeps.include = [];
141
152
  const envConfig = { plugins: paths.map((path) => removeEntrypointMainFunction(wxtConfig, path)) };
142
- const config = vite.mergeConfig(baseConfig, envConfig);
143
- const server = await vite.createServer(config);
144
- await server.pluginContainer.buildStart({});
145
- const node = new ViteNodeServer(server);
146
- installSourcemapsSupport({ getSourceMap: (source) => node.getSourceMap(source) });
147
- return {
148
- runner: new ViteNodeRunner({
149
- root: server.config.root,
150
- base: server.config.base,
151
- fetchModule(id) {
152
- return node.fetchModule(id);
153
- },
154
- resolveId(id, importer) {
155
- return node.resolveId(id, importer);
153
+ const importerConfig = vite.mergeConfig(baseConfig, envConfig);
154
+ const config = await vite.resolveConfig(vite.mergeConfig(importerConfig || {}, {
155
+ configFile: false,
156
+ envDir: false,
157
+ cacheDir: process.cwd(),
158
+ environments: { inline: {
159
+ consumer: "server",
160
+ dev: { moduleRunnerTransform: true },
161
+ resolve: {
162
+ external: true,
163
+ mainFields: [],
164
+ conditions: ["node"]
156
165
  }
157
- }),
158
- server
159
- };
166
+ } }
167
+ }), "serve");
168
+ const environment = vite.createRunnableDevEnvironment("inline", config, {
169
+ runnerOptions: { hmr: { logger: false } },
170
+ hot: false
171
+ });
172
+ await environment.init();
173
+ return environment;
160
174
  };
161
- const requireDefaultExport = (path, mod) => {
175
+ function requireDefaultExport(path, mod) {
162
176
  const relativePath = relative(wxtConfig.root, path);
163
177
  if (mod?.default == null) {
164
178
  const defineFn = relativePath.includes(".content") ? "defineContentScript" : relativePath.includes("background") ? "defineBackground" : "defineUnlistedScript";
165
179
  throw Error(`${relativePath}: Default export not found, did you forget to call "export default ${defineFn}(...)"?`);
166
180
  }
167
- };
181
+ }
168
182
  return {
169
183
  name: "Vite",
170
184
  version: vite.version,
171
185
  async importEntrypoint(path) {
172
- const env = createExtensionEnvironment();
173
- const { runner, server } = await createViteNodeImporter([path]);
174
- const res = await env.run(() => runner.executeFile(path));
175
- await server.close();
176
- requireDefaultExport(path, res);
177
- return res.default;
186
+ const [module] = await this.importEntrypoints([path]);
187
+ return module;
178
188
  },
179
189
  async importEntrypoints(paths) {
180
- const env = createExtensionEnvironment();
181
- const { runner, server } = await createViteNodeImporter(paths);
182
- const res = await env.run(() => Promise.all(paths.map(async (path) => {
183
- const mod = await runner.executeFile(path);
184
- requireDefaultExport(path, mod);
185
- return mod.default;
186
- })));
187
- await server.close();
188
- return res;
190
+ const context = createExtensionEnvironment();
191
+ const environment = await createImporterEnvironment(paths);
192
+ try {
193
+ return await context.run(async () => await Promise.all(paths.map(async (path) => {
194
+ const module = await environment.runner.import(path);
195
+ requireDefaultExport(path, module);
196
+ return module.default;
197
+ })));
198
+ } finally {
199
+ await environment.close();
200
+ }
189
201
  },
190
202
  async build(group) {
191
203
  let entryConfig;
@@ -236,14 +248,48 @@ async function createViteBuilder(wxtConfig, hooks, getWxtDevServer) {
236
248
  }
237
249
  };
238
250
  }
251
+ function getRunnerProfileWatchIgnores(wxtConfig) {
252
+ const root = normalizePath(wxtConfig.root);
253
+ const chromiumArgProfiles = extractPathArgs(wxtConfig.webExt.config?.chromiumArgs, "--user-data-dir");
254
+ const firefoxArgProfiles = extractPathArgs(wxtConfig.webExt.config?.firefoxArgs, "-profile");
255
+ const profiles = [
256
+ wxtConfig.webExt.config?.chromiumProfile,
257
+ wxtConfig.webExt.config?.firefoxProfile,
258
+ ...chromiumArgProfiles,
259
+ ...firefoxArgProfiles
260
+ ].filter((profile) => typeof profile === "string");
261
+ return Array.from(new Set(profiles.map((profile) => normalizePath(resolve(wxtConfig.root, profile))).filter((profilePath) => profilePath !== root).map((profilePath) => `${profilePath}/**`)));
262
+ }
263
+ function extractPathArgs(args, flag) {
264
+ if (!args?.length) return [];
265
+ const paths = [];
266
+ for (let i = 0; i < args.length; i++) {
267
+ const arg = args[i];
268
+ if (arg.startsWith(`${flag}=`)) {
269
+ const value = arg.slice(flag.length + 1).trim();
270
+ if (value) paths.push(value);
271
+ continue;
272
+ }
273
+ if (arg === flag) {
274
+ const nextValue = args[i + 1]?.trim();
275
+ if (nextValue) paths.push(nextValue);
276
+ i += 1;
277
+ }
278
+ }
279
+ return paths;
280
+ }
281
+ function getRollupAssetNames(assetInfo) {
282
+ if (Array.isArray(assetInfo.names)) return assetInfo.names;
283
+ return assetInfo.name ? [assetInfo.name] : [];
284
+ }
239
285
  function getBuildOutputChunks(result) {
240
286
  if ("on" in result) throw Error("wxt does not support vite watch mode.");
241
287
  if (Array.isArray(result)) return result.flatMap(({ output }) => output);
242
288
  return result.output;
243
289
  }
244
290
  /**
245
- * Returns the input module ID (virtual or real file) for an entrypoint. The returned string should
246
- * be passed as an input to rollup.
291
+ * Returns the input module ID (virtual or real file) for an entrypoint. The
292
+ * returned string should be passed as an input to rollup.
247
293
  */
248
294
  function getRollupEntry(entrypoint) {
249
295
  let virtualEntrypointType;
@@ -260,15 +306,17 @@ function getRollupEntry(entrypoint) {
260
306
  return entrypoint.inputPath;
261
307
  }
262
308
  /**
263
- * Ensures the HTML files output by a multipage build are in the correct location. This does two
264
- * things:
309
+ * Ensures the HTML files output by a multi-page build are in the correct
310
+ * location. This does two things:
265
311
  *
266
- * 1. Moves the HTML files to their final location at `<outDir>/<entrypoint.name>.html`.
267
- * 2. Updates the bundle so it summarizes the files correctly in the returned build output.
312
+ * 1. Moves the HTML files to their final location at
313
+ * `<outDir>/<entrypoint.name>.html`.
314
+ * 2. Updates the bundle so it summarizes the files correctly in the returned build
315
+ * output.
268
316
  *
269
- * Assets (JS and CSS) are output to the `<outDir>/assets` directory, and don't need to be modified.
270
- * HTML files access them via absolute URLs, so we don't need to update any import paths in the HTML
271
- * files either.
317
+ * Assets (JS and CSS) are output to the `<outDir>/assets` directory, and don't
318
+ * need to be modified. HTML files access them via absolute URLs, so we don't
319
+ * need to update any import paths in the HTML files either.
272
320
  */
273
321
  async function moveHtmlFiles(config, group, chunks) {
274
322
  if (!Array.isArray(group)) return chunks;
@@ -284,8 +332,8 @@ async function moveHtmlFiles(config, group, chunks) {
284
332
  const newBundlePath = getEntrypointBundlePath(entry, config.outDir, extname(chunk.fileName));
285
333
  const oldAbsPath = join(config.outDir, oldBundlePath);
286
334
  const newAbsPath = join(config.outDir, newBundlePath);
287
- await fs.ensureDir(dirname(newAbsPath));
288
- await fs.move(oldAbsPath, newAbsPath, { overwrite: true });
335
+ await mkdir(dirname(newAbsPath), { recursive: true });
336
+ await rename(oldAbsPath, newAbsPath);
289
337
  return {
290
338
  ...chunk,
291
339
  fileName: newBundlePath
@@ -294,19 +342,19 @@ async function moveHtmlFiles(config, group, chunks) {
294
342
  await removeEmptyDirs(config.outDir);
295
343
  return movedChunks;
296
344
  }
297
- /**
298
- * Recursively remove all directories that are empty/
299
- */
345
+ /** Recursively remove all directories that are empty/ */
300
346
  async function removeEmptyDirs(dir) {
301
- const files = await fs.readdir(dir);
347
+ const files = await readdir(dir);
302
348
  for (const file of files) {
303
349
  const filePath = join(dir, file);
304
- if ((await fs.stat(filePath)).isDirectory()) await removeEmptyDirs(filePath);
350
+ if ((await stat(filePath)).isDirectory()) await removeEmptyDirs(filePath);
305
351
  }
306
352
  try {
307
- await fs.rmdir(dir);
353
+ await rmdir(dir);
308
354
  } catch {}
309
355
  }
310
-
356
+ function isRolldownVersion(version) {
357
+ return Number(version.split(".")[0]) >= 8;
358
+ }
311
359
  //#endregion
312
- export { createViteBuilder };
360
+ export { createViteBuilder };
@@ -1,6 +1,5 @@
1
1
  import path from "node:path";
2
2
  import { visualizer } from "@aklinker1/rollup-plugin-visualizer";
3
-
4
3
  //#region src/core/builders/vite/plugins/bundleAnalysis.ts
5
4
  let increment = 0;
6
5
  function bundleAnalysis(config) {
@@ -9,6 +8,5 @@ function bundleAnalysis(config) {
9
8
  filename: path.resolve(config.analysis.outputDir, `${config.analysis.outputName}-${increment++}.json`)
10
9
  });
11
10
  }
12
-
13
11
  //#endregion
14
- export { bundleAnalysis };
12
+ export { bundleAnalysis };
@@ -1,15 +1,16 @@
1
1
  import { getEntrypointBundlePath } from "../../../utils/entrypoints.mjs";
2
-
3
2
  //#region src/core/builders/vite/plugins/cssEntrypoints.ts
4
3
  /**
5
- * Rename CSS entrypoint outputs to ensure a JS file is not generated, and that the CSS file is
6
- * placed in the correct place.
4
+ * Rename CSS entrypoint outputs to ensure a JS file is not generated, and that
5
+ * the CSS file is placed in the correct place.
7
6
  *
8
7
  * It:
8
+ *
9
9
  * 1. Renames CSS files to their final paths
10
10
  * 2. Removes the JS file that get's output by lib mode
11
11
  *
12
- * THIS PLUGIN SHOULD ONLY BE APPLIED TO CSS LIB MODE BUILDS. It should not be added to every build.
12
+ * THIS PLUGIN SHOULD ONLY BE APPLIED TO CSS LIB MODE BUILDS. It should not be
13
+ * added to every build.
13
14
  */
14
15
  function cssEntrypoints(entrypoint, config) {
15
16
  return {
@@ -24,6 +25,5 @@ function cssEntrypoints(entrypoint, config) {
24
25
  }
25
26
  };
26
27
  }
27
-
28
28
  //#endregion
29
- export { cssEntrypoints };
29
+ export { cssEntrypoints };