parcel
parcel copied to clipboard
Importing SVG as react component does not work as mentioned in the docs.
🐛 bug report
I am trying to import SVG as react component based on the documentation from parcel site. Instead of the svg being rendered as a component in the page, the build actually fails. With an error - @parcel/core: No transformers found for src/assets/logo.jsx with pipeline: 'jsx'.
🎛 Configuration (.babelrc, package.json, cli command)
Using default babel configuration.
// package.json
{
"name": "parcel-react-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "parcel src/index.html"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@parcel/transformer-svg-react": "^2.2.1",
"parcel": "^2.2.1"
},
"dependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2"
}
}
// .parcelrc
{
"extends": "@parcel/config-default",
"transformers": {
"jsx:*.svg": ["...", "@parcel/transformer-svg-react"]
}
}
🤔 Expected Behavior
The svg image should be loaded as a react component in the webpage.
😯 Current Behavior
An error is thrown saying @parcel/core: No transformers found for src/assets/logo.jsx with pipeline: 'jsx'.
💁 Possible Solution
🔦 Context
I am trying to import a svg image as a react component.
💻 Code Sample
Clone this repo and run yarn && yarn run dev
🌍 Your Environment
Software | Version(s) |
---|---|
Parcel | 2.2.0 |
Node | 16.13.2 |
npm/Yarn | 8.1.2 / 1.22.17 |
Operating System | Windows 10 |
Attachments:
Im getting the very same, this is for quite a while. No one has got a workaround or a fix for it yet right?
One possible workaround is to add "jsx:*": ["..."]
below your existing svg transformer.
One possible workaround is to add
"jsx:*": ["..."]
below your existing svg transformer.
This actually makes it work. Should i consider this issue to be resolved?
No, its not resolved, this is a workaround not a fix.
One possible workaround is to add
"jsx:*": ["..."]
below your existing svg transformer.
When we apply this workaround the error is gone but parcel gets stuck Optimizing index.html...
Our .parcelrc:
{
"extends": "@parcel/config-default",
"transformers": {
"jsx:*.svg": ["...", "@parcel/transformer-svg-react"],
"jsx:*": ["..."],
"*.{js,mjs,jsx,cjs}": ["@parcel/transformer-js", "@parcel/transformer-react-refresh-wrap"]
}
}
By removing the last line, starting with *.{js,mjs,jsx,cjs}"
it suddenly works, though I am unsure if we still require this pipeline.
EDIT: Sadly there are still issues which I am unable to diagnose as the Website simply does not render. The only error I get is this:
same issue with "@parcel/transformer-svg-react": "^2.5.0"
@MLNW - I hit the same error that you did - I think it's related to #7389
I found two workarounds: (1) remove inline style props on any svgs you are importing through your jsx:*.svg
named pipeline or (2) remove the @transformer/svg
plugin from that pipeline (i.e. remove the "..."
entry, which includes this by default). The final config that worked for me was:
{
"extends": "@parcel/config-default",
"transformers": {
"jsx:*.svg": ["@parcel/transformer-svg-react"]
"jsx:*": ["..."]
}
}
@astegmaier I somehow missed your comment. It looks promising. Sadly I have moved on from the project for now so I can't test your solution at the moment
My project uses SVG files in 2 ways:
- Inline React components
import Icon from "./icon.svg";
function Component() {
return <Icon />;
}
- As img src
import icon from "./icon.svg";
function Component() {
return <img src={icon} />;
}
To make parcel work with this I had to:
- Rename inlined SVG files to
*.jsx.svg
- Update
.parcelrc
"transformers": {
"*.jsx.svg": ["@parcel/transformer-svg-react"],
"*.{js,mjs,jsx,cjs,ts,tsx}": [
"@parcel/transformer-js",
"@parcel/transformer-react-refresh-wrap"
]
}
- Add a type definition:
declare module '*.jsx.svg' {
import { FunctionComponent, SVGProps } from 'react';
const svg: FunctionComponent<SVGProps<SVGSVGElement> & { title?: string }>;
export default svg;
}
declare module '*.svg' {
const src: string;
export default src;
}
It's not ideal because I cannot use the same image file both inline and as image but it works.
While https://github.com/parcel-bundler/parcel/issues/7587#issuecomment-1117652812 works, this named pipeline conflicts with Storybook's webpack. Anyway to have it working without the named pipeline?
I kept the named pipeline and created this webpack plugin so storybook can remove the jsx:
from the import:
module.exports = function (source) {
return source.replace(/import\('jsx:(.*\.svg)'\)/g, "import('$1')")
}
And have it in the storybook's webpack rules' array:
{
test: /\.(ts|tsx)$/,
use: [
{
loader: path.resolve(__dirname, 'renameJsxImport.js'),
},
],
},