Skip to content

Commit

Permalink
✨ improve(patch): prevent duplicate entrypoint imports (#2451)
Browse files Browse the repository at this point in the history
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**
  • Loading branch information
kellymears committed Sep 20, 2023
1 parent c77770f commit 93e8600
Showing 1 changed file with 8 additions and 2 deletions.
10 changes: 8 additions & 2 deletions sources/@roots/bud-build/src/config/entry.ts
Original file line number Diff line number Diff line change
@@ -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}
}, {})
}

0 comments on commit 93e8600

Please sign in to comment.