Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion packages/wxt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,14 @@
"web-ext-run": "^0.2.4"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
"vite": "^5.4.19 || ^6.3.4 || ^7.0.0"
},
"peerDependenciesMeta": {
"eslint": {
"optional": true
}
},
"devDependencies": {
"@aklinker1/check": "^2.1.0",
"@faker-js/faker": "^10.0.0",
Expand All @@ -72,6 +78,7 @@
"@types/node": "^20.17.6",
"@types/normalize-path": "^3.0.2",
"@types/prompts": "^2.4.9",
"eslint": "^9.38.0",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We test this by spinning up NPM projects that have eslint as a dependency, so we don't technically need it installed here. I would prefer not to, just so it's not installed as apart of the monorepo.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason we needed it is because otherwise TS errors that there's no types for the import("eslint").

I'll try to shim out a .d.ts instead.

"extract-zip": "^2.0.1",
"happy-dom": "^18.0.1",
"lodash.merge": "^4.6.2",
Expand All @@ -83,7 +90,6 @@
"vitest": "^3.2.4",
"vitest-plugin-random-seed": "^1.1.1"
},
"peerDependenciesMeta": {},
"repository": {
"type": "git",
"url": "git+https://github.com/wxt-dev/wxt.git"
Expand Down
8 changes: 4 additions & 4 deletions packages/wxt/src/@types/modules.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ declare module 'web-ext-run' {
exit(): Promise<void>;
}

const webExt: {
cmd: {
run(config: any, executeOptions: any): Promise<WebExtRunInstance>;
};
export declare const cmd: {
run(config: any, executeOptions: any): Promise<WebExtRunInstance>;
};

declare const webExt: { cmd: typeof cmd };
export default webExt;
}

Expand Down
8 changes: 3 additions & 5 deletions packages/wxt/src/core/builders/vite/index.ts
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to keep this file as-is, so that vite's not a required dependency. Eventually, I want to add support for more bundlers than just vite, which is why it's a dynamic import here. I'd like to keep the function async so trying to figure out how to make it async again is not a blocker whenever that happens.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So... I shouldn't work on tying WXT more closely to Vite using the Env API? ... was going to work on that next.

Can you explain why we'd want more bundlers than Vite? I'd understand if it was a webpack project and we were adding in support for RSPack or Turbopack, but there's not really Vite alternatives out there beyond Rolldown-Vite, which'll just be vanilla Vite pretty soon.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type * as vite from 'vite';
import * as vite from 'vite';
import {
BuildStepOutput,
Entrypoint,
Expand Down Expand Up @@ -29,13 +29,11 @@ import { dirname, extname, join, relative } from 'node:path';
import fs from 'fs-extra';
import { normalizePath } from '../../utils/paths';

export async function createViteBuilder(
export function createViteBuilder(
wxtConfig: ResolvedConfig,
hooks: Hookable<WxtHooks>,
getWxtDevServer?: () => WxtDevServer | undefined,
): Promise<WxtBuilder> {
const vite = await import('vite');

): WxtBuilder {
/**
* Returns the base vite config shared by all builds based on the inline and user config.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Plugin } from 'vite';
import type { Plugin } from 'vite';
import { ResolvedConfig, WxtDevServer } from '../../../../types';

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/wxt/src/core/builders/vite/plugins/download.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Plugin } from 'vite';
import type { Plugin } from 'vite';
import { ResolvedConfig } from '../../../../types';
import { fetchCached } from '../../../utils/network';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Plugin } from 'vite';
import type { Plugin } from 'vite';
import { VIRTUAL_NOOP_BACKGROUND_MODULE_ID } from '../../../utils/constants';

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ResolvedConfig } from '../../../../types';
import * as vite from 'vite';
import type * as vite from 'vite';
import { normalizePath } from '../../../utils/paths';
import { removeMainFunctionCode } from '../../../utils/transform';
import { resolve } from 'node:path';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Plugin } from 'vite';
import { ResolvedConfig } from '../../../../types';
import type { Plugin } from 'vite';
import type { ResolvedConfig } from '../../../../types';
import { normalizePath } from '../../../utils/paths';
import {
VirtualModuleId,
Expand Down
2 changes: 1 addition & 1 deletion packages/wxt/src/core/initialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import fs from 'fs-extra';
import path from 'node:path';
import pc from 'picocolors';
import { Formatter } from 'picocolors/types';
import ora from 'ora';

export async function initialize(options: {
directory: string;
Expand Down Expand Up @@ -161,7 +162,6 @@ async function cloneProject({
directory: string;
template: Template;
}) {
const { default: ora } = await import('ora');
const spinner = ora('Downloading template').start();
try {
// 1. Clone repo
Expand Down
48 changes: 15 additions & 33 deletions packages/wxt/src/core/resolve-config.ts
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this file is also only about importing vite up top. Let's revert it as well now, since Vite will be a peer soon.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even when Vite is a peer, it'll still be installed (either by error [yarn, pnpm sometimes] or by autoinstall [npm, bun, pnpm usually]).

Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { safeStringToNumber } from './utils/number';
import { loadEnv } from './utils/env';
import { getPort } from 'get-port-please';
import { fileURLToPath, pathToFileURL } from 'node:url';
import * as vite from 'vite';

/**
* Given an inline config, discover the config file if necessary, merge the results, resolve any
Expand Down Expand Up @@ -61,7 +62,7 @@ export async function resolveConfig(

// Merge it into the inline config

const mergedConfig = await mergeInlineConfig(inlineConfig, userConfig);
const mergedConfig = mergeInlineConfig(inlineConfig, userConfig);

// Apply defaults to make internal config.

Expand Down Expand Up @@ -255,10 +256,10 @@ async function resolveManifestConfig(
/**
* Merge the inline config and user config. Inline config is given priority. Defaults are not applied here.
*/
async function mergeInlineConfig(
function mergeInlineConfig(
inlineConfig: InlineConfig,
userConfig: UserConfig,
): Promise<InlineConfig> {
): InlineConfig {
// Merge imports option
const imports: InlineConfig['imports'] =
inlineConfig.imports === false || userConfig.imports === false
Expand All @@ -277,11 +278,7 @@ async function mergeInlineConfig(
const merged = defu(inlineConfig, userConfig);

// Builders
const builderConfig = await mergeBuilderConfig(
merged.logger ?? consola,
inlineConfig,
userConfig,
);
const builderConfig = mergeBuilderConfig(inlineConfig, userConfig);

return {
...merged,
Expand Down Expand Up @@ -536,17 +533,10 @@ async function getUnimportEslintOptions(
* Returns the path to `node_modules/wxt`.
*/
function resolveWxtModuleDir() {
// TODO: Drop the __filename expression once we're fully running in ESM
// (see https://github.com/wxt-dev/wxt/issues/277)
const importer =
typeof __filename === 'string'
? pathToFileURL(__filename).href
: import.meta.url;

// TODO: Switch to import.meta.resolve() once the parent argument is unflagged
// (e.g. --experimental-import-meta-resolve) and all Node.js versions we support
// have it.
const url = esmResolve('wxt', importer);
const url = esmResolve('wxt', import.meta.url);

// esmResolve() returns the "wxt/dist/index.mjs" file, not the package's root
// directory, which we want to return from this function.
Expand All @@ -573,25 +563,17 @@ const COMMAND_MODES: Record<WxtCommand, string> = {
serve: 'development',
};

export async function mergeBuilderConfig(
logger: Logger,
function mergeBuilderConfig(
inlineConfig: InlineConfig,
userConfig: UserConfig,
): Promise<Pick<InlineConfig, 'vite'>> {
const vite = await import('vite').catch((err) => {
logger.debug('Failed to import vite:', err);
});
if (vite) {
return {
vite: async (env) => {
const resolvedInlineConfig = (await inlineConfig.vite?.(env)) ?? {};
const resolvedUserConfig = (await userConfig.vite?.(env)) ?? {};
return vite.mergeConfig(resolvedUserConfig, resolvedInlineConfig);
},
};
}

throw Error('Builder not found. Make sure vite is installed.');
): Pick<InlineConfig, 'vite'> {
return {
vite: async (env) => {
const resolvedInlineConfig = (await inlineConfig.vite?.(env)) ?? {};
const resolvedUserConfig = (await userConfig.vite?.(env)) ?? {};
return vite.mergeConfig(resolvedUserConfig, resolvedInlineConfig);
},
};
}

export async function resolveWxtUserModules(
Expand Down
5 changes: 3 additions & 2 deletions packages/wxt/src/core/runners/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import { createWslRunner } from './wsl';
import { createWebExtRunner } from './web-ext';
import { createSafariRunner } from './safari';
import { createManualRunner } from './manual';
import { isWsl } from '../utils/wsl';

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

import { wxt } from '../wxt';
import isWsl from 'is-wsl';

export async function createExtensionRunner(): Promise<ExtensionRunner> {
if (wxt.config.browser === 'safari') return createSafariRunner();

if (await isWsl()) return createWslRunner();
if (isWsl) return createWslRunner();
if (wxt.config.runnerConfig.config?.disabled) return createManualRunner();

return createWebExtRunner();
Expand Down
8 changes: 4 additions & 4 deletions packages/wxt/src/core/runners/web-ext.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { WebExtRunInstance } from 'web-ext-run';
import webExt, { type WebExtRunInstance } from 'web-ext-run';
import * as webExtLogger from 'web-ext-run/util/logger';

import { ExtensionRunner } from '../../types';
import { formatDuration } from '../utils/time';
import defu from 'defu';
Expand Down Expand Up @@ -27,7 +29,6 @@ export function createWebExtRunner(): ExtensionRunner {
}

// Use WXT's logger instead of web-ext's built-in one.
const webExtLogger = await import('web-ext-run/util/logger');
webExtLogger.consoleStream.write = ({ level, msg, name }) => {
if (level >= ERROR_LOG_LEVEL) wxt.logger.error(name, msg);
if (level >= WARN_LOG_LEVEL) wxt.logger.warn(msg);
Expand Down Expand Up @@ -80,8 +81,7 @@ export function createWebExtRunner(): ExtensionRunner {
wxt.logger.debug('web-ext config:', finalConfig);
wxt.logger.debug('web-ext options:', options);

const webExt = await import('web-ext-run');
runner = await webExt.default.cmd.run(finalConfig, options);
runner = await webExt.cmd.run(finalConfig, options);

const duration = Date.now() - startTime;
wxt.logger.success(`Opened browser in ${formatDuration(duration)}`);
Expand Down
2 changes: 1 addition & 1 deletion packages/wxt/src/core/utils/building/internal-build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
import { wxt } from '../../wxt';
import { mergeJsonOutputs } from '@aklinker1/rollup-plugin-visualizer';
import { isCI } from 'ci-info';
import open from 'open';

/**
* Builds the extension based on an internal config. No more config discovery is performed, the
Expand Down Expand Up @@ -86,7 +87,6 @@ export async function internalBuild(): Promise<BuildOutput> {
wxt.logger.debug(`Skipped opening ${pc.yellow(statsPath)} in CI`);
} else {
wxt.logger.info(`Opening ${pc.yellow(statsPath)} in browser...`);
const { default: open } = await import('open');
open(wxt.config.analysis.outputFile);
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/wxt/src/core/utils/building/rebuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { buildEntrypoints } from './build-entrypoints';
import { generateManifest, writeManifest } from '../../utils/manifest';
import { wxt } from '../../wxt';
import type { Browser } from '@wxt-dev/browser';
import ora from 'ora';

/**
* Given a configuration, list of entrypoints, and an existing, partial output, build the
Expand Down Expand Up @@ -33,7 +34,6 @@ export async function rebuild(
manifest: Browser.runtime.Manifest;
warnings: any[][];
}> {
const { default: ora } = await import('ora');
const spinner = ora(`Preparing...`).start();

// Update types directory with new files and types
Expand Down
5 changes: 1 addition & 4 deletions packages/wxt/src/core/utils/eslint.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
export async function getEslintVersion(): Promise<string[]> {
try {
const require = (await import('node:module')).default.createRequire(
import.meta.url,
);
const { ESLint } = require('eslint');
const { ESLint } = await import('eslint');
return ESLint.version?.split('.') ?? [];
} catch {
// Return an empty version when there's an error importing ESLint
Expand Down
5 changes: 3 additions & 2 deletions packages/wxt/src/core/utils/wsl.ts
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can just delete this file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was having trouble mocking it, but I'll give it another shot

Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import isWsl_ from 'is-wsl';

/**
* Returns true when running on WSL or WSL2.
*/
export async function isWsl(): Promise<boolean> {
const { default: isWsl } = await import('is-wsl'); // ESM only, requires dynamic import
return isWsl;
return isWsl_;
}
2 changes: 1 addition & 1 deletion packages/wxt/src/core/wxt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export async function registerWxt(

const hooks = createHooks<WxtHooks>();
const config = await resolveConfig(inlineConfig, command);
const builder = await createViteBuilder(config, hooks, () => wxt.server);
const builder = createViteBuilder(config, hooks, () => wxt.server);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, and here I'm assuming vite exists lol. We should probably add an if statement and dynamic import createViteBuilder here as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But leave that for a different PR?

And I'm still not sure why it matters if Vite exists. It does exist, and acting like it doesn't just feels like premature abstraction, but 🤷🏻‍♂️

const pm = await createWxtPackageManager(config.root);

wxt = {
Expand Down
Loading