parcel icon indicating copy to clipboard operation
parcel copied to clipboard

importing css modules results in Error: "Bundles must have unique names"

Open goldylucks opened this issue 2 years ago • 9 comments

🐛 bug report

// index.js
import * as classes from './index.module.css'

results in

Error: Bundles must have unique names

🎛 Configuration (.babelrc, package.json, cli command)

// .parcelrc
{
	"extends": "@parcel/config-webextension"
}

// babel.config.js
module.exports = {
	plugins: [
		[
			"@babel/plugin-proposal-decorators",
			{
				legacy: true,
			},
		],
		[
			"@babel/plugin-proposal-class-properties",
			{
				loose: true,
			},
		],
	],
	presets: [
		[
			"@babel/preset-env",
			{
				targets: {
					node: "current",
				},
				loose: true,
			},
		],
		"@babel/preset-react",
	],
}

// package.json
{
	"private": true,
	"scripts": {
		"build": "parcel build source/manifest.json --no-content-hash --no-source-maps --dist-dir distribution --no-cache --detailed-report 0",
		"lint": "run-p lint:*",
		"lint-fix": "run-p 'lint:* -- --fix'",
		"lint:css": "stylelint source/**/*.css",
		"lint:js": "xo",
		"eslint": "eslint source/**/*.js source/**/*.jsx",
		"test": "run-p lint:* build",
		"watch": "parcel watch source/manifest.json --dist-dir distribution --no-cache --no-hmr"
	},
	"husky": {
		"hooks": {
			"pre-commit": "lint-staged"
		}
	},
	"lint-staged": {
		"source/**/*.{js,jsx}": [
			"eslint",
			"prettier --write"
		],
		"source/**/*.css": [
			"prettier --write"
		]
	},
	"browserslist": [
		"last 1 Chrome version",
		"last 1 Firefox version"
	],
	"xo": {
		"envs": [
			"browser"
		],
		"rules": {
			"no-unused-vars": [
				"error",
				{
					"varsIgnorePattern": "browser"
				}
			]
		}
	},
	"stylelint": {
		"extends": "stylelint-config-xo"
	},
	"dependencies": {
		"@reduxjs/toolkit": "^1.8.0",
		"bootstrap": "^5.1.3",
		"react": "^17.0.2",
		"react-bootstrap": "^2.2.1",
		"react-bootstrap-typeahead": "^6.0.0-alpha.9",
		"react-dom": "^17.0.2",
		"react-redux": "^7.2.6",
		"react-toastify": "^8.2.0",
		"redux-saga": "^1.1.3",
		"webext-options-sync": "^3.0.1",
		"webextension-polyfill": "^0.8.0"
	},
	"devDependencies": {
		"@babel/core": "^7.17.7",
		"@babel/eslint-parser": "^7.17.0",
		"@babel/plugin-proposal-class-properties": "^7.16.7",
		"@babel/plugin-proposal-decorators": "^7.17.2",
		"@babel/preset-env": "^7.16.11",
		"@babel/preset-react": "^7.16.7",
		"@parcel/config-webextension": "^2.3.2",
		"@parcel/transformer-image": "^2.3.2",
		"axios": "^0.26.1",
		"eslint": "^8.11.0",
		"eslint-plugin-import": "^2.25.4",
		"eslint-plugin-react": "^7.29.3",
		"husky": "4",
		"lint-staged": "^12.3.7",
		"npm-run-all": "^4.1.5",
		"parcel": "^2.3.2",
		"postcss": "^8.0.0",
		"postcss-modules": "^4.3.0",
		"prettier": "^2.5.1",
		"process": "^0.11.10",
		"rollup-plugin-import-css": "^3.0.3",
		"stylelint": "^14.5.3",
		"stylelint-config-xo": "^0.20.1",
		"xo": "^0.48.0"
	},
	"webExt": {
		"sourceDir": "distribution"
	}
}

🤔 Expected Behavior

should work

😯 Current Behavior

throws the error

Error: Bundles must have unique names

  AssertionError [ERR_ASSERTION]: Bundles must have unique names
  at BundlerRunner.nameBundles
  (/Users/Goldy/apps/web-extension/node_modules/@parcel/core/lib/requests/BundleGraphRequest.js:343:23)
  at async BundlerRunner.bundle
  (/Users/Goldy/apps/web-extension/node_modules/@parcel/core/lib/requests/BundleGraphRequest.js:286:5)
  at async RequestTracker.runRequest
  (/Users/Goldy/apps/web-extension/node_modules/@parcel/core/lib/RequestTracker.js:725:20)
  at async Object.run
  (/Users/Goldy/apps/web-extension/node_modules/@parcel/core/lib/requests/ParcelBuildRequest.js:62:7)
  at async RequestTracker.runRequest
  (/Users/Goldy/apps/web-extension/node_modules/@parcel/core/lib/RequestTracker.js:725:20)
  at async Parcel._build
  (/Users/Goldy/apps/web-extension/node_modules/@parcel/core/lib/Parcel.js:397:11)
  at async Parcel._startNextBuild
  (/Users/Goldy/apps/web-extension/node_modules/@parcel/core/lib/Parcel.js:298:24)
  at async $b0fd219fea43bcac$export$2e2bcd8739ae039._runFn
  (/Users/Goldy/apps/web-extension/node_modules/@parcel/utils/lib/index.js:32645:13)
  at async $b0fd219fea43bcac$export$2e2bcd8739ae039._next
  (/Users/Goldy/apps/web-extension/node_modules/@parcel/utils/lib/index.js:32638:9)

💁 Possible Solution

no idea 🤷‍♀️

🔦 Context

trying to use css modules (alongside global css and npm css files, tho those work fine)

💻 Code Sample

// index.js
import * as classes from './index.module.css'

🌍 Your Environment

Software Version(s)
Parcel 2.3.2
Node v16.13.2
npm/Yarn yarn 1.22.17
Operating System Mac OS Monterey 12.2.1 (21D62) (Apple sillicon m1)

goldylucks avatar Mar 18 '22 10:03 goldylucks

Also tried adding this file with no effect:

// .postcssrc.js
module.exports = {
	modules: true,
	plugins: {
		"postcss-modules": {
			generateScopedName: "[folder]__[local]___[hash:base64:6]",
		},
	},
}

goldylucks avatar Mar 18 '22 10:03 goldylucks

do you have a reproduction we can try?

devongovett avatar Mar 18 '22 15:03 devongovett

sure, here it is: https://github.com/goldylucks/browser-extension-template

thanks for the help and getting back to me so promptly!

goldylucks avatar Mar 19 '22 02:03 goldylucks

Appears to be generating two bundles named content.css. This is because there is a content.css file referenced from manifest.json (marked as needsStableName, not sure if required), and the sibling CSS file for content.js also gets named content.css. I guess the namer needs to be a bit smarter about it.

Note: this is not specific to CSS modules, it could happen with any CSS file. As a workaround, you could either rename content.js or content.css to something else for now.

devongovett avatar Mar 21 '22 01:03 devongovett

but if I rename the file the collision will just happen for the new name no?

or am I missing smthn here?

goldylucks avatar Mar 21 '22 07:03 goldylucks

Parcel generates {name}.css from {name}.js file which imports CSS files. In this case, parcel generates content.css from content.js and this will lead a collision fo filename. so to rename content.js to {other than content}.js or content.css to {other than content}.css can be workaround.

Shinyaigeek avatar Mar 21 '22 08:03 Shinyaigeek

CSS Modules aren't currently supported in the web extension config. Although #7050 will fix this specific issue, it's still probably a good idea to work around name collisions in the default namer even if needsStableName is present on multiple assets with the same name.

101arrowz avatar Mar 30 '22 22:03 101arrowz

I am seeing the same bug with SVG files when I use parcel-namer-custom plugin. The plugin logs that the name() is being repeatedly being called on the same SVG file (I suspect this is because multiple references are being generated by prior SVG plugins). In any case, this prevents renaming the file unless one uses a hash in the renamed file.

Edit: I can confirm this is caused by SVG transformer plugin on larger SVG files. Turning it off will remove multiple invocation in the namer plugin.

CxRes avatar Aug 01 '22 18:08 CxRes

As the reason of #7230, I tried to remove import 'index.css'; manually, so I disabled the Source Map in package.json to avoid incorrect Debugging Break-point:

{
    "devDependencies": {
        "@parcel/packager-ts": "~2.7.0",
        "@parcel/transformer-less": "~2.7.0",
        "@parcel/transformer-typescript-types": "~2.7.0",
        "parcel": "~2.7.0",
        "typescript": "~4.7.4"
    },
    "browserslist": "> 0.5%, last 2 versions, not dead",
    "targets": {
+        "default": {
+            "sourceMap": false
+        },
        "main": {
            "optimize": true
        }
    },
    "scripts": {
        "build": "parcel build"
    }
}

But I got the same error:

AssertionError [ERR_ASSERTION]: Bundles must have unique names

If I replace the JSON option with the CLI parameter --no-source-maps, the building succeed with a warning:

> 4 | import * as style from './index.module.less';
>   |                        ^^^^^^^^^^^^^^^^^^^^^^ Cannot find module './index.module.less' or its corresponding type declarations.

Guys of @parcel-bundler team, you can find the reproduce code in idea2app/Idea-React#20.

TechQuery avatar Sep 05 '22 19:09 TechQuery