feat: Open browser when starting dev server (#11)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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": {
|
||||
|
||||
Generated
+3831
-67
File diff suppressed because it is too large
Load Diff
Vendored
+32
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import { InternalConfig } from '../types';
|
||||
|
||||
export interface ExtensionRunner {
|
||||
openBrowser(config: InternalConfig): Promise<void>;
|
||||
closeBrowser(): Promise<void>;
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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[];
|
||||
}
|
||||
|
||||
@@ -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[];
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { ExtensionRunnerConfig } from '../types';
|
||||
|
||||
export function defineRunnerConfig(
|
||||
config: ExtensionRunnerConfig,
|
||||
): ExtensionRunnerConfig {
|
||||
return config;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user