Open bnussman-akamai opened 1 year ago
This is one of the fist things I encountered when I attempted to run my tests. Hope this gets resolved
So you're importing an .svg
here? Are you using some plugin to make this work with your current test runner? This doesn't appear to be supported in jest by default.
Yep, I am using vite-plugin-svgr
in order to be able to load .svg files as React components, e.g. import { ReactComponent as Logo } from "./logo.svg";
Vitest, which I use, picks up vite plugins so it can handle .svgs too.
The same "issue" is there when running bun build
as well. I guess bun needs some similar plugin in order to handle the .svg the same way?
This is the first blocking issue when migrating from Create React App.
seeing this too. import is:
import { ReactComponent as MyLogo } from './my-logo.svg'
yields:
SyntaxError: Import named 'ReactComponent' not found in module '/path/to/repo/my-logo.svg'.
We're using svgr
to import svgs as React Components.
I tried to use bun as test runner while webpack drives main application.
In order to mimic svg loading behavior accepted in our project (same as discussed in this issue, namely import { ReactComponent as Icon } from 'whatever.svg'
) I decided to write a simple plugin and came up with this solution. Don't forget to add @svgr/core
, @svgr/plugin-jsx
and @svgr/plugin-svgo
as dependencies, if you wanna use it.
# bunfig.toml
[test]
preload = ["./bunSvgPlugin.ts"]
// bunSvgPlugin.ts
import { plugin } from 'bun';
plugin({
name: 'SVG',
async setup(build) {
const { transform } = await import('@svgr/core');
const { readFileSync } = await import('fs');
build.onLoad({ filter: /\.(svg)$/ }, async args => {
const text = readFileSync(args.path, 'utf8');
const contents = await transform(
text,
{
icon: true,
exportType: 'named',
plugins: ['@svgr/plugin-svgo', '@svgr/plugin-jsx'],
},
{ componentName: 'ReactComponent' }
);
return {
contents,
loader: 'js', // not sure why js and not jsx, but it works only this way
};
});
},
});
Thank you a lot @wldyslw for your script, it works great!
It breaks string import of svg though (like in import PalletSvgUrl from '../../../assets/pallet-90deg.svg';
, I personally import in both ways...). I suggest adding the following line:
contents += `\nexport default (() => ReactComponent())();`;
So here you script with the small modification:
// bunSvgPlugin.ts
import { plugin } from 'bun';
import { writeFileSync } from 'fs';
/**
* The code comes from: https://github.com/oven-sh/bun/issues/3673#issuecomment-1735840376
*/
plugin({
name: 'SVG',
async setup(build) {
const { transform } = await import('@svgr/core');
const { readFileSync } = await import('fs');
build.onLoad({ filter: /\.(svg)$/ }, async args => {
const text = readFileSync(args.path, 'utf8');
let contents = await transform(
text,
{
icon: true,
exportType: 'named',
plugins: ['@svgr/plugin-svgo', '@svgr/plugin-jsx'],
},
{ componentName: 'ReactComponent' }
);
contents += `\nexport default (() => ReactComponent())();`;
return {
contents,
loader: 'js', // not sure why js and not jsx, but it works only this way
};
});
},
});
By the way, did you achieve to build your project using Bun instead of webpack? (I am not sure if it is the right place but it is quite related)
I wanted to give a try but the SVGs loadings fail.
Here are my files:
// build.ts
import Bun from 'bun';
import svgPlugin from './bunSvgPlugin';
console.log('Building...')
const result = await Bun.build({
entrypoints: ['./src/index.tsx'],
outdir: './dist',
plugins: [
svgPlugin
]
});
if (result.success){
console.log('Build success!');
} else {
console.error('Build failed!');
// console.log(result);
for (const log of result.logs){
console.log(log)
}
}
// bunSvgPlugin.ts
import { plugin } from 'bun';
import { writeFileSync } from 'fs';
/**
* The code comes from: https://github.com/oven-sh/bun/issues/3673#issuecomment-1735840376
*/
const pluginsParams = {
name: 'SVG',
async setup(build) {
const { transform } = await import('@svgr/core');
const { readFileSync } = await import('fs');
build.onLoad({ filter: /\.(svg)$/ }, async args => {
const text = readFileSync(args.path, 'utf8');
let contents = await transform(
text,
{
icon: true,
exportType: 'named',
plugins: ['@svgr/plugin-svgo', '@svgr/plugin-jsx'],
},
{ componentName: 'ReactComponent' }
);
contents += `\nexport default (() => ReactComponent())();`;
return {
contents,
loader: 'js', // not sure why js and not jsx, but it works only this way
};
});
},
}
plugin(pluginsParams);
export default pluginsParams;
And here's the output:
X@X:~/X(feature/bun-test)$ bun run build.ts
Building...
Build failed!
error: Unexpected <
const ReactComponent = props => <svg xmlns="http://www.w3.org/2000/svg" fill="none" strokeLinecap="square" strok
^
X/src/assets/X.svg:2:33 64
error: Unexpected <
const ReactComponent = props => <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" {...props}><pat
^
X/src/assets/X.svg:2:33 64
error: Unexpected <
const ReactComponent = props => <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" {...props}><pat
^
X/src/assets/X.svg:2:33 64
error: Unexpected <
const ReactComponent = props => <svg xmlns="http://www.w3.org/2000/svg" fill="none" strokeLinecap="square" strok
^
X/src/assets/Xn.svg:2:33 64
error: Unexpected <
const ReactComponent = props => <svg xmlns="http://www.w3.org/2000/svg" fill="none" strokeLinecap="square" strok
^
X/src/assets/X.svg:2:33 64
error: Unexpected <
const ReactComponent = props => <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 40
...
(i replaced personal data by X)
The build does not fail if we change loader: 'js'
to loader: 'jsx'
(but then the tests fail).
@Amatewasu no, we have to stick to webpack. But in this situation the most straightforward solution is to change loader
depending on command you're running. You can do that with, for instance, environmental variables, but I'm not that good at Bun and there's might be a better solution
Still facing this error, and we are not able to use bun test.
I import svg as import { ReactComponent as MyLogo } from './my-logo.svg'
Getting this error SyntaxError: Import named 'ReactComponent' not found in module '/path/to/repo/my-logo.svg'.
@TkDodo did you find a way to get past this?
The suggested way above still does not work for me for some reason.
What is the problem this feature would solve?
I would like
bun test
to not fail if it encounters an SVG. Currently it fails to prase.What is the feature you are proposing to solve the problem?
You'd know better than me but Bun should be able to recognize an SVG and handle it accordingly.
I don't really care how an SVG is handleled. It could just return a null component for all I care.
What alternatives have you considered?
Jest or Vitest have ways to handle SVGs when testing react components.