evanw / evanw/esbuild

Support Import attributes with options `format: 'esm'` and `splitting: true`.

Open
#4,368 3 comments 1 reaction 0 assignees View on GitHub
Dominant language
Go
Stars
40.1k
Forks
1.3k
PR merge metrics
No merged PRs in 30d

Description

As This example:
```
import stylesheet from "./index.css" with {type: 'css'};

export class Button extends HTMLElement {

static get is() {
return 'my-button';
}

#shadowRoot = this.attachShadow({ mode: 'closed' });

constructor() {
super();

this.#shadowRoot.adoptedStyleSheets.push(stylesheet);
}
}
customElements.define(Button.is, Button);
```
[Web components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components) + [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM) + [Import attributes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import/with) is frequently used in projects. But esbuld don't support `Import attributes`(see #3384 ), even with options `format: 'esm'` and `splitting: true`.
Why can't we keep this sentence of Import attributes just like then options `loader:{'.css': 'copy'}`?
Indeed, setting the 'loader: {'. css': 'copy' 'option seems to be a solution at present. But as it is written literally, it simply copies files and does not handle the functions already supported by `css loader` such as' @ import 'and' loader for image and font files'. What I want is if I can process the copied CSS files using the default CSS loader, it would be perfect.
At present, I can only write a plugin like the one below to temporarily handle this issue:
```
import { build } from "esbuild";
import type { PluginBuild } from "esbuild";

const cssConstructStylesheetPlugin = {
name: 'css imports',
setup(pluginBuild: PluginBuild) {
pluginBuild.onLoad({ filter: /\.css$/ }, async args => {
if (args.with['type'] === 'css') {
const result = await build({
bundle: true,
entryPoints: [args.path],
minify: pluginBuild.initialOptions.minify || true,
charset: 'utf8',
loader: {
'.woff2': 'dataurl',
'.gif': 'dataurl',
},
write: false,
});
return { contents: result.outputFiles[0]!.text, loader: 'copy' };
} else {
return { loader: 'empty' };
}
});
}
}

build({
entryPoints: [
'src/index.ts',
],
outdir: 'dist',
outbase: "src",
bundle: true,
minify: true,
format: 'esm',
charset: 'utf8',
splitting: true,
treeShaking: true,
plugins: [cssConstructStylesheetPlugin],
loader: {
'.html': 'text',
'.svg': 'text',
'.xml': 'text',
}
});
```

Currently, for the entire [Import attributes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import/with) proposal, except for the CSS file which needs to be processed using the `css loader` + `copy loader`, there is no problem with other references such as `copy loader`.

Finally, it turns out that I used machine translation to translate terrible English!

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the import-attributes behavior referenced in #3384 and the example build using format 'esm' and splitting: true. Compare the current loader: {'.css': 'copy'} workaround and plugin in the issue; done means CSS import attributes work while preserving CSS-loader handling of @import, images, and fonts.

Written by the indexing model from the issue text.

Assessment

Tech stack
css, go, javascript
Domain
build-system, compilers, web-dev
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.