From 93e860013190fcc273be92eaf4bfb423e1d5ed90 Mon Sep 17 00:00:00 2001 From: Kelly Mears Date: Wed, 20 Sep 2023 01:01:56 -0400 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20improve(patch):=20prevent=20duplica?= =?UTF-8?q?te=20entrypoint=20imports=20(#2451)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prevent duplicate entrypoint imports. It is relatively easy to reproduce this. Just add a duplicate module to an entrypoint: ```ts bud.entry({ app: ['@scripts/app', '@scripts/app'], }) ``` Before compilation, bud.js validates the configuration using webpack's validation API. At this point the following error is observed: ```txt ValidationError ✘ Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema. - configuration[0].entry['app'].import should not contain the item '@scripts/app' twice. -> All modules are loaded upon startup. The last one is exported. ``` Initially, I thought about tightening the [bud.entry](https://bud.js.org/reference/bud.entry) parameter validation to prevent this, but that could cause ecosystem problems. For example, if multiple extensions add the same module to an entrypoint. It would be possible to force extensions to check the imports array before adding a module, but this is more prone to error and doesn't confer any advantages. Since there is no scenario where a module would be intentionally included more than once it is better, I think, to dedupe each entrypoint's imports before compilation, which is what this PR does. The solution is simple: 1. the entrypoint imports are an array which may contain duplicate items 2. the imports array is cast to a Set (which cannot contain duplicates) 3. the Set is spread into a new array ## Type of change **PATCH: backwards compatible change** --- sources/@roots/bud-build/src/config/entry.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sources/@roots/bud-build/src/config/entry.ts b/sources/@roots/bud-build/src/config/entry.ts index 15358309d4..052f8fb785 100644 --- a/sources/@roots/bud-build/src/config/entry.ts +++ b/sources/@roots/bud-build/src/config/entry.ts @@ -1,4 +1,10 @@ import type {Factory} from '@roots/bud-build/config' -export const entry: Factory<`entry`> = async ({hooks}) => - hooks.filter(`build.entry`, {main: {import: [`index`]}}) +export const entry: Factory<`entry`> = async ({hooks}) => { + const entrypoints = hooks.filter(`build.entry`, {main: {import: [`index`]}}) + + return Object.entries(entrypoints).reduce((acc, [key, value]) => { + value.import = [...new Set(value.import)] + return {...acc, [key]: value} + }, {}) +}