feat: Open browser when starting dev server (#11)

This commit is contained in:
Aaron
2023-06-25 20:58:47 -05:00
committed by GitHub
parent 50bb8454dd
commit 62f4f605d0
12 changed files with 4052 additions and 86 deletions
+3
View File
@@ -3,6 +3,7 @@
.env.*
.idea
.output
.webextrc
.wxt
*.log
/.vscode/
@@ -12,3 +13,5 @@ dist
e2e/project
node_modules
TODOs.md
web-ext.config.js
web-ext.config.ts
+2
View File
@@ -47,6 +47,7 @@
"prepare": "simple-git-hooks"
},
"dependencies": {
"c12": "^1.4.2",
"cac": "^6.7.14",
"consola": "^3.1.0",
"fast-glob": "^3.2.12",
@@ -59,6 +60,7 @@
"picomatch": "^2.3.1",
"unimport": "^3.0.8",
"vite": "^4.3.9",
"web-ext": "^7.6.2",
"webextension-polyfill": "^0.10.0"
},
"devDependencies": {
+3831 -67
View File
File diff suppressed because it is too large Load Diff
+32
View File
@@ -0,0 +1,32 @@
declare module 'web-ext' {
export interface WebExtRunInstance {
reloadAllExtensions(): Promise<void>;
exit(): Promise<void>;
}
const webExt: {
cmd: {
run(config: any, executeOptions: any): Promise<WebExtRunInstance>;
};
};
export default webExt;
}
declare module 'web-ext/util/logger' {
// https://github.com/mozilla/web-ext/blob/e37e60a2738478f512f1255c537133321f301771/src/util/logger.js#L43
export interface IConsoleStream {
stopCapturing(): void;
startCapturing(): void;
write(packet: Packet, options: unknown): void;
flushCapturedLogs(options: unknown): void;
}
export interface Packet {
name: string;
msg: string;
level: number;
}
export class ConsoleStream implements IConsoleStream {
constructor(options?: { verbose: false });
}
export const consoleStream: IConsoleStream;
}
+1 -1
View File
@@ -24,6 +24,6 @@ export const dev = defineCommand<
const server = await wxt.createServer(cliConfig);
await server.listen(server.port);
server.logger.success(`Started dev server @ ${server.origin}`);
return true;
});
+17 -17
View File
@@ -14,12 +14,14 @@ import { generateTypesDir } from './utils/generateTypesDir';
import pc from 'picocolors';
import * as vite from 'vite';
import { findOpenPort } from './utils/findOpenPort';
import { relative } from 'path';
import { formatDuration } from './utils/formatDuration';
import { createWebExtRunner } from './runners/createWebExtRunner';
export { version } from '../package.json';
export * from './types/external';
export * from './utils/defineConfig';
export * from './utils/defineRunnerConfig';
/**
* Bundles the extension for production. Returns a promise of the build result.
*/
@@ -43,26 +45,24 @@ export async function createServer(
vite.mergeConfig(serverConfig, config ?? {}),
'serve',
);
const runner = createWebExtRunner();
const viteServer = await vite.createServer(internalConfig.vite);
viteServer.middlewares.use(function (req, res, next) {
internalConfig.logger.log('middleware');
next();
});
viteServer.watcher.on('all', (eventName, path) => {
if (
!path.startsWith(internalConfig.srcDir) ||
path.startsWith(internalConfig.outBaseDir) ||
path.startsWith(internalConfig.wxtDir)
)
return;
internalConfig.logger.log(
`${pc.green(eventName + ':')} ${relative(process.cwd(), path)}`,
);
});
const server: WxtDevServer = {
...viteServer,
async listen(port, isRestart) {
const res = await viteServer.listen(port, isRestart);
if (!isRestart) {
internalConfig.logger.success(`Started dev server @ ${origin}`);
internalConfig.logger.info('Opening browser...');
await runner.openBrowser(internalConfig);
internalConfig.logger.success('Opened!');
}
return res;
},
logger: internalConfig.logger,
port,
hostname,
+6
View File
@@ -0,0 +1,6 @@
import { InternalConfig } from '../types';
export interface ExtensionRunner {
openBrowser(config: InternalConfig): Promise<void>;
closeBrowser(): Promise<void>;
}
+70
View File
@@ -0,0 +1,70 @@
import type { WebExtRunInstance } from 'web-ext';
import { ExtensionRunner } from './ExtensionRunner';
/**
* Create an `ExtensionRunner` backed by `web-ext`.
*/
export function createWebExtRunner(): ExtensionRunner {
let runner: WebExtRunInstance | undefined;
return {
async openBrowser(config) {
if (config.browser === 'safari') {
config.logger.warn('Cannot open safari automatically.');
return;
}
// Use the plugin's logger instead of web-ext's built-in one.
const webExtLogger = await import('web-ext/util/logger');
webExtLogger.consoleStream.write = ({ level, msg, name }) => {
if (level >= ERROR_LOG_LEVEL) config.logger.error(name, msg);
if (level >= WARN_LOG_LEVEL) config.logger.warn(msg);
};
const wxtUserConfig = config.runnerConfig.config;
const userConfig = {
console: wxtUserConfig?.openConsole,
devtools: wxtUserConfig?.openDevtools,
startUrl: wxtUserConfig?.startUrls,
...(config.browser === 'firefox'
? {
firefox: wxtUserConfig?.binaries?.firefox,
firefoxProfile: wxtUserConfig?.firefoxProfile,
prefs: wxtUserConfig?.firefoxPrefs,
args: wxtUserConfig?.firefoxArgs,
}
: {
chromiumBinary: wxtUserConfig?.binaries?.[config.browser],
chromiumProfile: wxtUserConfig?.chromiumProfile,
args: wxtUserConfig?.chromiumArgs,
}),
};
const finalConfig = {
...userConfig,
target: config.browser === 'firefox' ? 'firefox-desktop' : 'chromium',
sourceDir: config.outDir,
// WXT handles reloads, so disable auto-reload behaviors in web-ext
noReload: true,
noInput: true,
};
const options = {
// Don't call `process.exit(0)` after starting web-ext
shouldExitProgram: false,
};
config.logger.debug('web-ext config:', finalConfig);
config.logger.debug('web-ext options:', options);
const webExt = await import('web-ext');
runner = await webExt.default.cmd.run(finalConfig, options);
},
async closeBrowser() {
return await runner?.exit();
},
};
}
// https://github.com/mozilla/web-ext/blob/e37e60a2738478f512f1255c537133321f301771/src/util/logger.js#L12
const WARN_LOG_LEVEL = 40;
const ERROR_LOG_LEVEL = 50;
+66
View File
@@ -21,6 +21,7 @@ export interface InlineConfig {
vite?: Omit<vite.InlineConfig, 'root' | 'configFile' | 'mode'>;
manifest?: UserManifest;
server?: WxtDevServer;
runner?: ExtensionRunnerConfig;
}
export interface WxtInlineViteConfig
@@ -177,3 +178,68 @@ export type UserManifest = Omit<
| 'version'
| 'version_name'
>;
/**
* Configure how the browser starts up.
*/
export interface ExtensionRunnerConfig {
/**
* @see https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#browser-console
*/
openConsole?: boolean;
/**
* @see https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#devtools
*/
openDevtools?: boolean;
/**
* List of browser names and the binary that should be used to open the browser.
*/
binaries?: {
/**
* @see https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#chromium-binary
*/
chrome?: string;
/**
* @see https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#chromium-binary
*/
edge?: string;
/**
* @see https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#chromium-binary
*/
opera?: string;
/**
* @see https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#firefox
*/
firefox?:
| 'firefox'
| 'beta'
| 'nightly'
| 'deved'
| 'firefoxdeveloperedition'
| string;
};
/**
* @see https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#firefox-profile
*/
firefoxProfile?: string;
/**
* @see https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#chromium-profile
*/
chromiumProfile?: string;
/**
* @see https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#pref
*/
firefoxPrefs?: Record<string, string>;
/**
* @see https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#args
*/
firefoxArgs?: string[];
/**
* @see https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#args
*/
chromiumArgs?: string[];
/**
* @see https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#start-url
*/
startUrls?: string[];
}
+3
View File
@@ -6,8 +6,10 @@ import {
TargetBrowser,
TargetManifestVersion,
UserManifest,
ExtensionRunnerConfig,
} from './external';
import { UnimportOptions } from 'unimport';
import { ResolvedConfig } from 'c12';
export interface InternalConfig {
root: string;
@@ -33,6 +35,7 @@ export interface InternalConfig {
manifest: UserManifest;
fsCache: FsCache;
server?: WxtDevServer;
runnerConfig: ResolvedConfig<ExtensionRunnerConfig>;
}
export type EntrypointGroup = Entrypoint | Entrypoint[];
+7
View File
@@ -0,0 +1,7 @@
import { ExtensionRunnerConfig } from '../types';
export function defineRunnerConfig(
config: ExtensionRunnerConfig,
): ExtensionRunnerConfig {
return config;
}
+14 -1
View File
@@ -1,4 +1,9 @@
import { InlineConfig, InternalConfig, UserConfig } from '../types';
import {
ExtensionRunnerConfig,
InlineConfig,
InternalConfig,
UserConfig,
} from '../types';
import path, { resolve } from 'node:path';
import * as vite from 'vite';
import { consola } from 'consola';
@@ -6,6 +11,7 @@ import { importTsFile } from './importTsFile';
import * as plugins from '../vite-plugins';
import { createFsCache } from './createFsCache';
import { getGlobals } from './globals';
import { loadConfig } from 'c12';
/**
* Given an inline config, discover the config file if necessary, merge the results, resolve any
@@ -39,6 +45,13 @@ export async function getInternalConfig(
vite: config.vite ?? {},
manifest: config.manifest ?? {},
imports: config.imports ?? {},
runnerConfig: await loadConfig<ExtensionRunnerConfig>({
name: 'web-ext',
cwd: root,
globalRc: true,
rcFile: '.webextrc',
overrides: config.runner,
}),
};
// Load user config from file