chore: Refactor build output type (#19)
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
import * as vite from 'vite';
|
||||
import { BuildOutput, Entrypoint, InternalConfig } from '../types';
|
||||
import { groupEntrypoints } from '../utils/groupEntrypoints';
|
||||
import {
|
||||
BuildOutput,
|
||||
BuildStepOutput,
|
||||
Entrypoint,
|
||||
EntrypointGroup,
|
||||
InternalConfig,
|
||||
} from '../types';
|
||||
import * as plugins from '../vite-plugins';
|
||||
import { removeEmptyDirs } from '../utils/removeEmptyDirs';
|
||||
import { getEntrypointBundlePath } from '../utils/entrypoints';
|
||||
@@ -9,25 +14,22 @@ import fs from 'fs-extra';
|
||||
import { dirname, resolve } from 'path';
|
||||
|
||||
export async function buildEntrypoints(
|
||||
entrypoints: Entrypoint[],
|
||||
groups: EntrypointGroup[],
|
||||
config: InternalConfig,
|
||||
): Promise<BuildOutput> {
|
||||
const groups = groupEntrypoints(entrypoints);
|
||||
|
||||
const outputs: BuildOutput[] = [];
|
||||
): Promise<Omit<BuildOutput, 'manifest'>> {
|
||||
const steps: BuildStepOutput[] = [];
|
||||
for (const group of groups) {
|
||||
const output = Array.isArray(group)
|
||||
const step = Array.isArray(group)
|
||||
? await buildMultipleEntrypoints(group, config)
|
||||
: await buildSingleEntrypoint(group, config);
|
||||
outputs.push(output);
|
||||
steps.push(step);
|
||||
}
|
||||
const publicOutput = await copyPublicDirectory(config);
|
||||
outputs.push(publicOutput);
|
||||
const publicAssets = await copyPublicDirectory(config);
|
||||
|
||||
// Remove any empty directories from moving outputs around
|
||||
await removeEmptyDirs(config.outDir);
|
||||
|
||||
return outputs.flat();
|
||||
return { publicAssets, steps };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,7 +38,7 @@ export async function buildEntrypoints(
|
||||
async function buildSingleEntrypoint(
|
||||
entrypoint: Entrypoint,
|
||||
config: InternalConfig,
|
||||
): Promise<BuildOutput> {
|
||||
): Promise<BuildStepOutput> {
|
||||
// Should this entrypoint be wrapped by the vite-plugins/virtualEntrypoint plugin?
|
||||
const isVirtual = ['background', 'content-script'].includes(entrypoint.type);
|
||||
const entry = isVirtual
|
||||
@@ -74,7 +76,10 @@ async function buildSingleEntrypoint(
|
||||
) as vite.InlineConfig;
|
||||
|
||||
const result = await vite.build(entryConfig);
|
||||
return getBuildOutput(result);
|
||||
return {
|
||||
entrypoints: entrypoint,
|
||||
chunks: getBuildOutputChunks(result),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,7 +88,7 @@ async function buildSingleEntrypoint(
|
||||
async function buildMultipleEntrypoints(
|
||||
entrypoints: Entrypoint[],
|
||||
config: InternalConfig,
|
||||
): Promise<BuildOutput> {
|
||||
): Promise<BuildStepOutput> {
|
||||
const multiPage: vite.InlineConfig = {
|
||||
plugins: [plugins.multipageMove(entrypoints, config)],
|
||||
build: {
|
||||
@@ -110,12 +115,15 @@ async function buildMultipleEntrypoints(
|
||||
) as vite.InlineConfig;
|
||||
|
||||
const result = await vite.build(entryConfig);
|
||||
return getBuildOutput(result);
|
||||
return {
|
||||
entrypoints,
|
||||
chunks: getBuildOutputChunks(result),
|
||||
};
|
||||
}
|
||||
|
||||
function getBuildOutput(
|
||||
function getBuildOutputChunks(
|
||||
result: Awaited<ReturnType<typeof vite.build>>,
|
||||
): BuildOutput {
|
||||
): BuildStepOutput['chunks'] {
|
||||
if ('on' in result) throw Error('wxt does not support vite watch mode.');
|
||||
if (Array.isArray(result)) return result.flatMap(({ output }) => output);
|
||||
return result.output;
|
||||
@@ -123,19 +131,19 @@ function getBuildOutput(
|
||||
|
||||
async function copyPublicDirectory(
|
||||
config: InternalConfig,
|
||||
): Promise<BuildOutput> {
|
||||
if (!(await fs.exists(config.publicDir))) return [];
|
||||
): Promise<BuildOutput['publicAssets']> {
|
||||
const publicAssets: BuildOutput['publicAssets'] = [];
|
||||
if (!(await fs.exists(config.publicDir))) return publicAssets;
|
||||
|
||||
const files = await glob('**/*', { cwd: config.publicDir });
|
||||
|
||||
const outputs: BuildOutput = [];
|
||||
for (const file of files) {
|
||||
const srcPath = resolve(config.publicDir, file);
|
||||
const outPath = resolve(config.outDir, file);
|
||||
|
||||
await fs.ensureDir(dirname(outPath));
|
||||
await fs.copyFile(srcPath, outPath);
|
||||
outputs.push({
|
||||
publicAssets.push({
|
||||
type: 'asset',
|
||||
fileName: file,
|
||||
name: file,
|
||||
@@ -143,5 +151,6 @@ async function copyPublicDirectory(
|
||||
source: await fs.readFile(srcPath),
|
||||
});
|
||||
}
|
||||
return outputs;
|
||||
|
||||
return publicAssets;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,10 @@ export async function printBuildSummary(
|
||||
output: BuildOutput,
|
||||
config: InternalConfig,
|
||||
) {
|
||||
const chunks = output.sort((l, r) => {
|
||||
const chunks = [
|
||||
...output.steps.flatMap((step) => step.chunks),
|
||||
...output.publicAssets,
|
||||
].sort((l, r) => {
|
||||
const lWeight =
|
||||
CHUNK_SORT_WEIGHTS[l.fileName] ??
|
||||
CHUNK_SORT_WEIGHTS[extname(l.fileName)] ??
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as vite from 'vite';
|
||||
import { Manifest } from 'webextension-polyfill';
|
||||
import { UnimportOptions } from 'unimport';
|
||||
import { EntrypointGroup } from '.';
|
||||
|
||||
export interface InlineConfig {
|
||||
root?: string;
|
||||
@@ -29,7 +30,16 @@ export interface WxtInlineViteConfig
|
||||
build?: Omit<vite.BuildOptions, 'outDir'>;
|
||||
}
|
||||
|
||||
export type BuildOutput = (vite.Rollup.OutputChunk | vite.Rollup.OutputAsset)[];
|
||||
export interface BuildOutput {
|
||||
manifest: Manifest.WebExtensionManifest;
|
||||
publicAssets: vite.Rollup.OutputAsset[];
|
||||
steps: BuildStepOutput[];
|
||||
}
|
||||
|
||||
export interface BuildStepOutput {
|
||||
entrypoints: EntrypointGroup;
|
||||
chunks: (vite.Rollup.OutputChunk | vite.Rollup.OutputAsset)[];
|
||||
}
|
||||
|
||||
export interface WxtDevServer extends vite.ViteDevServer {
|
||||
logger: Logger;
|
||||
|
||||
@@ -29,7 +29,7 @@ export async function writeManifest(
|
||||
await fs.ensureDir(config.outDir);
|
||||
await fs.writeFile(resolve(config.outDir, 'manifest.json'), str, 'utf-8');
|
||||
|
||||
output.unshift({
|
||||
output.publicAssets.unshift({
|
||||
type: 'asset',
|
||||
fileName: 'manifest.json',
|
||||
name: 'manifest',
|
||||
@@ -43,7 +43,7 @@ export async function writeManifest(
|
||||
*/
|
||||
export async function generateMainfest(
|
||||
entrypoints: Entrypoint[],
|
||||
buildOutput: BuildOutput,
|
||||
buildOutput: Omit<BuildOutput, 'manifest'>,
|
||||
config: InternalConfig,
|
||||
): Promise<Manifest.WebExtensionManifest> {
|
||||
const pkg = await getPackageJson(config);
|
||||
@@ -100,7 +100,7 @@ function simplifyVersion(versionName: string): string {
|
||||
function addEntrypoints(
|
||||
manifest: Manifest.WebExtensionManifest,
|
||||
entrypoints: Entrypoint[],
|
||||
buildOutput: BuildOutput,
|
||||
buildOutput: Omit<BuildOutput, 'manifest'>,
|
||||
config: InternalConfig,
|
||||
): void {
|
||||
const entriesByType = entrypoints.reduce<
|
||||
@@ -351,12 +351,14 @@ function addDevModeCsp(
|
||||
*/
|
||||
function getContentScriptCssFiles(
|
||||
contentScripts: ContentScriptEntrypoint[],
|
||||
buildOutput: BuildOutput,
|
||||
buildOutput: Omit<BuildOutput, 'manifest'>,
|
||||
): string[] | undefined {
|
||||
const css: string[] = [];
|
||||
|
||||
const allChunks = buildOutput.steps.flatMap((step) => step.chunks);
|
||||
|
||||
contentScripts.forEach((script) => {
|
||||
const relatedCss = buildOutput.find(
|
||||
const relatedCss = allChunks.find(
|
||||
(chunk) => chunk.fileName === `assets/${script.name}.css`,
|
||||
);
|
||||
if (relatedCss) css.push(relatedCss.fileName);
|
||||
|
||||
+37
-7
@@ -3,6 +3,7 @@ import {
|
||||
WxtDevServer,
|
||||
InlineConfig,
|
||||
InternalConfig,
|
||||
EntrypointGroup,
|
||||
} from './core/types';
|
||||
import { getInternalConfig } from './core/utils/getInternalConfig';
|
||||
import { findEntrypoints } from './core/build/findEntrypoints';
|
||||
@@ -16,6 +17,8 @@ import * as vite from 'vite';
|
||||
import { findOpenPort } from './core/utils/findOpenPort';
|
||||
import { formatDuration } from './core/utils/formatDuration';
|
||||
import { createWebExtRunner } from './core/runners/createWebExtRunner';
|
||||
import { groupEntrypoints } from './core/utils/groupEntrypoints';
|
||||
import { Manifest } from 'webextension-polyfill';
|
||||
|
||||
export { version } from '../package.json';
|
||||
export * from './core/types/external';
|
||||
@@ -90,14 +93,9 @@ async function buildInternal(config: InternalConfig): Promise<BuildOutput> {
|
||||
await fs.rm(config.outDir, { recursive: true, force: true });
|
||||
await fs.ensureDir(config.outDir);
|
||||
|
||||
// Build
|
||||
const entrypoints = await findEntrypoints(config);
|
||||
await generateTypesDir(entrypoints, config);
|
||||
const output = await buildEntrypoints(entrypoints, config);
|
||||
|
||||
// Write manifest
|
||||
const manifest = await generateMainfest(entrypoints, output, config);
|
||||
await writeManifest(manifest, output, config);
|
||||
const groups = groupEntrypoints(entrypoints);
|
||||
const { output } = await rebuild(config, groups);
|
||||
|
||||
// Post-build
|
||||
config.logger.success(
|
||||
@@ -107,3 +105,35 @@ async function buildInternal(config: InternalConfig): Promise<BuildOutput> {
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
export async function rebuild(
|
||||
config: InternalConfig,
|
||||
entrypointGroups: EntrypointGroup[],
|
||||
existingOutput: Omit<BuildOutput, 'manifest'> = {
|
||||
steps: [],
|
||||
publicAssets: [],
|
||||
},
|
||||
): Promise<{ output: BuildOutput; manifest: Manifest.WebExtensionManifest }> {
|
||||
// Build
|
||||
const allEntrypoints = await findEntrypoints(config);
|
||||
await generateTypesDir(allEntrypoints, config);
|
||||
const buildOutput = await buildEntrypoints(entrypointGroups, config);
|
||||
|
||||
const manifest = await generateMainfest(allEntrypoints, buildOutput, config);
|
||||
const output: BuildOutput = {
|
||||
manifest,
|
||||
...buildOutput,
|
||||
};
|
||||
|
||||
// Write manifest
|
||||
await writeManifest(manifest, output, config);
|
||||
|
||||
return {
|
||||
output: {
|
||||
manifest,
|
||||
steps: [...existingOutput.steps, ...output.steps],
|
||||
publicAssets: [...existingOutput.publicAssets, ...output.publicAssets],
|
||||
},
|
||||
manifest,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user