parcel-bundler / parcel

The zero configuration build tool for the web. πŸ“¦πŸš€
https://parceljs.org
MIT License
43.5k stars 2.27k forks source link

[Parcel 2]: Bundle group cannot have more than one entry bundle of the same type #6310

Closed TobiasSchikora closed 1 month ago

TobiasSchikora commented 3 years ago

πŸ› bug report

Hi together,

I am switching from Parcel 1 to Parcel 2 with a larger project. With Parcel 1 there are no problems. Parcel 2 shows the following error message: Bundle group cannot have more than one entry bundle of the same type.

My entrypoints are assets/src/*/*.js. There are 3 folders in src: mobile, desktop and shared. When I try to import the same file from assets/src/shared folder in assets/src/desktop/aaa.js as well as in assets/src/mobile/bbb.js, then the error occurs.

I saw the following code part:

(0, _assert().default)(entryBundlesOfType.length === 1, // Otherwise, we'd end up naming two bundles the same thing.
      'Bundle group cannot have more than one entry bundle of the same type');

which aborts the bundle. Why? And why does this work in parcel 1 without any problems? What can I do?

πŸŽ› Configuration (.babelrc, package.json, cli command)

"scripts": {
    "start": "npx parcel watch assets/src/*/*.js --public-url ../ --no-hmr",
    "build": "npx parcel build assets/src/*/*.js --no-source-maps --public-url ../"
  }

There is no difference if I use the --dist-dir cli option or the target in package.json.

πŸ€” Expected Behavior

The bundle should be created without any error messages. The files which were shared between desktop and mobile entrypoints should be in both entry output files. Parcel 1 does exactly what I expected.

😯 Current Behavior

The bundle aborts with an error message as follows:

AssertionError [ERR_ASSERTION]: Bundle group cannot have more than one entry bundle of the same type
    at Object.name (C:\mf\node_modules\@parcel\namer-default\lib\DefaultNamer.js:94:29)
    at BundlerRunner.nameBundle (C:\mf\node_modules\@parcel\core\lib\requests\BundleGraphRequest.js:494:39)
    at C:\mf\node_modules\@parcel\core\lib\requests\BundleGraphRequest.js:470:50
    at Array.map (<anonymous>)
    at BundlerRunner.nameBundles (C:\mf\node_modules\@parcel\core\lib\requests\BundleGraphRequest.js:470:31)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
    at async BundlerRunner.bundle (C:\mf\node_modules\@parcel\core\lib\requests\BundleGraphRequest.js:434:5)
    at async RequestTracker.runRequest (C:\mf\node_modules\@parcel\core\lib\RequestTracker.js:694:20)
    at async Parcel._build (C:\mf\node_modules\@parcel\core\lib\Parcel.js:661:25). 

πŸ”¦ Context

I try to share some modules between desktop and mobile (different) entrypoints. I have much entrypoints which are sharing some modules.

πŸ’» Code Sample

assets/src/desktop/main.js import '../shared/components/autologin';

assets/src/mobile/main.js import '../shared/components/autologin';

assets/src/shared/components/autologin.js // some code

🌍 Your Environment

Software Version(s)
Parcel 2.0.0-nightly.674
npm/Yarn 6.14.8 (npm)
Operating System Windows 10 Pro (20H2)
TobiasSchikora commented 3 years ago

No, unfortunately this was not the problem :( Everytime when I inport the same file in more than one entrypoint, I got this message.

mischnic commented 3 years ago

Please provide a complete code example that produces this error

TobiasSchikora commented 3 years ago

That is, what causes the problem:

a.js

import { FuncOne } from './legacy/legacy';
import AnotherFunc from 'another.js';

b.js

import { FuncTwo } from './legacy';`

legacy.js

import AnotherFunc from 'another.js';
export FuncOne;
export FuncTwo;

CLI-Command is: npx parcel watch a.js b.js

TobiasSchikora commented 3 years ago

Is there a command or cli parameter to debug where exactly it crashes?

TobiasSchikora commented 3 years ago

Can somebody explain in which cases the message β€žBundle group cannot have more than one entry bundle of the same typeβ€œ appears? Still looking for a solution :(

TobiasSchikora commented 3 years ago

Hi together,

I have uploaded a simplyfied version of my code which is not usable with parcel 2. My parcel cli command is: parcel watch src/*/*.js --dist-dir www/dist

The following link opens Google Drive (directory listing + download option):

https://drive.google.com/file/d/12A43L1qET1WjhY_uVGglF4yXAqzZTvfr/view?usp=sharing

I don't know if I do something wrong or this is a parcel 2 bug. In parcel 1 this example runs without any errors. Thanks for your help!

TobiasSchikora commented 3 years ago

It seems to be the same problem as described in https://github.com/parcel-bundler/parcel/discussions/5074

lgarron commented 3 years ago

I tried converting a project back to Parcel and am running into this. :-/

The output is really unhelpful, so I'm at a loss.

Repro:

git clone https://github.com/cubing/cubing.js && cd cubing.js
git checkout parcel-yet-again-again # 4a71add2091da6ab46dbf493f83a16d6d4d71428
npm install
make build-search-worker
npx parcel build src/sites/experiments-cubing-net/cubing-js/index.html

Output:

🚨 Build failed.

@parcel/namer-default: Bundle group cannot have more than one entry bundle of the same type

  AssertionError [ERR_ASSERTION]: Bundle group cannot have more than one entry bundle of the same type
  at Object.name
  (/Users/lgarron/Code/git/github.com/cubing/cubing.js/node_modules/@parcel/namer-default/lib/DefaultNamer.js:82:29)
  at BundlerRunner.nameBundle
  (/Users/lgarron/Code/git/github.com/cubing/cubing.js/node_modules/@parcel/core/lib/requests/BundleGraphRequest.js:346:39)
  at
  /Users/lgarron/Code/git/github.com/cubing/cubing.js/node_modules/@parcel/core/lib/requests/BundleGraphRequest.js:322:50
  at Array.map (<anonymous>)
  at BundlerRunner.nameBundles
  (/Users/lgarron/Code/git/github.com/cubing/cubing.js/node_modules/@parcel/core/lib/requests/BundleGraphRequest.js:322:31)
  at async BundlerRunner.bundle
  (/Users/lgarron/Code/git/github.com/cubing/cubing.js/node_modules/@parcel/core/lib/requests/BundleGraphRequest.js:283:5)
  at async RequestTracker.runRequest
  (/Users/lgarron/Code/git/github.com/cubing/cubing.js/node_modules/@parcel/core/lib/RequestTracker.js:711:20)
  at async Object.run
  (/Users/lgarron/Code/git/github.com/cubing/cubing.js/node_modules/@parcel/core/lib/requests/ParcelBuildRequest.js:57:21)
  at async RequestTracker.runRequest
  (/Users/lgarron/Code/git/github.com/cubing/cubing.js/node_modules/@parcel/core/lib/RequestTracker.js:711:20)
  at async Parcel._build
  (/Users/lgarron/Code/git/github.com/cubing/cubing.js/node_modules/@parcel/core/lib/Parcel.js:397:11)

Note that this works just fine for development:

npx parcel serve src/sites/experiments-cubing-net/cubing-js/index.html

(Also, the build process (but not the dev server) also runs into issues when folders have periods, so I renamed them for this repro.)

lgarron commented 3 years ago

I tried converting a project back to Parcel and am running into this. :-/

The output is really unhelpful, so I'm at a loss.

This is still a major issue for us.

I just tried 2.0.0-nightly.850 and we still get the same issue.

TobiasSchikora commented 3 years ago

Same here. Major issue. We can't update :'(

jlkawlfj commented 3 years ago

My files(entry points) were in the /src/pages/ folder and I was getting the this error, but when I moved all the entry points to /src/ it worked. I waiting fix.

before: "build": "parcel build src/pages/.jsx " after: "build": "parcel build src/.jsx "

TobiasSchikora commented 2 years ago

In the meantime it is the end of 2021 and there is still no feedback. We still have to use Parcel 1 because of this bug.

I have uploaded a code example to https://drive.google.com/file/d/12A43L1qET1WjhY_uVGglF4yXAqzZTvfr/view?usp=sharing.

My Parcel command is: parcel watch src/*/*.js --dist-dir www/dist.

Please help! We would love to update to Parcel 2.

mischnic commented 2 years ago

In @TobiasSchikora's case the problem is that it generates a shared CSS bundle, and one CSS bundle specific to just one of the entries. And because doing parcel build something.js generates something.js and something.css if there is a CSS import inside, there would be two something.css in this case.

TobiasSchikora commented 2 years ago

How does Parcel 1 handle this? (There are no problems). Do you think that this issue can be solved? I really love Parcel.

mischnic commented 2 years ago

Apparently it doesn't create a shared bundle.

2silver commented 2 years ago

Do you have any - maybe the same - browserlist/target configurations?

package.json

  "targets": {
    "mobile": {
      "engines": {
        "browsers": "> 0.5%, last 2 versions, not dead"
      }
    },
    "desktop": {
      "engines": {
        "browsers": "> 0.5%, last 2 versions, not dead"
      }
    }
  },
windware-ono commented 2 years ago

Is there a way to avoid this error?

I have this package.json targets with no other directives than package dependencies,

    "targets": {
        "site": {
            "source": "site/bundle.js",
            "distDir": "site/root/asset/",
            "publicUrl": "/asset/"
        },
        "admin": {
            "source": "admin/bundle.js",
            "distDir": "admin/root/asset/",
            "publicUrl": "/asset/"
        }
    },

and both of bundle.js have these lines

require('../style/*.styl')
require('./style/*.styl')

The former is a shared style files pointing to a same folder for both targets and the latter is local style files which differs for each targets.

Funny thing is that if there are no files in the local ./style/ folder, then somehow it bundles without an error but if I have a file in there, it errors with group bundle error but in that case if I remove the former shared style from being bundled, it works.

jptissot commented 2 years ago

Just ran into this as well. My setup is a bit different.

I was trying to use a glob pattern to build multiple package.json files under a folder.

 "scripts": {
    "watch": "parcel build apps/*'",

This gave the error above. The same thing occurs if I have a single package.json that has multiple targets.

danbrellis commented 2 years ago

Same issue for me as well with parcel 2.6.2

cli parcel watch 'modules/*.(js|scss)'

modules/a.js

import "./styles/a.scss
import * as helper from "components/helper";

helper.helper();

modules/b.js

import "./styles/b.scss
import * as helper from "components/helper";

helper.helper();

components/helper.js

import "./x-scroll.scss";
 exports.helper = () => {}
exports.helper();

When I remove the scss import from either a.js or b.js the error goes away.

TobiasSchikora commented 2 years ago

It seems that there is no interest to fix this :'(

danbrellis commented 2 years ago

@mischnic - do you have thoughts on a workaround (somehow disable shared bundles) or some indication if this would be addressed? Happy to help in any way I can!

judd-pathoftrees commented 2 years ago

I came across this issue when debugging a similar problem: I have two targets with different sources; js modules imported into each source were added to a shared bundle and only written to the output directory of the first target.

I was able to work around the problem by increasing the value of minBundles, as described under shared bundle configuration, to prevent the shared bundle being created (hat tip to @danbrellis for the 'disable shared bundles' idea).

This doesn't fix the original bug report, though I did get @TobiasSchikora's example to run by inlining the shared css import using transformer-inline as described at bundle inlining. However, running parcel build on this edited example causes Terser to throw a 'no file' error unless --no-optimize is used. It's hard to tell from the example if this is a viable workaround, but it could be worth exploring.

richardkmichael commented 1 year ago

I have this problem migrating a project to Parcel 2 as well.

I'm not familiar with the project's entry points, but based on @2silver hint, I naively removed the package.json browserslist config and now Parcel runs. I guess that's my starting point for entry point investigation.

dsibinski commented 1 year ago

I'm also facing this issue. The scenario is a bit different, but it's probably the same cause.

I have several sources defined in package.json:

"source": [
    "src/appsEntries/app1.ts",
    "src/appsEntries/app2.ts",
    "src/appsEntries/app3.ts"
  ]

Now I have two React files:

In Layout.tsx I import a common.styles.scss file:

// Layout.tsx
import "./common.styles.scss";

and in Component.tsx file I import a different styles file, another.scss:

// Component.tsx
import "../../assets/another.scss";

when building with parcel I'm getting an error:

🚨 Build failed.

@parcel/namer-default: Bundle group cannot have more than one entry bundle of the same type

  AssertionError [ERR_ASSERTION]: Bundle group cannot have more than one entry bundle of the same type
      at Object.name (C:\my-web-app\node_modules\@parcel\namer-default\lib\DefaultNamer.js:82:29)
      at BundlerRunner.nameBundle (C:\my-web-app\node_modules\@parcel\core\lib\requests\BundleGraphRequest.js:402:39)
      at C:\my-web-app\node_modules\@parcel\core\lib\requests\BundleGraphRequest.js:378:50
      at Array.map (<anonymous>)
      at BundlerRunner.nameBundles (C:\my-web-app\node_modules\@parcel\core\lib\requests\BundleGraphRequest.js:378:31)
      at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
      at async BundlerRunner.bundle (C:\my-web-app\node_modules\@parcel\core\lib\requests\BundleGraphRequest.js:341:7)
      at async Object.run (C:\my-web-app\node_modules\@parcel\core\lib\requests\BundleGraphRequest.js:156:17)
      at async RequestTracker.runRequest (C:\my-web-app\node_modules\@parcel\core\lib\RequestTracker.js:756:20)
      at async Object.run (C:\my-web-app\node_modules\@parcel\core\lib\requests\ParcelBuildRequest.js:56:7)

I'm attaching a sample app which reproduces this error: parcel-scss-issue.zip

Run npm install, then npm run build to see the error.

This is problematic, as it doesn't allow splitting styles in this use scenario πŸ˜₯ It would be great if there's a configuration option to either disable the same bundles names for specific cases or somehow override it.

crummy commented 1 year ago

For what it's worth, I've changed to Vite which seems to support this relatively easily.

Here's my vite.config.ts:

import {defineConfig} from 'vite'
import react from '@vitejs/plugin-react-swc'
import * as path from "path";

// https://vitejs.dev/config/
export default defineConfig(({mode}) => ({
    plugins: [react()],
    build: {
        manifest: true,
        rollupOptions: {
            input: {
                foo: __dirname + '/src/foo/index.tsx',
                bar: __dirname + '/src/bar/index.tsx',
                // ...etc
            },
        },
    },
}))

We have a dozen or so entry points and it's all straightforward.

lol768 commented 1 year ago

We also unfortunately moved to Vite.

jondlm commented 1 year ago

9023 might fix this issue also.

tcmulder commented 1 year ago

Any progress on this? Running into the same issue: "Bundle group cannot have more than one entry bundle of the same type" when trying to import the same file via separate entry points.

lol768 commented 1 year ago

Hate to say it, but my solution was just to move to Vite

tcmulder commented 1 year ago

For now, I'm bypassing the issue by creating a separate file that imports the file I'm after. Using @TobiasSchikora 's filename examples, assets/src/shared still contains the shared things I want in both aaa and bbb, but I don't import them directly into assets/src/desktop/aaa.js and assets/src/desktop/bbb.js: instead, assets/src/desktop/aaa.js imports assets/src/desktop/aaa-shared.css and assets/src/desktop/bbb.js imports assets/src/desktop/bbb-shared.css, both of which are simply:

@import "../shared/*.css";

Parcel seems fine with this since both imports get to the same files via different paths πŸ€·β€β™‚οΈ

It works for my use case which is just for reused CSS files (haven't tried this with JavaScript), though it's a bit ugly, and may not work for more complex needs. Still, it lets me just write my shared code once and import into aaa and bbb (with only a couple new lines/files I set up once and don't need to touch again) which is what I'm after.

jondlm commented 1 year ago

9023 is still being reviewed but I'm hopeful it'll fix this issue. I'm in the process of testing out the patch with one of our exhibiting codebases. I'll report back when I have a result.

dsibinski commented 11 months ago

any news here? After 2,5 years parcel still doesn't support two .scss files in the same project...

TobiasSchikora commented 11 months ago

Unfortunately not. And I don't think that will ever happen. We are currently in the process of porting our projects to other bundlers. This is really very sad.

jondlm commented 11 months ago

Sorry I forgot to report back. #9023 didn't fix the issue for me. I intend to find a solution to this issue since other bundlers can't scale for us the way Parcel can. Not sure when I'll get the time to dig deeply on this one but it'll happen.

chengr4 commented 7 months ago

Hi, I wonder if this is a complicated issue that only the maintainer can solve, or if someone can guide people by sharing info, for example, which codebase or related materials we can read to help this issue?

mischnic commented 7 months ago

With multiple JS entrypoints (e.g. entry1.js, entry2.js), Parcel would usually output the bundles dist/entry1.js with dist/entry1.css and dist/entry2.js with dist/entry2.css. Note that the names don't contain hashes because they have to be deterministic for you to be able to reference them wherever these end up being loaded.

Now Parcel tries to create shared bundles for CSS. Then one of the following can happen:

If I remember correctly, this should cover all of the cases I've seen so far.

EDIT: The reason that not everyone runs into this bug is that if you use HTML entries with Parcel, this works fine because there is no restriction to have deterministic names and so 2 CSS shared bundles are fine.

The code that determines which bundles are created and which files get put into which bundle is the bundler (docs).

As far as I can tell, Parcel doesn't actually create shared JS bundles across entry points, so not creating shared CSS bundles might be a solution here.

@devongovett Any thoughts?

chengr4 commented 7 months ago

@mischnic Thanks for your patient and kind response!

I would like to add our situation for your information: In rustc-perf, I believe we encountered case 3.

In short, the rustc-perf frontend has two entry points, entry1.js and entry2.js, both of which use the shared components A.js with scoped CSS and B.js without CSS.

flowchart LR
entry1.js -- use --> c["`
            A.js with scoped CSS
            B.js without CSS
           `"]
entry2.js -- use --> c

According to my observation, the shared B.js was successfully added to the respective entry1.js and entry2.js bundles. However, for A.js with scoped CSS, it showed the error message here.

My inference is although Parcel 2 doesn't actually create shared JS bundles, it successfully ensures that the shared JS is added to their respective bundles smoothly.

The issue appears to be caused solely by the CSS part. Perhaps a method could be found to ensure that CSS can be added to their respective bundles, just like JS component itself.

mischnic commented 7 months ago

One thing I should have noted in my comment: the reason that not everyone runs into this bug is that if you use HTML entries with Parcel, this works fine because there is no restriction to have deterministic names and so 2 CSS shared bundles are fine.

TobiasSchikora commented 1 month ago

I tried it again and now it works! Thank you very much for supporting it β™₯