wxt 0.18.7 → 0.18.9

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.
@@ -12,7 +12,7 @@ import {
12
12
  } from "./chunk-QGM4M3NI.js";
13
13
 
14
14
  // package.json
15
- var version = "0.18.6";
15
+ var version = "0.18.8";
16
16
 
17
17
  // src/core/utils/paths.ts
18
18
  import systemPath from "node:path";
@@ -713,10 +713,13 @@ try {
713
713
  // Use "pre" so the new script is added before vite bundles all the scripts
714
714
  order: "pre",
715
715
  handler(html, _ctx) {
716
+ const src = config.command === "serve" ? `http://${config.dev.server?.hostname}:${config.dev.server?.port}/@id/${virtualHtmlModuleId}` : virtualHtmlModuleId;
716
717
  const { document } = parseHTML2(html);
718
+ const existing = document.querySelector(`script[src='${src}']`);
719
+ if (existing) return;
717
720
  const script = document.createElement("script");
718
721
  script.type = "module";
719
- script.src = config.command === "serve" ? `http://${config.dev.server?.hostname}:${config.dev.server?.port}/@id/${virtualHtmlModuleId}` : virtualHtmlModuleId;
722
+ script.src = src;
720
723
  if (document.head == null) {
721
724
  const newHead = document.createElement("head");
722
725
  document.documentElement.prepend(newHead);
@@ -822,11 +825,25 @@ function detectDevChanges(changedFiles, currentOutput) {
822
825
  (changedFile) => findEffectedSteps(changedFile, currentOutput)
823
826
  )
824
827
  );
825
- if (changedSteps.size === 0) return { type: "no-change" };
828
+ if (changedSteps.size === 0) {
829
+ const hasPublicChange = some(
830
+ changedFiles,
831
+ (file) => file.startsWith(wxt.config.publicDir)
832
+ );
833
+ if (hasPublicChange) {
834
+ return {
835
+ type: "extension-reload",
836
+ rebuildGroups: [],
837
+ cachedOutput: currentOutput
838
+ };
839
+ } else {
840
+ return { type: "no-change" };
841
+ }
842
+ }
826
843
  const unchangedOutput = {
827
844
  manifest: currentOutput.manifest,
828
845
  steps: [],
829
- publicAssets: []
846
+ publicAssets: [...currentOutput.publicAssets]
830
847
  };
831
848
  const changedOutput = {
832
849
  manifest: currentOutput.manifest,
@@ -840,13 +857,6 @@ function detectDevChanges(changedFiles, currentOutput) {
840
857
  unchangedOutput.steps.push(step);
841
858
  }
842
859
  }
843
- for (const asset of currentOutput.publicAssets) {
844
- if (changedSteps.has(asset)) {
845
- changedOutput.publicAssets.push(asset);
846
- } else {
847
- unchangedOutput.publicAssets.push(asset);
848
- }
849
- }
850
860
  const isOnlyHtmlChanges = changedFiles.length > 0 && every(changedFiles, (file) => file.endsWith(".html"));
851
861
  if (isOnlyHtmlChanges) {
852
862
  return {
@@ -887,122 +897,27 @@ function findEffectedSteps(changedFile, currentOutput) {
887
897
  const effectedChunk = step.chunks.find((chunk) => isChunkEffected(chunk));
888
898
  if (effectedChunk) changes.push(step);
889
899
  }
890
- const effectedAsset = currentOutput.publicAssets.find(
891
- (chunk) => isChunkEffected(chunk)
892
- );
893
- if (effectedAsset) changes.push(effectedAsset);
894
900
  return changes;
895
901
  }
896
902
 
897
903
  // src/core/utils/building/find-entrypoints.ts
898
- import { relative as relative4, resolve as resolve8 } from "path";
899
- import fs6 from "fs-extra";
904
+ import { relative as relative3, resolve as resolve7 } from "path";
905
+ import fs5 from "fs-extra";
900
906
  import { minimatch } from "minimatch";
901
907
  import { parseHTML as parseHTML3 } from "linkedom";
902
908
  import JSON5 from "json5";
903
909
  import glob2 from "fast-glob";
904
910
  import pc2 from "picocolors";
905
-
906
- // src/core/utils/building/import-entrypoint.ts
907
- import createJITI from "jiti";
908
- import { createUnimport as createUnimport2 } from "unimport";
909
- import fs5 from "fs-extra";
910
- import { relative as relative3, resolve as resolve7 } from "node:path";
911
- import { transformSync } from "esbuild";
912
- import { fileURLToPath } from "node:url";
913
- async function importEntrypointFile(path8) {
914
- wxt.logger.debug("Loading file metadata:", path8);
915
- const normalPath = normalizePath(path8);
916
- const unimport2 = createUnimport2({
917
- ...wxt.config.imports,
918
- // Only allow specific imports, not all from the project
919
- dirs: []
920
- });
921
- await unimport2.init();
922
- const text = await fs5.readFile(path8, "utf-8");
923
- const textNoImports = removeProjectImportStatements(text);
924
- const { code } = await unimport2.injectImports(textNoImports);
925
- wxt.logger.debug(
926
- ["Text:", text, "No imports:", textNoImports, "Code:", code].join("\n")
927
- );
928
- const jiti = createJITI(
929
- typeof __filename !== "undefined" ? __filename : fileURLToPath(import.meta.url),
930
- {
931
- cache: false,
932
- debug: wxt.config.debug,
933
- esmResolve: true,
934
- alias: {
935
- "webextension-polyfill": resolve7(
936
- wxt.config.wxtModuleDir,
937
- "dist/virtual/mock-browser.js"
938
- )
939
- },
940
- // Continue using node to load TS files even if `bun run --bun` is detected. Jiti does not
941
- // respect the custom transform function when using it's native bun option.
942
- experimentalBun: false,
943
- // List of extensions to transform with esbuild
944
- extensions: [
945
- ".ts",
946
- ".cts",
947
- ".mts",
948
- ".tsx",
949
- ".js",
950
- ".cjs",
951
- ".mjs",
952
- ".jsx"
953
- ],
954
- transform(opts) {
955
- const isEntrypoint = opts.filename === normalPath;
956
- return transformSync(
957
- // Use modified source code for entrypoints
958
- isEntrypoint ? code : opts.source,
959
- getEsbuildOptions(opts)
960
- );
961
- }
962
- }
963
- );
964
- try {
965
- const res = await jiti(path8);
966
- return res.default;
967
- } catch (err) {
968
- const filePath = relative3(wxt.config.root, path8);
969
- if (err instanceof ReferenceError) {
970
- const variableName = err.message.replace(" is not defined", "");
971
- throw Error(
972
- `${filePath}: Cannot use imported variable "${variableName}" outside the main function. See https://wxt.dev/guide/go-further/entrypoint-side-effects.html`,
973
- { cause: err }
974
- );
975
- } else {
976
- wxt.logger.error(err);
977
- throw Error(`Failed to load entrypoint: ${filePath}`, { cause: err });
978
- }
979
- }
980
- }
981
- function getEsbuildOptions(opts) {
982
- const isJsx = opts.filename?.endsWith("x");
983
- return {
984
- format: "cjs",
985
- loader: isJsx ? "tsx" : "ts",
986
- ...isJsx ? {
987
- // `h` and `Fragment` are undefined, but that's OK because JSX is never evaluated while
988
- // grabbing the entrypoint's options.
989
- jsxFactory: "h",
990
- jsxFragment: "Fragment"
991
- } : void 0
992
- };
993
- }
994
-
995
- // src/core/utils/building/find-entrypoints.ts
996
911
  async function findEntrypoints() {
997
- await fs6.mkdir(wxt.config.wxtDir, { recursive: true });
998
- await fs6.writeJson(resolve8(wxt.config.wxtDir, "tsconfig.json"), {});
912
+ await fs5.mkdir(wxt.config.wxtDir, { recursive: true });
913
+ await fs5.writeJson(resolve7(wxt.config.wxtDir, "tsconfig.json"), {});
999
914
  const relativePaths = await glob2(Object.keys(PATH_GLOB_TO_TYPE_MAP), {
1000
915
  cwd: wxt.config.entrypointsDir
1001
916
  });
1002
917
  relativePaths.sort();
1003
918
  const pathGlobs = Object.keys(PATH_GLOB_TO_TYPE_MAP);
1004
919
  const entrypointInfos = relativePaths.reduce((results, relativePath) => {
1005
- const inputPath = resolve8(wxt.config.entrypointsDir, relativePath);
920
+ const inputPath = resolve7(wxt.config.entrypointsDir, relativePath);
1006
921
  const name = getEntrypointName(wxt.config.entrypointsDir, inputPath);
1007
922
  const matchingGlob = pathGlobs.find(
1008
923
  (glob5) => minimatch(relativePath, glob5)
@@ -1044,7 +959,7 @@ async function findEntrypoints() {
1044
959
  return {
1045
960
  ...info,
1046
961
  type,
1047
- outputDir: resolve8(wxt.config.outDir, CONTENT_SCRIPT_OUT_DIR),
962
+ outputDir: resolve7(wxt.config.outDir, CONTENT_SCRIPT_OUT_DIR),
1048
963
  options: {
1049
964
  include: void 0,
1050
965
  exclude: void 0
@@ -1118,7 +1033,7 @@ function preventDuplicateEntrypointNames(files) {
1118
1033
  if (absolutePaths.length > 1) {
1119
1034
  lines.push(`- ${name}`);
1120
1035
  absolutePaths.forEach((absolutePath) => {
1121
- lines.push(` - ${relative4(wxt.config.root, absolutePath)}`);
1036
+ lines.push(` - ${relative3(wxt.config.root, absolutePath)}`);
1122
1037
  });
1123
1038
  }
1124
1039
  return lines;
@@ -1206,7 +1121,7 @@ async function getUnlistedScriptEntrypoint({
1206
1121
  name,
1207
1122
  skipped
1208
1123
  }) {
1209
- const defaultExport = await importEntrypoint(inputPath);
1124
+ const defaultExport = await wxt.builder.importEntrypoint(inputPath);
1210
1125
  if (defaultExport == null) {
1211
1126
  throw Error(
1212
1127
  `${name}: Default export not found, did you forget to call "export default defineUnlistedScript(...)"?`
@@ -1229,7 +1144,7 @@ async function getBackgroundEntrypoint({
1229
1144
  }) {
1230
1145
  let options = {};
1231
1146
  if (inputPath !== VIRTUAL_NOOP_BACKGROUND_MODULE_ID) {
1232
- const defaultExport = await importEntrypoint(inputPath);
1147
+ const defaultExport = await wxt.builder.importEntrypoint(inputPath);
1233
1148
  if (defaultExport == null) {
1234
1149
  throw Error(
1235
1150
  `${name}: Default export not found, did you forget to call "export default defineBackground(...)"?`
@@ -1255,7 +1170,13 @@ async function getContentScriptEntrypoint({
1255
1170
  name,
1256
1171
  skipped
1257
1172
  }) {
1258
- const { main: _, ...options } = await importEntrypoint(inputPath);
1173
+ const defaultExport = await wxt.builder.importEntrypoint(inputPath);
1174
+ if (defaultExport == null) {
1175
+ throw Error(
1176
+ `${name}: Default export not found, did you forget to call "export default defineContentScript(...)"?`
1177
+ );
1178
+ }
1179
+ const { main: _, ...options } = defaultExport;
1259
1180
  if (options == null) {
1260
1181
  throw Error(
1261
1182
  `${name}: Default export not found, did you forget to call "export default defineContentScript(...)"?`
@@ -1265,7 +1186,7 @@ async function getContentScriptEntrypoint({
1265
1186
  type: "content-script",
1266
1187
  name,
1267
1188
  inputPath,
1268
- outputDir: resolve8(wxt.config.outDir, CONTENT_SCRIPT_OUT_DIR),
1189
+ outputDir: resolve7(wxt.config.outDir, CONTENT_SCRIPT_OUT_DIR),
1269
1190
  options: resolvePerBrowserOptions(options, wxt.config.browser),
1270
1191
  skipped
1271
1192
  };
@@ -1298,7 +1219,7 @@ async function getSidepanelEntrypoint(info) {
1298
1219
  };
1299
1220
  }
1300
1221
  async function getHtmlEntrypointOptions(info, keyMap, queries, parsers) {
1301
- const content = await fs6.readFile(info.inputPath, "utf-8");
1222
+ const content = await fs5.readFile(info.inputPath, "utf-8");
1302
1223
  const { document } = parseHTML3(content);
1303
1224
  const options = {};
1304
1225
  const defaultQuery = (manifestKey) => document.querySelector(`meta[name='manifest.${manifestKey}']`)?.getAttribute("content");
@@ -1358,14 +1279,11 @@ var PATH_GLOB_TO_TYPE_MAP = {
1358
1279
  [`*/index.${CSS_EXTENSIONS_PATTERN}`]: "unlisted-style"
1359
1280
  };
1360
1281
  var CONTENT_SCRIPT_OUT_DIR = "content-scripts";
1361
- function importEntrypoint(path8) {
1362
- return wxt.config.experimental.viteRuntime ? wxt.builder.importEntrypoint(path8) : importEntrypointFile(path8);
1363
- }
1364
1282
 
1365
1283
  // src/core/utils/building/generate-wxt-dir.ts
1366
- import { createUnimport as createUnimport3 } from "unimport";
1367
- import fs7 from "fs-extra";
1368
- import { relative as relative5, resolve as resolve9 } from "path";
1284
+ import { createUnimport as createUnimport2 } from "unimport";
1285
+ import fs6 from "fs-extra";
1286
+ import { relative as relative4, resolve as resolve8 } from "path";
1369
1287
  import path4 from "node:path";
1370
1288
 
1371
1289
  // src/core/utils/i18n.ts
@@ -1407,10 +1325,10 @@ function parseI18nMessages(messagesJson) {
1407
1325
 
1408
1326
  // src/core/utils/building/generate-wxt-dir.ts
1409
1327
  async function generateTypesDir(entrypoints) {
1410
- await fs7.ensureDir(wxt.config.typesDir);
1328
+ await fs6.ensureDir(wxt.config.typesDir);
1411
1329
  const references = [];
1412
1330
  if (wxt.config.imports !== false) {
1413
- const unimport2 = createUnimport3(wxt.config.imports);
1331
+ const unimport2 = createUnimport2(wxt.config.imports);
1414
1332
  references.push(await writeImportsDeclarationFile(unimport2));
1415
1333
  if (wxt.config.imports.eslintrc.enabled) {
1416
1334
  await writeImportsEslintFile(unimport2, wxt.config.imports);
@@ -1423,7 +1341,7 @@ async function generateTypesDir(entrypoints) {
1423
1341
  await writeTsConfigFile(mainReference);
1424
1342
  }
1425
1343
  async function writeImportsDeclarationFile(unimport2) {
1426
- const filePath = resolve9(wxt.config.typesDir, "imports.d.ts");
1344
+ const filePath = resolve8(wxt.config.typesDir, "imports.d.ts");
1427
1345
  await unimport2.scanImportsFromDir(void 0, { cwd: wxt.config.srcDir });
1428
1346
  await writeFileIfDifferent(
1429
1347
  filePath,
@@ -1439,10 +1357,10 @@ async function writeImportsEslintFile(unimport2, options) {
1439
1357
  (await unimport2.getImports()).map((i) => i.as ?? i.name).filter(Boolean).sort().forEach((name) => {
1440
1358
  eslintrc.globals[name] = options.eslintrc.globalsPropValue;
1441
1359
  });
1442
- await fs7.writeJson(options.eslintrc.filePath, eslintrc, { spaces: 2 });
1360
+ await fs6.writeJson(options.eslintrc.filePath, eslintrc, { spaces: 2 });
1443
1361
  }
1444
1362
  async function writePathsDeclarationFile(entrypoints) {
1445
- const filePath = resolve9(wxt.config.typesDir, "paths.d.ts");
1363
+ const filePath = resolve8(wxt.config.typesDir, "paths.d.ts");
1446
1364
  const unions = entrypoints.map(
1447
1365
  (entry) => getEntrypointBundlePath(
1448
1366
  entry,
@@ -1470,7 +1388,7 @@ declare module "wxt/browser" {
1470
1388
  return filePath;
1471
1389
  }
1472
1390
  async function writeI18nDeclarationFile() {
1473
- const filePath = resolve9(wxt.config.typesDir, "i18n.d.ts");
1391
+ const filePath = resolve8(wxt.config.typesDir, "i18n.d.ts");
1474
1392
  const defaultLocale = wxt.config.manifest.default_locale;
1475
1393
  const template = `// Generated by wxt
1476
1394
  import "wxt/browser";
@@ -1499,7 +1417,7 @@ declare module "wxt/browser" {
1499
1417
  defaultLocale,
1500
1418
  "messages.json"
1501
1419
  );
1502
- const content = JSON.parse(await fs7.readFile(defaultLocalePath, "utf-8"));
1420
+ const content = JSON.parse(await fs6.readFile(defaultLocalePath, "utf-8"));
1503
1421
  messages = parseI18nMessages(content);
1504
1422
  } else {
1505
1423
  messages = parseI18nMessages({});
@@ -1523,7 +1441,7 @@ declare module "wxt/browser" {
1523
1441
  return filePath;
1524
1442
  }
1525
1443
  async function writeGlobalsDeclarationFile() {
1526
- const filePath = resolve9(wxt.config.typesDir, "globals.d.ts");
1444
+ const filePath = resolve8(wxt.config.typesDir, "globals.d.ts");
1527
1445
  const globals2 = [...getGlobals(wxt.config), ...getEntrypointGlobals("")];
1528
1446
  await writeFileIfDifferent(
1529
1447
  filePath,
@@ -1542,14 +1460,14 @@ async function writeGlobalsDeclarationFile() {
1542
1460
  }
1543
1461
  async function writeMainDeclarationFile(references) {
1544
1462
  const dir = wxt.config.wxtDir;
1545
- const filePath = resolve9(dir, "wxt.d.ts");
1463
+ const filePath = resolve8(dir, "wxt.d.ts");
1546
1464
  await writeFileIfDifferent(
1547
1465
  filePath,
1548
1466
  [
1549
1467
  "// Generated by wxt",
1550
1468
  `/// <reference types="wxt/vite-builder-env" />`,
1551
1469
  ...references.map(
1552
- (ref) => `/// <reference types="./${normalizePath(relative5(dir, ref))}" />`
1470
+ (ref) => `/// <reference types="./${normalizePath(relative4(dir, ref))}" />`
1553
1471
  ),
1554
1472
  // Add references to modules installed from NPM to the TS project so
1555
1473
  // their type augmentation can update InlineConfig correctly. Local
@@ -1564,7 +1482,7 @@ async function writeMainDeclarationFile(references) {
1564
1482
  }
1565
1483
  async function writeTsConfigFile(mainReference) {
1566
1484
  const dir = wxt.config.wxtDir;
1567
- const getTsconfigPath = (path8) => normalizePath(relative5(dir, path8));
1485
+ const getTsconfigPath = (path8) => normalizePath(relative4(dir, path8));
1568
1486
  const paths = Object.entries(wxt.config.alias).flatMap(([alias, absolutePath]) => {
1569
1487
  const aliasPath = getTsconfigPath(absolutePath);
1570
1488
  return [
@@ -1573,7 +1491,7 @@ async function writeTsConfigFile(mainReference) {
1573
1491
  ];
1574
1492
  }).join(",\n");
1575
1493
  await writeFileIfDifferent(
1576
- resolve9(dir, "tsconfig.json"),
1494
+ resolve8(dir, "tsconfig.json"),
1577
1495
  `{
1578
1496
  "compilerOptions": {
1579
1497
  "target": "ESNext",
@@ -1603,10 +1521,10 @@ import { loadConfig } from "c12";
1603
1521
  import path5 from "node:path";
1604
1522
 
1605
1523
  // src/core/utils/cache.ts
1606
- import fs8, { ensureDir as ensureDir2 } from "fs-extra";
1607
- import { dirname as dirname4, resolve as resolve10 } from "path";
1524
+ import fs7, { ensureDir as ensureDir2 } from "fs-extra";
1525
+ import { dirname as dirname4, resolve as resolve9 } from "path";
1608
1526
  function createFsCache(wxtDir) {
1609
- const getPath = (key) => resolve10(wxtDir, "cache", encodeURIComponent(key));
1527
+ const getPath = (key) => resolve9(wxtDir, "cache", encodeURIComponent(key));
1610
1528
  return {
1611
1529
  async set(key, value) {
1612
1530
  const path8 = getPath(key);
@@ -1616,7 +1534,7 @@ function createFsCache(wxtDir) {
1616
1534
  async get(key) {
1617
1535
  const path8 = getPath(key);
1618
1536
  try {
1619
- return await fs8.readFile(path8, "utf-8");
1537
+ return await fs7.readFile(path8, "utf-8");
1620
1538
  } catch {
1621
1539
  return void 0;
1622
1540
  }
@@ -1628,12 +1546,12 @@ function createFsCache(wxtDir) {
1628
1546
  import defu from "defu";
1629
1547
 
1630
1548
  // src/core/utils/package.ts
1631
- import { resolve as resolve11 } from "node:path";
1632
- import fs9 from "fs-extra";
1549
+ import { resolve as resolve10 } from "node:path";
1550
+ import fs8 from "fs-extra";
1633
1551
  async function getPackageJson() {
1634
- const file = resolve11(wxt.config.root, "package.json");
1552
+ const file = resolve10(wxt.config.root, "package.json");
1635
1553
  try {
1636
- return await fs9.readJson(file);
1554
+ return await fs8.readJson(file);
1637
1555
  } catch (err) {
1638
1556
  wxt.logger.debug(
1639
1557
  `Failed to read package.json at: ${file}. Returning undefined.`
@@ -1649,7 +1567,7 @@ function isModuleInstalled(name) {
1649
1567
  }
1650
1568
 
1651
1569
  // src/core/utils/building/resolve-config.ts
1652
- import fs10 from "fs-extra";
1570
+ import fs9 from "fs-extra";
1653
1571
  import glob3 from "fast-glob";
1654
1572
  async function resolveConfig(inlineConfig, command) {
1655
1573
  let userConfig = {};
@@ -1765,7 +1683,7 @@ async function resolveConfig(inlineConfig, command) {
1765
1683
  alias,
1766
1684
  experimental: defu(mergedConfig.experimental, {
1767
1685
  includeBrowserPolyfill: true,
1768
- viteRuntime: false
1686
+ entrypointImporter: "jiti"
1769
1687
  }),
1770
1688
  dev: {
1771
1689
  server: devServerConfig,
@@ -1887,7 +1805,7 @@ async function resolveWxtModuleDir() {
1887
1805
  return path5.resolve(requireResolve("wxt"), "../..");
1888
1806
  }
1889
1807
  async function isDirMissing(dir) {
1890
- return !await fs10.exists(dir);
1808
+ return !await fs9.exists(dir);
1891
1809
  }
1892
1810
  function logMissingDir(logger, name, expected) {
1893
1811
  logger.warn(
@@ -1999,6 +1917,95 @@ var ENTRY_TYPE_TO_GROUP_MAP = {
1999
1917
  "content-script-style": "individual"
2000
1918
  };
2001
1919
 
1920
+ // src/core/utils/building/import-entrypoint.ts
1921
+ import createJITI from "jiti";
1922
+ import { createUnimport as createUnimport3 } from "unimport";
1923
+ import fs10 from "fs-extra";
1924
+ import { relative as relative5, resolve as resolve11 } from "node:path";
1925
+ import { transformSync } from "esbuild";
1926
+ import { fileURLToPath } from "node:url";
1927
+ async function importEntrypointFile(path8) {
1928
+ wxt.logger.debug("Loading file metadata:", path8);
1929
+ const normalPath = normalizePath(path8);
1930
+ const unimport2 = createUnimport3({
1931
+ ...wxt.config.imports,
1932
+ // Only allow specific imports, not all from the project
1933
+ dirs: []
1934
+ });
1935
+ await unimport2.init();
1936
+ const text = await fs10.readFile(path8, "utf-8");
1937
+ const textNoImports = removeProjectImportStatements(text);
1938
+ const { code } = await unimport2.injectImports(textNoImports);
1939
+ wxt.logger.debug(
1940
+ ["Text:", text, "No imports:", textNoImports, "Code:", code].join("\n")
1941
+ );
1942
+ const jiti = createJITI(
1943
+ typeof __filename !== "undefined" ? __filename : fileURLToPath(import.meta.url),
1944
+ {
1945
+ cache: false,
1946
+ debug: wxt.config.debug,
1947
+ esmResolve: true,
1948
+ alias: {
1949
+ "webextension-polyfill": resolve11(
1950
+ wxt.config.wxtModuleDir,
1951
+ "dist/virtual/mock-browser.js"
1952
+ )
1953
+ },
1954
+ // Continue using node to load TS files even if `bun run --bun` is detected. Jiti does not
1955
+ // respect the custom transform function when using it's native bun option.
1956
+ experimentalBun: false,
1957
+ // List of extensions to transform with esbuild
1958
+ extensions: [
1959
+ ".ts",
1960
+ ".cts",
1961
+ ".mts",
1962
+ ".tsx",
1963
+ ".js",
1964
+ ".cjs",
1965
+ ".mjs",
1966
+ ".jsx"
1967
+ ],
1968
+ transform(opts) {
1969
+ const isEntrypoint = opts.filename === normalPath;
1970
+ return transformSync(
1971
+ // Use modified source code for entrypoints
1972
+ isEntrypoint ? code : opts.source,
1973
+ getEsbuildOptions(opts)
1974
+ );
1975
+ }
1976
+ }
1977
+ );
1978
+ try {
1979
+ const res = await jiti(path8);
1980
+ return res.default;
1981
+ } catch (err) {
1982
+ const filePath = relative5(wxt.config.root, path8);
1983
+ if (err instanceof ReferenceError) {
1984
+ const variableName = err.message.replace(" is not defined", "");
1985
+ throw Error(
1986
+ `${filePath}: Cannot use imported variable "${variableName}" outside the main function. See https://wxt.dev/guide/go-further/entrypoint-side-effects.html`,
1987
+ { cause: err }
1988
+ );
1989
+ } else {
1990
+ wxt.logger.error(err);
1991
+ throw Error(`Failed to load entrypoint: ${filePath}`, { cause: err });
1992
+ }
1993
+ }
1994
+ }
1995
+ function getEsbuildOptions(opts) {
1996
+ const isJsx = opts.filename?.endsWith("x");
1997
+ return {
1998
+ format: "cjs",
1999
+ loader: isJsx ? "tsx" : "ts",
2000
+ ...isJsx ? {
2001
+ // `h` and `Fragment` are undefined, but that's OK because JSX is never evaluated while
2002
+ // grabbing the entrypoint's options.
2003
+ jsxFactory: "h",
2004
+ jsxFragment: "Fragment"
2005
+ } : void 0
2006
+ };
2007
+ }
2008
+
2002
2009
  // src/core/utils/building/internal-build.ts
2003
2010
  import pc5 from "picocolors";
2004
2011
  import fs13 from "fs-extra";
@@ -3119,6 +3126,9 @@ var packageManagers = {
3119
3126
  };
3120
3127
 
3121
3128
  // src/core/builders/vite/index.ts
3129
+ import { ViteNodeServer } from "vite-node/server";
3130
+ import { ViteNodeRunner } from "vite-node/client";
3131
+ import { installSourcemapsSupport } from "vite-node/source-map";
3122
3132
  async function createViteBuilder(wxtConfig, hooks, server) {
3123
3133
  const vite = await import("vite");
3124
3134
  const getBaseConfig = async () => {
@@ -3266,21 +3276,64 @@ async function createViteBuilder(wxtConfig, hooks, server) {
3266
3276
  return {
3267
3277
  name: "Vite",
3268
3278
  version: vite.version,
3269
- async importEntrypoint(url) {
3270
- const baseConfig = await getBaseConfig();
3271
- const envConfig = {
3272
- plugins: [
3273
- webextensionPolyfillMock(wxtConfig),
3274
- removeEntrypointMainFunction(wxtConfig, url)
3275
- ]
3276
- };
3277
- const config = vite.mergeConfig(baseConfig, envConfig);
3278
- const server2 = await vite.createServer(config);
3279
- await server2.listen();
3280
- const runtime = await vite.createViteRuntime(server2, { hmr: false });
3281
- const module = await runtime.executeUrl(url);
3282
- await server2.close();
3283
- return module.default;
3279
+ async importEntrypoint(path8) {
3280
+ switch (wxtConfig.experimental.entrypointImporter) {
3281
+ default:
3282
+ case "jiti": {
3283
+ return await importEntrypointFile(path8);
3284
+ }
3285
+ case "vite-runtime": {
3286
+ const baseConfig = await getBaseConfig();
3287
+ const envConfig = {
3288
+ plugins: [
3289
+ webextensionPolyfillMock(wxtConfig),
3290
+ removeEntrypointMainFunction(wxtConfig, path8)
3291
+ ]
3292
+ };
3293
+ const config = vite.mergeConfig(baseConfig, envConfig);
3294
+ const server2 = await vite.createServer(config);
3295
+ await server2.listen();
3296
+ const runtime = await vite.createViteRuntime(server2, { hmr: false });
3297
+ const module = await runtime.executeUrl(path8);
3298
+ await server2.close();
3299
+ return module.default;
3300
+ }
3301
+ case "vite-node": {
3302
+ const baseConfig = await getBaseConfig();
3303
+ baseConfig.optimizeDeps ??= {};
3304
+ baseConfig.optimizeDeps.noDiscovery = true;
3305
+ baseConfig.optimizeDeps.include = [];
3306
+ const envConfig = {
3307
+ plugins: [
3308
+ webextensionPolyfillMock(wxtConfig),
3309
+ removeEntrypointMainFunction(wxtConfig, path8)
3310
+ ]
3311
+ };
3312
+ const config = vite.mergeConfig(baseConfig, envConfig);
3313
+ const server2 = await vite.createServer(config);
3314
+ await server2.pluginContainer.buildStart({});
3315
+ const node = new ViteNodeServer(server2);
3316
+ installSourcemapsSupport({
3317
+ getSourceMap: (source) => node.getSourceMap(source)
3318
+ });
3319
+ const runner = new ViteNodeRunner({
3320
+ root: server2.config.root,
3321
+ base: server2.config.base,
3322
+ // when having the server and runner in a different context,
3323
+ // you will need to handle the communication between them
3324
+ // and pass to this function
3325
+ fetchModule(id) {
3326
+ return node.fetchModule(id);
3327
+ },
3328
+ resolveId(id, importer) {
3329
+ return node.resolveId(id, importer);
3330
+ }
3331
+ });
3332
+ const res = await runner.executeFile(path8);
3333
+ await server2.close();
3334
+ return res.default;
3335
+ }
3336
+ }
3284
3337
  },
3285
3338
  async build(group) {
3286
3339
  let entryConfig;