parcel
parcel copied to clipboard
css import in bundled ES module
🐛 bug report
🎛 Configuration
package.json
{
...
"source": "src/App/index.js",
"module": "dist/output.js",
"scripts": {
...
"start": "parcel src/index.html --dist-dir debug",
"build": "parcel build --no-content-hash --no-source-maps"
},
"targets": {
"module": {
"context": "browser",
"includeNodeModules": true,
"optimize": true
}
},
"alias": {
"process": {
"global": "{}"
}
},
"dependencies": {
"@popperjs/core": "^2.11.6",
"classnames": "^2.3.2",
"css-loader": "^6.8.1",
"cytoscape": "^3.25.0",
"cytoscape-fcose": "^2.2.0",
"cytoscape-node-html-label": "^1.2.2",
"cytoscape-popper": "^2.0.0",
"html2canvas": "^1.4.1",
"lodash.debounce": "^4.0.8",
"redux-batched-subscribe": "^0.1.6",
"redux-saga": "^1.2.3",
"tippy.js": "^2.6.0",
"vanjs-core": "^1.2.1"
},
"devDependencies": {
"@parcel/optimizer-data-url": "^2.11.0",
"@parcel/transformer-inline-string": "^2.11.0",
"@parcel/transformer-sass": "^2.11.0",
"@reduxjs/toolkit": "^1.9.5",
"@types/cytoscape": "^3.19.11",
"@types/cytoscape-fcose": "^2.2.4",
"@types/redux-batched-subscribe": "^0.1.4",
"parcel": "^2.11.0",
"process": "^0.11.10"
}
}
tsconfig.json
{
"compilerOptions": {
"baseUrl": "./src",
"target": "ES2019",
"module": "ES2020",
"allowJs": true,
"checkJs": true,
"moduleResolution": "node",
"paths": {
"/*": [
"../*"
],
}
},
"exclude": [
"dist",
"debug",
"public/example",
"node_modules"
]
}
🤔 Expected Behavior
css should not be imported into JS bundle
😯 Current Behavior
After build is done, i get following output in dist/output.js
:
import"./pcr.css";function t(t,e,n,r){Object.defineProperty(t,e,{get:n,set:r...
which obviously does not work in browser:
Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/css". Strict MIME type checking is enforced for module scripts per HTML spec.
is given for the import of pcr.css
💁 Possible Solution
not sure if my configuration is correct (was not really straightforward and took my a while to find proper settings in both parcel docs, github issues and stackoverflow), but generally, there's no reason to include CSS in browser
context
🔦 Context
export an app as a ES module that can be included in a webpage
💻 Code Sample
using (s)css modules in my JS, vanJS and redux, but not any opinionated framework such as React
...
import * as cssTab from './Components/ControlPanel/Tab/styles.module.scss';
import * as cssTabItem from './Components/ControlPanel/TabMenu/Item/styles.module.scss';
import * as style from 'bundle-text:scss/cytoscape.scss';
import 'scss/index.scss';
...
🌍 Your Environment
Software | Version(s) |
---|---|
Parcel | 2.11 |
Node | 18.17.0 |
npm/Yarn | 9.6.7 |
Operating System | Win11 x64 |
- Don't use
"module"
as the target name unless you're literally building some JS library to publish to npm/.... Call it "app" or anything other than module/main/browser - You imported CSS in your JS source file, so of course the Parcel output also contains the CSS import. Why don't use import the CSS in that
src/index.html
file?
hi, thanks for the answer
- even when i had
"library"
there, it did the same output. the only difference was, i was able to set"outputFormat"
which is disabled and auto-set for"module"
- as OP states, I'm using (S)CSS modules, so the imported
pcr.css
goes as follows:
._4EfISG_heading{letter-spacing:.0225rem;margin-top:0;margin-bottom:.625rem;font-size:1.125rem;font-weight:700}...
the only thing is the css import in the ES module really, it seems that context setting "browser"
does not seem to be considered during build. when i remove the above mentioned CSS import, the result is exactly what i want
@mischnic I am actually building a React library and wanted to use CSS modules so the class names don't clash with user's styles:
src/MyComponent.tsx
import { myClass } from "./MyComponent.module.css"
export function MyComponent() {
return <div className={myClass} />
}
src/MyComponent.module.css
.myClass {
border: 3px solid hotpink;
}
The user is supposed to import the js and css separately as described in this SO answer:
import "my-react-library/dist/style.css"
import { MyComponent } from "my-react-library"
I tried building it like that:
{
"name": "my-react-library",
"version": "1.0.0",
"type": "module",
"source": "src/MyComponent.tsx",
"main": "dist/module.js",
"types": "dist/types.d.ts",
"style": "dist/style.css", // this is ignored and uses the same name as js :( but that's ok
"scripts": {
"prepare": "parcel build",
},
"devDependencies": {
"@parcel/packager-ts": "^2.12.0",
"@parcel/transformer-typescript-types": "^2.12.0",
"parcel": "^2.12.0"
}
}
This almost works but includes the css import in js. It makes sense, because they're part of the same target with one entry point and one output js file.
It would be nice if there was a way to disable it for library mode and simply not include the css import. Even better if the style
key in package.json was considered a separate target which collects all the styles and ouputs a css bundle only.
I also just tried similar thing without CSS modules:
src/MyComponent.tsx
export function MyComponent() {
return <div className="myHopefullyUniqueClass" />
}
src/MyComponent.css
.myHopefullyUniqueClass {
border: 3px solid hotpink;
}
package.json
{
"source": "src/MyComponent.tsx",
"main": "dist/module.js",
"types": "dist/types.d.ts",
"style": "dist/style.css",
"targets": {
"main": {},
"types": {},
"style": {
"source": "src/MyComponent.css",
}
}
}
~~But I get an error from parcel:~~
Error: Expected content key 5777301ba3af460e to exist
Edit: nvm I cleared parcel cache and it worked. Also it doesn't work when target name is "style" but works if I change to "styles" for some reason.