zabute / gatsby-plugin-svgr Goto Github PK
View Code? Open in Web Editor NEWTransform SVGs into React components with SVGR
License: MIT License
Transform SVGs into React components with SVGR
License: MIT License
Not sure exactly what changed between 2.0.0-alpha
(which was working great for me) and 2.0.0
mainline, but I just updated and installed @svgr/webpack
as a peer dep, and now Gatsby is complaining about imported PNG images and missing a relevant loader. Any ideas what could be causing this? It's definitely plugin-svgr
that's doing it — does it mess with the default file/url loaders in Gatsby?
Thanks for this plugin!
v2.0.0-alpha
is still working great, but running gatsby develop
in Gatsby v2.0.50
using either v2.0.0
or v.2.0.1
fails with the following error:
Plugin gatsby-plugin-svgr returned an error
Error: Cannot find module '@svgr/webpack'
The plugin still works if I roll back to v2.0.0-alpha
, but I thought you'd probably want to know about this.
I'd find it more useful to process SVGs with a particular filename pattern and no others, rather than the current options, which are all-or-nothing, or "process only SVGs in this particular directory".
Please consider adding an option to provide a filename regex, such as /\.inline\.svg$/
.
Hey! Thank you for the awesome plugin. While using it, I've discovered what appears to be an unexpected behavior. I'd like to know your opinion on this.
Setting svgoConfig.cleanupIDs: false
still removes id
attributes from SVG nodes.
Setting svgoConfig.cleanupIDs: false
does not remove id
attributes from SVG nodes.
// gatsby-config.js
module.exports = {
plugins: [
{
resolve: `gatsby-plugin-svgr`,
options: {
svgoConfig: {
cleanupIDs: false,
},
},
},
]
}
// example.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 28" focusable="false">
<title>
Gatsby
</title>
<circle cx="14" cy="14" r="14" fill="#639"/>
<path id="i-should-persist" fill="#fff" d="M6.2 21.8C4.1 19.7 3 16.9 3 14.2L13.9 25c-2.8-.1-5.6-1.1-7.7-3.2zm10.2 2.9L3.3 11.6C4.4 6.7 8.8 3 14 3c3.7 0 6.9 1.8 8.9 4.5l-1.5 1.3C19.7 6.5 17 5 14 5c-3.9 0-7.2 2.5-8.5 6L17 22.5c2.9-1 5.1-3.5 5.8-6.5H18v-2h7c0 5.2-3.7 9.6-8.6 10.7z"/>
</svg>
In the compiled example.svg
there is no `id="i-should-persist".
It says unable to find plugin "gatsby-plugin-svgr" on the gatsby-starter-hero-blog.
Doesn't seem like svgo: false
in the options works. Unfortunately SVGO is causing me some issues with inlined SVGs and I'd like to disable to confirm.
I'd fix, but I know very little about node packages or how webpack works.
This doesn't work:
plugins: {
removeViewBox: true, // remove viewBox when possible (default)
cleanupIDs: true, // remove unused IDs and minify remaining IDs (default)
},
This works:
plugins: [
{ removeViewBox: true }, // remove viewBox when possible (default)
{ cleanupIDs: true }, // remove unused IDs and minify remaining IDs (default)
],
While working on solving a issue, namely this one, which uses this plugin and storybook, i implemented a simple gatsby website using typescript, a simple hello world one, without any "bells and whistles"(pardon the bad pun), to test out what could be the root of the issue linked above. I was able to solve that issue and got it to work as you can see my latest comment. But it led me to the reason of this specific issue.
I installed the plugin and followed the instructions to add the plugin to gatsby website. To be safe i kept it simple. All went fine and i was able to make the plugin work with storybook. The issue is when i start gatsby, issuing gatsby develop
goes without any problems. It's when i open a page that the following error pops up:
Here are the relevant parts:
{
"dependencies": {
"@svgr/webpack": "^4.1.0",
"gatsby": "^2.1.20",
"gatsby-plugin-sass": "^2.0.10",
"gatsby-plugin-svgr": "^2.0.2",
"gatsby-plugin-typescript": "^2.0.10",
"node-sass": "^4.11.0",
"prop-types": "^15.7.2",
"react": "^16.8.3",
"react-dom": "^16.8.3",
"typescript": "^3.3.3333",
"webpack": "^4.29.6"
},
"devDependencies": {
"@babel/core": "^7.4.0",
"@types/node": "^11.11.4",
"@types/react": "^16.8.8",
"@types/react-dom": "^16.8.2",
"@typescript-eslint/eslint-plugin": "^1.4.2",
"@typescript-eslint/parser": "^1.4.2",
"babel-loader": "^8.0.5",
"gatsby-plugin-tslint": "^0.0.1",
"tslint": "^5.13.1",
"tslint-loader": "^3.5.4",
"tslint-react": "^3.6.0",
"@storybook/react": "^5.0.3",
"@storybook/addon-actions": "^5.0.3",
"@storybook/addon-links": "^5.0.3",
"@storybook/addons": "^5.0.3"
},
"engines": {
"node": ">=8.0.0"
}
}
gatsby-config.js
contents:module.exports = {
siteMetadata: {
name: `Hello Typescript World!`,
tagline: `Gatsby + SASS + Typescript = 💪`
},
plugins: [
`gatsby-plugin-sass`,
`gatsby-plugin-typescript`,
`gatsby-plugin-tslint`,
{
resolve:'gatsby-plugin-svgr',
options: {
icon: true,
},
}
],
}
import * as React from 'react';
import Star from '../assets/icons/Five-pointed_star.svg';
// import Star from './Five-pointed_star.svg';
const SimpleSvg: React.FunctionComponent = () => (
<div style={{display: 'flex', justifyContent: 'space-around', maxWidth: `960px`, margin: `1.45rem` }}>
<div>
<h4>this is a star injected directly into a react component</h4>
<Star/>
</div>
{/* <div>
<h4>this is a star injected into a img element</h4>
<img src={Star} alt="A five point star"/>
</div> */}
</div>
);
export default SimpleSvg;
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="255" height="240" viewBox="0 0 51 48">
<title>Five Pointed Star</title>
<path fill="none" stroke="#000" d="m25,1 6,17h18l-14,11 5,17-15-10-15,10 5-17-14-11h18z"/>
</svg>
With a little tweak on storybook, it works without any issues. But not with gatsby. Any ideas on to solve this issue? Is there anything missing in my end? Some configuration or something else?
The full code is here
Feel free to provide feedback. Thanks in advance
I updated to Gatsby 3.0 following the migration guide and I get the following error when running gatsby develop
. If the fix is non trivial, maybe the plugin should be flagged as Gatsby 2.x only
Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.
- configuration.module.rules[12] should be one of these:
["..." | object { compiler?, dependency?, descriptionData?, enforce?, exclude?, generator?, include?, issuer?, issuerLayer?, layer?, loader?, mimetype?, oneOf?, options?, parser?, realResource?, resolve?,
resource?, resourceFragment?, resourceQuery?, rules?, sideEffects?, test?, type?, use? }, ...]
-> A rule.
Details:
* configuration.module.rules[11].issuer has an unknown property 'test'. These properties are valid:
object { and?, not?, or? }
* configuration.module.rules[12].issuer has an unknown property 'test'. These properties are valid:
object { and?, not?, or? }
ValidationError: Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.
- configuration.module.rules[12] should be one of these:
["..." | object { compiler?, dependency?, descriptionData?, enforce?, exclude?, generator?, include?, issuer?, issuerLayer?, layer?, loader?, mimetype?, oneOf?, options?, parser?, realResource?, resolve?, r esource?, resourceFragment?, resourceQuery?, rules?, sideEffects?, test?, type?, use? }, ...]
-> A rule.
Details:
* configuration.module.rules[11].issuer has an unknown property 'test'. These properties are valid:
object { and?, not?, or? }
* configuration.module.rules[12].issuer has an unknown property 'test'. These properties are valid:
object { and?, not?, or? }
- validate.js:104 validate
[gatsby-starter-ianmethyst]/[schema-utils]/dist/validate.js:104:11
- validateSchema.js:79 validateSchema
[gatsby-starter-ianmethyst]/[webpack]/lib/validateSchema.js:79:2
- webpack.js:105 create
[gatsby-starter-ianmethyst]/[webpack]/lib/webpack.js:105:4
- webpack.js:142 webpack
[gatsby-starter-ianmethyst]/[webpack]/lib/webpack.js:142:32
- index.js:41 f
[gatsby-starter-ianmethyst]/[webpack]/lib/index.js:41:15
- build-html.ts:63
[gatsby-starter-ianmethyst]/[gatsby]/src/commands/build-html.ts:63:7
- debuggability.js:384 Promise._execute
[gatsby-starter-ianmethyst]/[bluebird]/js/release/debuggability.js:384:9
- promise.js:518 Promise._resolveFromExecutor
[gatsby-starter-ianmethyst]/[bluebird]/js/release/promise.js:518:18
- promise.js:103 new Promise
[gatsby-starter-ianmethyst]/[bluebird]/js/release/promise.js:103:10
- build-html.ts:61 runWebpack
[gatsby-starter-ianmethyst]/[gatsby]/src/commands/build-html.ts:61:3
- build-html.ts:114 doBuildRenderer
[gatsby-starter-ianmethyst]/[gatsby]/src/commands/build-html.ts:114:23
- build-html.ts:143 buildRenderer
[gatsby-starter-ianmethyst]/[gatsby]/src/commands/build-html.ts:143:10
- start-server.ts:113 createIndexHtml
[gatsby-starter-ianmethyst]/[gatsby]/src/utils/start-server.ts:113:28
- start-server.ts:150 startServer
[gatsby-starter-ianmethyst]/[gatsby]/src/utils/start-server.ts:150:5
- start-webpack-server.ts:44 startWebpackServer
[gatsby-starter-ianmethyst]/[gatsby]/src/services/start-webpack-server.ts:44:7
not finished Building development bundle - 0.291s
I'd love to be able to enable this plugin, but still be able to use SVG files in Sass/CSS and JSX. I don't think that's currently possible?
I'm not really literate in Webpack (especially v1), but it seems like v3's oneOf
combined with a resourceQuery
would make this possible…but again, not sure how to do that in v1.
I was picturing something like this:
import LogoSvg from 'svgs/logo.svg?component // handled by SVGR
import logo from 'images/logo.svg // handled by url-loader
[…]
<LogoSvg />
<img src={logo} />
…or maybe just a configureable path:
import LogoSvg from 'svgs/logo.svg // svg/**/*.svg handled by SVGR
import logo from 'images/logo.svg // all others handled by url-loader
[…]
<LogoSvg />
<img src={logo} />
If this is already actually possible, I'd love some tips on how to configure it to work this way if you have some time. Thanks!
In this plugin's gatsby-node.js
, in the onCreateWebpackConfig
hook the following rule is added:
const urlLoader = loaders.url({ name: "static/[name].[hash:8].[ext]" })
The default behaviour of URLLoader is that no limit is set for inlining files. So this effectively adds a rule telling webpack to inline all svgs regardless of file-size, overriding Gatsby's own config which sets the limit to 10KB.
Currently you offer a plugins
object to pass plugin configuration to SVGO, however this doesn't allow plugins to be disabled, only configured.
SVGO provides a disable
flag: --disable=PLUGIN
or for multiple: --disable=PLUGIN1,PLUGIN2
that allows disabling of plugins.
Please provide a mechanism so that a list of plugins to be disabled can be passed through to SVGO.
For example, currently it is impossible to disable removeViewBox
which is necessary to enable removeDimensions
. Setting removeViewBox
to false
isn't enough in this instance.
Gatsby v3 has switched to Webpack v5, however this plugin supplies configuration for Webpack v4. This results in the following error during build:
ValidationError: Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API sc
hema.
- configuration.module.rules[12] should be one of these:
["..." | object { compiler?, dependency?, descriptionData?, enforce?, exclude?, generator?, include?, issuer?, issuerLayer?, layer?,
loader?, mimetype?, oneOf?, options?, parser?, realResource?, resolve?, resource?, resourceFragment?, resourceQuery?, rules?, sideEffe
cts?, test?, type?, use? }, ...]
-> A rule.
Details:
* configuration.module.rules[10].issuer has an unknown property 'test'. These properties are valid:
object { and?, not?, or? }
* configuration.module.rules[11].issuer has an unknown property 'test'. These properties are valid:
object { and?, not?, or? }
* configuration.module.rules[12].issuer has an unknown property 'test'. These properties are valid:
object { and?, not?, or? }
My SVG file has a viewBox
defined, but the React Component created does not include the viewBox
even when I define viewBox: true
in my gatsby-config.js
. This is causing the SVG to not scale properly. If I import the data uri and render in an image tag, it works.
Hey there,
thank you for coming up with this plugin! Saved my day :)
I ran into the following issue where my Gatsby config doesn't apply the SVGO configuration.
{
resolve: 'gatsby-plugin-svgr',
options: {
svgoConfig: {
removeViewBox: false,
},
},
},
Instead, I have to define a .svgo.yml file with
plugins:
removeViewBox: false
to make it work. Any thoughts on why this might not work?
Please release new npm package for the plugin, compliant with the last commit. The version 1.0.0 is trying to install svgr which is deprecated
I tried to install gatsby-plugin-svgr
on a fresh installation of the default gatsby-starter-blog and got this
λ yarn add gatsby-plugin-svgr
yarn add v1.3.2
warning ..\..\..\package.json: No license field
[1/4] Resolving packages...
warning gatsby-plugin-svgr > [email protected]: Please install @svgr/cli, @svgr/core or @svgr/webpack
[2/4] Fetching packages...
info [email protected]: The platform "win32" is incompatible with this module.
info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
warning "gatsby > [email protected]" has incorrect peer dependency "webpack@^2.0.0 || ^3.0.0 || ^4.0.0".
warning "gatsby > [email protected]" has unmet peer dependency "caniuse-db@^1.0.30000652".
warning "gatsby-plugin-react-helmet > [email protected]" has unmet peer dependency "react@>=15.0.0".
warning "gatsby-plugin-react-helmet > react-helmet > [email protected]" has unmet peer dependency "react@^0.13.0 || ^0.14.0 || ^15.0.0 || ^16.0.0".
warning "gatsby-plugin-typography > [email protected]" has unmet peer dependency "react@^0.14.0 || ^15.0.0 || ^16.0.0".
warning "gatsby-transformer-remark > [email protected]" has unmet peer dependency "graphql@>=0.4.0".
[4/4] Building fresh packages...
[1/1] ⢀ svgr
[-/1] ⠠ waiting...
[-/1] ⠠ waiting...
[-/1] ⠠ waiting...
error C:\Users\Greg\_dev\tests\test-for-svgr-2\node_modules\svgr: Command failed.
Exit code: 1
Command: node message.js; sleep 10; exit 1;
Arguments:
Directory: C:\Users\Greg\_dev\tests\test-for-svgr-2\node_modules\svgr
Output:
module.js:549
throw err;
^
Error: Cannot find module 'C:\Users\Greg\_dev\tests\test-for-svgr-2\node_modules\svgr\message.js;'
at Function.Module._resolveFilename (module.js:547:15)
at Function.Module._load (module.js:474:25)
I'm using the config options of { icon: true, viewBox: false }
.
When doing (roughly) this:
import CommentIcon from '../icons/comment-alt.svg'
export const Example = props => (
<div>
<CommentIcon width="1.125em" />
</div>
)
The final render is (roughly):
<div><svg viewBox="0 0 576 512" width="1em" height="1em">...</path></svg></div>
I expected the width
to be 1.125em
.
Hmm, how exactly should my gatsby-config.js
look like? I'm getting an error when the plugin config is passed as an object like this:
module.exports = {
siteMetadata: {
...
},
{
resolve: 'gatsby-plugin-svgr',
options: {
dir: '/src/svg',
icon: true,
viewBox: false,
},
},
plugins: [
`gatsby-plugin-react-helmet`,
`gatsby-plugin-offline`,
`gatsby-plugin-sass`,
`gatsby-plugin-netlify`
]
};
→ gatsby develop
success delete html files from previous builds — 0.006 s
error Could not load gatsby-config
Error: /Users/pugson/Sites/wojtek.im-blog/gatsby-config.js:6
{
^
SyntaxError: Unexpected token {
- module.js:11 require
internal/module.js:11:18
- index.js:106 _callee$
[wojtek.im-blog]/[gatsby]/dist/bootstrap/index.js:106:38
- next_tick.js:150 process._tickCallback
internal/process/next_tick.js:150:11
After dropping the additional {}
I get another error:
ValidationError: "resolve" is not allowed. "options" is not allowed
error UNHANDLED REJECTION
Error: The site's gatsby-config.js failed validation
- config.js:34 module.exports
[wojtek.im-blog]/[gatsby]/dist/redux/reducers/config.js:34:17
- combineReducers.js:133 combination
[wojtek.im-blog]/[redux]/lib/combineReducers.js:133:29
- createStore.js:178 Object.dispatch
[wojtek.im-blog]/[redux]/lib/createStore.js:178:22
- index.js:114 _callee$
[wojtek.im-blog]/[gatsby]/dist/bootstrap/index.js:114:19
- next_tick.js:150 process._tickCallback
internal/process/next_tick.js:150:11
Hi guys,
Great work on the plugin. Does any one know how to import individual icons using the SVG sprite method (As seen here: https://css-tricks.com/svg-sprites-use-better-icon-fonts/ using the <use xlinkHref>
tag.
I tried but failed at implementing this method.
I was unable to get the config to keep the viewBox
over the width / height
attributes given an SVG that has both. See this CodePen:
https://codesandbox.io/s/gatsbysvgrsvgotest-e4i19
I would expect that this config would yield a check.svg
SVG that only has viewBox
:
svgoConfig: {
removeDimensions: true,
removeViewBox: false,
},
But you can see, it's the reverse and we only see the width / height
retained on the svg
element. Does this mean SVGO rule overrides may not be applied?
Possibly related to #17 (not that familiar with svgr itself), but gatsby-plugin-svgr
completely breaks render in Gatsby 2, causing it to silently fail (took me aaages to figure out it was svgr going wrong).
Since it fails silently, can't be much help debugging, but I can only assume it's to do with Webpack 4, and that bumping to @svgr/webpack
would fix it.
Could we try that and release under a next
tag for Gatsby v2? Seems to solve both issues, don't have to worry about breaking gatsby/webpack 1, keeps compat going forward for Gatsby 2
Hi,
Is there anyway to dynamically import the svgs into a component? I've seen some examples of using React.lazy to import but I havent been able to get it to work.
Ideally Im looking for a react compoent where I can pass the filename of the svg as a prop.
These are more or less issues/suggestions that I thought may be useful feedback. There may be a config way around these, but I want to share how I solved them.
By default it seems like the plugin configs Webpack to use both url-loader
and svgr/webpack
. Would be nice to be able to opt into or out of the url-loader.
There is either a bug or "feature" of Webpack currently where the presence of an issuer rule will prevent Webpack from using a loader on files dynamically imported, since we load a folder of filename.svg
files through require.context
, the default gatsby-plugin-svgr
loader config would not work. (webpack/webpack#9309)
In either case, I got around both of these issues by more manually configuring the gatsby-node.js webpack config. However, it seems a bit round about -- I may not even need to use this plugin given the amount of webpack config changes I am making to the default config provided.
I have used this plugin successfully for SVG to React Component, but I get some struggle to figure out how to replace fill
attribute. This is my configuration
{
resolve: 'gatsby-plugin-svgr',
options: {
icon: true,
viewBox: false,
expandProps: 'end',
replaceAttrValues: {
'#FFBB00': 'currentColor',
},
},
},
It didn't work as expected
I'm trying to use an svg background-image in my CSS. Just a basic background-image: url(./icons/icon.svg);
.
Unfortunately, it looks like the svgr loader is intercepting that and replacing it with background-image: url(" + require(" ./icons/icon.svg ") + ")
, which then gets stringified into [Object object]
.
The base svgr plugin gets around this by using Rule.issuer, but that's not available to us here in Gatsby, with our Webpack v1.
Would it be possible to exclude CSS files from the automatic conversion of SVGs to components? Or at least an option that offers some way around that? Thanks!
The plugin doesn't currently work correctly with the latest version of @svgr/webpack. Config settings defined within the plugin are not passed on to svgo.
Please upgrade the version of @svgr/webpack used.
I ran into the following error:
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
This error originates from a SVG which I use the following way:
import { ReactComponent as WelcomeGraphic } from '../../static/graphics/welcome.svg';
<WelcomeSpotlight color="--white-color" background={<WelcomeGraphic />}>
I'm using this plugin with the following .svgo.yml
configuration:
multipass: true
plugins:
- removeDimensions: true
- removeViewBox: false
I also have some types declared for it as I'm using TypeScript:
declare module '*.svg' {
import { PureComponent, SVGProps } from 'react';
export class ReactComponent extends PureComponent<SVGProps<SVGSVGElement>> {}
}
Do you have an idea what needs to be changed to have a proper default export back?
Thank you in advance.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.