twopluszero / next-images

Import images in Next.js (supports jpg, jpeg, svg, png and gif images)
MIT License
948 stars 67 forks source link

Using next-images with svg components #15

Closed arctouch-rodrigoteobaldo closed 3 years ago

arctouch-rodrigoteobaldo commented 5 years ago

It's possible to use next-images with SVG components (with https://github.com/airbnb/babel-plugin-inline-react-svg)? I tried but without success. When using both I'm not able to import SVG as a component, just as a URI. It's like next-images overridden it.

arefaslani commented 5 years ago

I think it would be a good idea to create a URL parameter for ignoring specific import expressions

import CloseSVG from './close.svg?next-images-ignore=true';

or add a configuration option to ignore all imports of a type:

// next.config.js
const path = require('path');
const withImages = require('next-images')
module.exports = withImages({
  ignoreTypes: ["svg"],
  webpack(config, options) {
    return config
  }
})

I will add a solution for it ASAP.

arctouch-rodrigoteobaldo commented 5 years ago

It wasn't expected that exclude resolves this? In some cases and I want to keep some svgs as just images and some cases I want to use svg as a components to add some style. I tried to add a exclude in config but this doesn't works to me.

arefaslani commented 5 years ago

Did you try the exclude option? It's only available in version 1.1.0 and higher. I don't think that it solves your problem because I'm guessing what is happening is that next-images is overwriting babel-plugin-inline-react-svg. So I think the best solution to this problem is by disabling next-images for some imports or some file types. If you can, please test the exclude option to see whether it solves your issue or not.

arctouch-rodrigoteobaldo commented 5 years ago

Yeah, I tried and both don't work even with exclude. The import doesn't print any URL neither work as a SVG component.

arefaslani commented 5 years ago

@arctouch-rodrigoteobaldo Sorry to coming back to you this late. I've figured out that a simple solution would be using the resourceQuery option of Webpack rules. But it doesn't work with negative regex lookup. I've created an issue on the Webpack project 22 days ago, but it doesn't have any response till now. Also I've created a question on the stack overflow and I asked help on the Webpack gitter; we should get help and work on the solution to have this feature work smoothly. Thank you for waiting and helping.

https://github.com/webpack/webpack/issues/8925 https://stackoverflow.com/questions/55172985/webpack-how-to-negative-match-resource-query

arctouch-rodrigoteobaldo commented 5 years ago

Sounds good. Thank you for the work.

veksen commented 5 years ago

Is there a solution for this? Really can't seem to get it to work, and would prefer to avoid using the suggested svg-react-loader (the API is messy IMO).

arefaslani commented 5 years ago

@veksen I think the best way to implement this feature is to add a query param to force Webpack to ignore next-images loader. I've configured that with 'resourceQuery' param:

resourceQuery: /^((?!ni-ignore).)*$/i,

But now it doesn't work without a query param and you must provide even an empty param to make it work:

import Blah from "blahblah?"

Do you have any suggestion? Or I should put another weekend on it.

aminkhademian commented 5 years ago

@veksen @arctouch-rodrigoteobaldo Today I was developing a ni-ignore resource query to force next-images to ignore imports with this query parameter. Then I realized that there is no problem using both packages together.

First you should install the airbnb babel plugin:

npm install --save-dev babel-plugin-inline-react-svg

then create a .babelrc file:

{
  "presets": [
    "next/babel"
  ],
  "plugins": [
    "inline-react-svg"
  ]
}

Don't forget to add next/babel preset. Then you can easily use svg files as React components in you components as:

import React from 'react';
import SampleSVG from './sample.svg';
const SVGComponent = () => <SampleSVG />;

export default () => <SVGComponent />;
aminkhademian commented 5 years ago

Feel free to reopen this issue if you think the problem is still there.

tangye1234 commented 5 years ago

The problem is that, inline-react-svg can receive svg properties like 'viewBox', but next-images cannot.

image

zyqxd commented 4 years ago

@aminkhademian Yes this is still an issue, specifically around the typing here like @tangye1234 mentioned

This overwrites our global typing to make svg imports work with react-inline-svg.

Workaround is to use path mapping to redirect next-images typing to a custom file.

tsconfig.json

{
  "compilerOptions": {
    ...
    "paths: { 
      "next-images": ["./local_types/whatever.d.ts"]
    }
  }
}

./local_types/whatever.d.ts

// type for react-inline-svg
declare module '*.svg' {
  const content: any;
  export default content;
}

// copy rest of types from https://github.com/twopluszero/next-images/blob/master/index.d.ts
...
jptaylor commented 4 years ago

The issue seems to be that you can either import SVGs as React components or as as URIs, but not both.

For example:

{
  "presets": ["next/babel"],
  "plugins": [
    ["module-resolver", { "root": ["./src"] }],
    ["styled-components", { "ssr": true }],
    "inline-react-svg"
  ]
}

Means that this will work:

import Icon from "icons/some-icon.svg";

<Icon />

But this will not work:

import Icon from "icons/some-icon.svg";

<img src={Icon} />

I think the way CRA does this is ideal:

import {ReactComponent as Icon} from "icons/some-icon.svg";
<Icon />

or 

import Icon from "icons/some-icon.svg";
<img src={Icon} />
typeofweb commented 4 years ago

Should this be reopened?

massmediagroup-93 commented 3 years ago

instead of ignoreTypes: ["svg"] should be exclude: path.resolve(__dirname, 'src/images/svg') // next.config.js const path = require('path'); const withImages = require('next-images') module.exports = withImages({ exclude: path.resolve(__dirname, 'src/images/svg'), webpack(config, options) { return config } })

better to use it with next-compose-plugins const path = require('path'); const withPlugins = require('next-compose-plugins'); const withImages = require('next-images') const withSvgr = require("next-svgr");

module.exports = withPlugins([ [withImages, {exclude: path.resolve(__dirname, 'src/images/svg')}], [withSvgr] ]);

Don't forget to install it first: npm install@svgr/webpack

arefaslani commented 3 years ago

We also have added an option to whitelist file extensions: https://github.com/twopluszero/next-images#file-extensions

Please let me know to close this issue if this solves your problem.

luopeihai commented 2 years ago

I had the same stuff, Finally, I resolved the problem without changing the next config example:

import Logo from '@/data/logo.svg'
const Home = () =>{
   return <Logo />
}

resolved code

const Home = () =>{
   return <Logo />
}

const  Logo = () =>{
   return <svg>......</svg>
}