chore: Refactor findEntrypoints to return all entrypoints with skipped set properly (#1244)
This commit is contained in:
@@ -75,3 +75,5 @@ Here are some examples:
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Alternatively, you can use the [`filterEntrypoints` config](/api/reference/wxt/interfaces/InlineConfig#filterentrypoints) to list all the entrypoints you want to build.
|
||||
|
||||
@@ -701,7 +701,7 @@ describe('findEntrypoints', () => {
|
||||
});
|
||||
|
||||
describe('include option', () => {
|
||||
it("should filter out the background when include doesn't contain the target browser", async () => {
|
||||
it("should mark the background as skipped when include doesn't contain the target browser", async () => {
|
||||
globMock.mockResolvedValueOnce(['background.ts']);
|
||||
importEntrypointMock.mockResolvedValue({
|
||||
include: ['not' + config.browser],
|
||||
@@ -709,10 +709,15 @@ describe('findEntrypoints', () => {
|
||||
|
||||
const entrypoints = await findEntrypoints();
|
||||
|
||||
expect(entrypoints).toEqual([]);
|
||||
expect(entrypoints).toEqual([
|
||||
expect.objectContaining({
|
||||
name: 'background',
|
||||
skipped: true,
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it("should filter out content scripts when include doesn't contain the target browser", async () => {
|
||||
it("should mark content scripts as skipped when include doesn't contain the target browser", async () => {
|
||||
globMock.mockResolvedValueOnce(['example.content.ts']);
|
||||
importEntrypointMock.mockResolvedValue({
|
||||
include: ['not' + config.browser],
|
||||
@@ -720,10 +725,15 @@ describe('findEntrypoints', () => {
|
||||
|
||||
const entrypoints = await findEntrypoints();
|
||||
|
||||
expect(entrypoints).toEqual([]);
|
||||
expect(entrypoints).toEqual([
|
||||
expect.objectContaining({
|
||||
name: 'example',
|
||||
skipped: true,
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it("should filter out the popup when include doesn't contain the target browser", async () => {
|
||||
it("should mark the popup as skipped when include doesn't contain the target browser", async () => {
|
||||
globMock.mockResolvedValueOnce(['popup.html']);
|
||||
readFileMock.mockResolvedValueOnce(
|
||||
`<html>
|
||||
@@ -737,10 +747,15 @@ describe('findEntrypoints', () => {
|
||||
|
||||
const entrypoints = await findEntrypoints();
|
||||
|
||||
expect(entrypoints).toEqual([]);
|
||||
expect(entrypoints).toEqual([
|
||||
expect.objectContaining({
|
||||
name: 'popup',
|
||||
skipped: true,
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it("should filter out the options page when include doesn't contain the target browser", async () => {
|
||||
it("should mark the options page as skipped when include doesn't contain the target browser", async () => {
|
||||
globMock.mockResolvedValueOnce(['options.html']);
|
||||
readFileMock.mockResolvedValueOnce(
|
||||
`<html>
|
||||
@@ -754,10 +769,15 @@ describe('findEntrypoints', () => {
|
||||
|
||||
const entrypoints = await findEntrypoints();
|
||||
|
||||
expect(entrypoints).toEqual([]);
|
||||
expect(entrypoints).toEqual([
|
||||
expect.objectContaining({
|
||||
name: 'options',
|
||||
skipped: true,
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it("should filter out an unlisted page when include doesn't contain the target browser", async () => {
|
||||
it("should mark unlisted pages as skipped when include doesn't contain the target browser", async () => {
|
||||
globMock.mockResolvedValueOnce(['unlisted.html']);
|
||||
readFileMock.mockResolvedValueOnce(
|
||||
`<html>
|
||||
@@ -771,12 +791,17 @@ describe('findEntrypoints', () => {
|
||||
|
||||
const entrypoints = await findEntrypoints();
|
||||
|
||||
expect(entrypoints).toEqual([]);
|
||||
expect(entrypoints).toEqual([
|
||||
expect.objectContaining({
|
||||
name: 'unlisted',
|
||||
skipped: true,
|
||||
}),
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('exclude option', () => {
|
||||
it('should filter out the background when exclude contains the target browser', async () => {
|
||||
it('should mark the background as skipped when exclude contains the target browser', async () => {
|
||||
globMock.mockResolvedValueOnce(['background.ts']);
|
||||
importEntrypointMock.mockResolvedValue({
|
||||
exclude: [config.browser],
|
||||
@@ -784,10 +809,15 @@ describe('findEntrypoints', () => {
|
||||
|
||||
const entrypoints = await findEntrypoints();
|
||||
|
||||
expect(entrypoints).toEqual([]);
|
||||
expect(entrypoints).toEqual([
|
||||
expect.objectContaining({
|
||||
name: 'background',
|
||||
skipped: true,
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('should filter out content scripts when exclude contains the target browser', async () => {
|
||||
it('should mark content scripts as skipped when exclude contains the target browser', async () => {
|
||||
globMock.mockResolvedValueOnce(['example.content.ts']);
|
||||
importEntrypointMock.mockResolvedValue({
|
||||
exclude: [config.browser],
|
||||
@@ -795,10 +825,15 @@ describe('findEntrypoints', () => {
|
||||
|
||||
const entrypoints = await findEntrypoints();
|
||||
|
||||
expect(entrypoints).toEqual([]);
|
||||
expect(entrypoints).toEqual([
|
||||
expect.objectContaining({
|
||||
name: 'example',
|
||||
skipped: true,
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('should filter out the popup when exclude contains the target browser', async () => {
|
||||
it('should mark the popup as skipped when exclude contains the target browser', async () => {
|
||||
globMock.mockResolvedValueOnce(['popup.html']);
|
||||
readFileMock.mockResolvedValueOnce(
|
||||
`<html>
|
||||
@@ -810,10 +845,15 @@ describe('findEntrypoints', () => {
|
||||
|
||||
const entrypoints = await findEntrypoints();
|
||||
|
||||
expect(entrypoints).toEqual([]);
|
||||
expect(entrypoints).toEqual([
|
||||
expect.objectContaining({
|
||||
name: 'popup',
|
||||
skipped: true,
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('should filter out the options page when exclude contains the target browser', async () => {
|
||||
it('should mark the options page as skipped when exclude contains the target browser', async () => {
|
||||
globMock.mockResolvedValueOnce(['options.html']);
|
||||
readFileMock.mockResolvedValueOnce(
|
||||
`<html>
|
||||
@@ -825,10 +865,15 @@ describe('findEntrypoints', () => {
|
||||
|
||||
const entrypoints = await findEntrypoints();
|
||||
|
||||
expect(entrypoints).toEqual([]);
|
||||
expect(entrypoints).toEqual([
|
||||
expect.objectContaining({
|
||||
name: 'options',
|
||||
skipped: true,
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('should filter out an unlisted page when exclude contains the target browser', async () => {
|
||||
it('should mark unlisted pages as skipped when exclude contains the target browser', async () => {
|
||||
globMock.mockResolvedValueOnce(['unlisted.html']);
|
||||
readFileMock.mockResolvedValueOnce(
|
||||
`<html>
|
||||
@@ -840,12 +885,17 @@ describe('findEntrypoints', () => {
|
||||
|
||||
const entrypoints = await findEntrypoints();
|
||||
|
||||
expect(entrypoints).toEqual([]);
|
||||
expect(entrypoints).toEqual([
|
||||
expect.objectContaining({
|
||||
name: 'unlisted',
|
||||
skipped: true,
|
||||
}),
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('filterEntrypoints option', () => {
|
||||
it('should control entrypoints accessible', async () => {
|
||||
it('should override include/exclude of individual entrypoint options', async () => {
|
||||
globMock.mockResolvedValue([
|
||||
'options/index.html',
|
||||
'popup/index.html',
|
||||
@@ -867,9 +917,25 @@ describe('findEntrypoints', () => {
|
||||
importEntrypointMock.mockResolvedValue({});
|
||||
|
||||
const entrypoints = await findEntrypoints();
|
||||
const names = entrypoints.map((item) => item.name);
|
||||
expect(names).toHaveLength(2);
|
||||
expect(names).toEqual(filterEntrypoints);
|
||||
|
||||
expect(entrypoints).toEqual([
|
||||
expect.objectContaining({
|
||||
name: 'injected',
|
||||
skipped: true,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
name: 'options',
|
||||
skipped: true,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
name: 'popup',
|
||||
skipped: false,
|
||||
}),
|
||||
expect.objectContaining({
|
||||
name: 'ui',
|
||||
skipped: false,
|
||||
}),
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -152,12 +152,16 @@ describe('groupEntrypoints', () => {
|
||||
options: {
|
||||
type: 'module',
|
||||
},
|
||||
skipped: false,
|
||||
});
|
||||
const popup = fakePopupEntrypoint({
|
||||
skipped: false,
|
||||
});
|
||||
const popup = fakePopupEntrypoint();
|
||||
const sandbox = fakeGenericEntrypoint({
|
||||
inputPath: '/entrypoints/sandbox.html',
|
||||
name: 'sandbox',
|
||||
type: 'sandbox',
|
||||
skipped: false,
|
||||
});
|
||||
|
||||
const actual = groupEntrypoints([background, popup, sandbox]);
|
||||
@@ -165,6 +169,22 @@ describe('groupEntrypoints', () => {
|
||||
expect(actual).toEqual([[background, popup], [sandbox]]);
|
||||
});
|
||||
|
||||
it('should exclude skipped entrypoints from the groups to build', () => {
|
||||
const background = fakeBackgroundEntrypoint({
|
||||
options: {
|
||||
type: 'module',
|
||||
},
|
||||
skipped: false,
|
||||
});
|
||||
const popup = fakePopupEntrypoint({
|
||||
skipped: true,
|
||||
});
|
||||
|
||||
const actual = groupEntrypoints([background, popup]);
|
||||
|
||||
expect(actual).toEqual([[background]]);
|
||||
});
|
||||
|
||||
it.todo(
|
||||
'should group ESM compatible sandbox scripts with sandbox pages',
|
||||
() => {
|
||||
|
||||
@@ -65,14 +65,7 @@ export async function findEntrypoints(): Promise<Entrypoint[]> {
|
||||
);
|
||||
if (matchingGlob) {
|
||||
const type = PATH_GLOB_TO_TYPE_MAP[matchingGlob];
|
||||
results.push({
|
||||
name,
|
||||
inputPath,
|
||||
type,
|
||||
skipped:
|
||||
wxt.config.filterEntrypoints != null &&
|
||||
!wxt.config.filterEntrypoints.has(name),
|
||||
});
|
||||
results.push({ name, inputPath, type });
|
||||
}
|
||||
return results;
|
||||
}, []);
|
||||
@@ -84,7 +77,7 @@ export async function findEntrypoints(): Promise<Entrypoint[]> {
|
||||
// Import entrypoints to get their config
|
||||
let hasBackground = false;
|
||||
const env = createExtensionEnvironment();
|
||||
const entrypoints: Entrypoint[] = await env.run(() =>
|
||||
const entrypointsWithoutSkipped: Entrypoint[] = await env.run(() =>
|
||||
Promise.all(
|
||||
entrypointInfos.map(async (info): Promise<Entrypoint> => {
|
||||
const { type } = info;
|
||||
@@ -130,61 +123,44 @@ export async function findEntrypoints(): Promise<Entrypoint[]> {
|
||||
);
|
||||
|
||||
if (wxt.config.command === 'serve' && !hasBackground) {
|
||||
entrypoints.push(
|
||||
entrypointsWithoutSkipped.push(
|
||||
await getBackgroundEntrypoint({
|
||||
inputPath: VIRTUAL_NOOP_BACKGROUND_MODULE_ID,
|
||||
name: 'background',
|
||||
type: 'background',
|
||||
skipped: false,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// Mark entrypoints as skipped or not
|
||||
const entrypoints = entrypointsWithoutSkipped.map((entry) => ({
|
||||
...entry,
|
||||
skipped: isEntrypointSkipped(entry),
|
||||
}));
|
||||
|
||||
wxt.logger.debug('All entrypoints:', entrypoints);
|
||||
const skippedEntrypointNames = entrypointInfos
|
||||
const skippedEntrypointNames = entrypoints
|
||||
.filter((item) => item.skipped)
|
||||
.map((item) => item.name);
|
||||
if (skippedEntrypointNames.length) {
|
||||
wxt.logger.warn(
|
||||
`Filter excluded the following entrypoints:\n${skippedEntrypointNames
|
||||
.map((item) => `${pc.dim('-')} ${pc.cyan(item)}`)
|
||||
.join('\n')}`,
|
||||
[
|
||||
'The following entrypoints have been skipped:',
|
||||
...skippedEntrypointNames.map(
|
||||
(item) => `${pc.dim('-')} ${pc.cyan(item)}`,
|
||||
),
|
||||
].join('\n'),
|
||||
);
|
||||
}
|
||||
const targetEntrypoints = entrypoints.filter((entry) => {
|
||||
const { include, exclude } = entry.options;
|
||||
if (include?.length && exclude?.length) {
|
||||
wxt.logger.warn(
|
||||
`The ${entry.name} entrypoint lists both include and exclude, but only one can be used per entrypoint. Entrypoint ignored.`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (exclude?.length && !include?.length) {
|
||||
return !exclude.includes(wxt.config.browser);
|
||||
}
|
||||
if (include?.length && !exclude?.length) {
|
||||
return include.includes(wxt.config.browser);
|
||||
}
|
||||
if (skippedEntrypointNames.includes(entry.name)) {
|
||||
return false;
|
||||
}
|
||||
await wxt.hooks.callHook('entrypoints:resolved', wxt, entrypoints);
|
||||
|
||||
return true;
|
||||
});
|
||||
wxt.logger.debug(`${wxt.config.browser} entrypoints:`, targetEntrypoints);
|
||||
await wxt.hooks.callHook('entrypoints:resolved', wxt, targetEntrypoints);
|
||||
|
||||
return targetEntrypoints;
|
||||
return entrypoints;
|
||||
}
|
||||
|
||||
interface EntrypointInfo {
|
||||
name: string;
|
||||
inputPath: string;
|
||||
type: Entrypoint['type'];
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
skipped: boolean;
|
||||
}
|
||||
|
||||
function preventDuplicateEntrypointNames(files: EntrypointInfo[]) {
|
||||
@@ -252,7 +228,6 @@ async function getPopupEntrypoint(
|
||||
options: resolvePerBrowserOptions(options, wxt.config.browser),
|
||||
inputPath: info.inputPath,
|
||||
outputDir: wxt.config.outDir,
|
||||
skipped: info.skipped,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -275,7 +250,6 @@ async function getOptionsEntrypoint(
|
||||
options: resolvePerBrowserOptions(options, wxt.config.browser),
|
||||
inputPath: info.inputPath,
|
||||
outputDir: wxt.config.outDir,
|
||||
skipped: info.skipped,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -293,14 +267,12 @@ async function getUnlistedPageEntrypoint(
|
||||
inputPath: info.inputPath,
|
||||
outputDir: wxt.config.outDir,
|
||||
options,
|
||||
skipped: info.skipped,
|
||||
};
|
||||
}
|
||||
|
||||
async function getUnlistedScriptEntrypoint({
|
||||
inputPath,
|
||||
name,
|
||||
skipped,
|
||||
}: EntrypointInfo): Promise<GenericEntrypoint> {
|
||||
const defaultExport =
|
||||
await wxt.builder.importEntrypoint<UnlistedScriptDefinition>(inputPath);
|
||||
@@ -316,14 +288,12 @@ async function getUnlistedScriptEntrypoint({
|
||||
inputPath,
|
||||
outputDir: wxt.config.outDir,
|
||||
options: resolvePerBrowserOptions(options, wxt.config.browser),
|
||||
skipped,
|
||||
};
|
||||
}
|
||||
|
||||
async function getBackgroundEntrypoint({
|
||||
inputPath,
|
||||
name,
|
||||
skipped,
|
||||
}: EntrypointInfo): Promise<BackgroundEntrypoint> {
|
||||
let options: Omit<BackgroundDefinition, 'main'> = {};
|
||||
if (inputPath !== VIRTUAL_NOOP_BACKGROUND_MODULE_ID) {
|
||||
@@ -348,14 +318,12 @@ async function getBackgroundEntrypoint({
|
||||
inputPath,
|
||||
outputDir: wxt.config.outDir,
|
||||
options: resolvePerBrowserOptions(options, wxt.config.browser),
|
||||
skipped,
|
||||
};
|
||||
}
|
||||
|
||||
async function getContentScriptEntrypoint({
|
||||
inputPath,
|
||||
name,
|
||||
skipped,
|
||||
}: EntrypointInfo): Promise<ContentScriptEntrypoint> {
|
||||
const defaultExport =
|
||||
await wxt.builder.importEntrypoint<ContentScriptDefinition>(inputPath);
|
||||
@@ -377,7 +345,6 @@ async function getContentScriptEntrypoint({
|
||||
inputPath,
|
||||
outputDir: resolve(wxt.config.outDir, CONTENT_SCRIPT_OUT_DIR),
|
||||
options: resolvePerBrowserOptions(options, wxt.config.browser),
|
||||
skipped,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -409,7 +376,6 @@ async function getSidepanelEntrypoint(
|
||||
options: resolvePerBrowserOptions(options, wxt.config.browser),
|
||||
inputPath: info.inputPath,
|
||||
outputDir: wxt.config.outDir,
|
||||
skipped: info.skipped,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -457,6 +423,29 @@ async function getHtmlEntrypointOptions<T extends BaseEntrypointOptions>(
|
||||
return options;
|
||||
}
|
||||
|
||||
function isEntrypointSkipped(entry: Omit<Entrypoint, 'skipped'>): boolean {
|
||||
if (wxt.config.filterEntrypoints != null) {
|
||||
return !wxt.config.filterEntrypoints.has(entry.name);
|
||||
}
|
||||
|
||||
const { include, exclude } = entry.options;
|
||||
if (include?.length && exclude?.length) {
|
||||
wxt.logger.warn(
|
||||
`The ${entry.name} entrypoint lists both include and exclude, but only one can be used per entrypoint. Entrypoint skipped.`,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (exclude?.length && !include?.length) {
|
||||
return exclude.includes(wxt.config.browser);
|
||||
}
|
||||
if (include?.length && !exclude?.length) {
|
||||
return !include.includes(wxt.config.browser);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const PATH_GLOB_TO_TYPE_MAP: Record<string, Entrypoint['type']> = {
|
||||
'sandbox.html': 'sandbox',
|
||||
'sandbox/index.html': 'sandbox',
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Entrypoint, EntrypointGroup } from '../../../types';
|
||||
|
||||
/**
|
||||
* Entrypoints can be build in groups. HTML pages can all be built together in a single step, while
|
||||
* content scripts must be build individually.
|
||||
* Entrypoints are built in groups. HTML pages can all be built together in a single step,
|
||||
* content scripts must be build individually, etc.
|
||||
*
|
||||
* This function returns the entrypoints put into these types of groups.
|
||||
*/
|
||||
@@ -11,6 +11,8 @@ export function groupEntrypoints(entrypoints: Entrypoint[]): EntrypointGroup[] {
|
||||
const groups: EntrypointGroup[] = [];
|
||||
|
||||
for (const entry of entrypoints) {
|
||||
if (entry.skipped) continue;
|
||||
|
||||
let group = ENTRY_TYPE_TO_GROUP_MAP[entry.type];
|
||||
if (entry.type === 'background' && entry.options.type === 'module') {
|
||||
group = 'esm';
|
||||
|
||||
@@ -45,6 +45,7 @@ export interface InlineConfig {
|
||||
* A list of entrypoint names (`"popup"`, `"options"`, etc.) to build. Will speed up the build if
|
||||
* your extension has lots of entrypoints, and you don't need to build all of them to develop a
|
||||
* feature.
|
||||
* If specified, this completely overrides the `include`/`exclude` option provided per-entrypoint.
|
||||
*/
|
||||
filterEntrypoints?: string[];
|
||||
/**
|
||||
@@ -728,7 +729,14 @@ export interface BaseEntrypoint {
|
||||
* subdirectory of it.
|
||||
*/
|
||||
outputDir: string;
|
||||
skipped: boolean;
|
||||
/**
|
||||
* When true, the entrypoint will not be built by WXT. Normally this is set
|
||||
* based on the `filterEntrypoints` config or the entrypoint's
|
||||
* `include`/`exclude` options defined inside the file.
|
||||
*
|
||||
* See https://wxt.dev/guide/essentials/target-different-browsers.html#filtering-entrypoints
|
||||
*/
|
||||
skipped?: boolean;
|
||||
}
|
||||
|
||||
export interface GenericEntrypoint extends BaseEntrypoint {
|
||||
|
||||
Reference in New Issue
Block a user