material-components / material-components/material-web
Use bare specifier import for dependent components
Nobody has claimed this yet.
- Dominant language
- SCSS
- Stars
- 11.3k
- Forks
- 1.1k
- Avg merge
- 20h 28m
- Merged PRs (30d)
- 13
Description
What is affected?
Tooling
Description
As reported by a user on discord https://discord.com/channels/1012791295170859069/1076197552904491108/1165169545816846346
when components are loaded from CDNs like esm.run or esm.sh, they end up being bundled such that using multiple components can cause duplicate custom element registration errors.
CDN bundlers currently have no knowledge of all the entrypoints to the package to be able to deduplicate internal self imports. Using bare specifiers and package exports would help with this.
Reproduction
https://lit.dev/playground/#gist=73234f9745308e38a224d3eb92ca71ab
doing
import "https://esm.sh/@material/web/button/elevated-button.js";
import "https://esm.sh/@material/web/switch/switch.js";
produces error
Uncaught DOMException: Failed to execute 'define' on 'CustomElementRegistry': the name "md-focus-ring" has already been used with this registry
Workaround
Workaround is to use the all.js entrypoint to register everything at once, or don't use a CDN and use a build system to actually bundle the code being used yourself.
Using bare specifier imports internally would allow better deduplication control by these bundlers.
e.g.
https://github.com/material-components/material-web/blob/33e4293eca4f7056ed106f7247f12424dbc82290/button/internal/button.ts#L7-L8
could turn into
import '@material/web/focus/md-focus-ring.js';
import '@material/web/ripple/ripple.js';
Unfortunately, I think package exports is required for self reference in Node https://nodejs.org/api/packages.html#self-referencing-a-package-using-its-name.
So following should be added to package.json
{
"exports": {
"./button/*.js": "./button/*.js",
"./checkbox/*.js": "./checkbox/*.js",
... etc
}
}
This can be considered breaking unless absolutely every file that was accessible before, including internal files, is listed there.
Is this a regression?
No or unsure. This never worked, or I haven't tried before.
Affected versions
1.0.1
Browser/OS/Node environment
n/a
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with internal imports such as button/internal/button.ts and inspect package.json exports. Reproduce the duplicate md-focus-ring registration using the linked Lit playground, then assess replacing internal imports with bare package specifiers and exposing the required entrypoints without unintentionally hiding previously accessible files. Confirm the CDN imports no longer register the same custom element twice.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- build-system, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100