如何使用 webpack 设置内联 svg

Posted

技术标签:

【中文标题】如何使用 webpack 设置内联 svg【英文标题】:how to set up an inline svg with webpack 【发布时间】:2016-03-19 09:19:48 【问题描述】:

我想知道?

我正在关注react-webpack-cookbook。

我的 webpack.config 使用 文件加载器 正确设置。

但是,该示例显示使用这样的背景图像:

.icon 
   background-image: url(./logo.svg);

效果很好,但我想要一个内联的 svg 图像,我该怎么做才能在我的反应组件中包含我的 logo.svg 内联?

import React,  Component  from 'react'

class Header extends Component 

  render() 
    return (
        <div className='header'>
            <img src='./logo.svg' />
        </div>
    );
  
;

export default Header

【问题讨论】:

【参考方案1】:

如果我没记错的话,由于您使用的是文件加载器,因此您可以像使用其他任何需要一样使用它。 Webpack 会将require("./logo.svg") 转换为文件的路径,它会在打包时发出。

import React,  Component  from 'react'

import mySvg from './logo.svg'

class Header extends Component 

  render() 
    return (
        <div className='header'>
            <img src=mySvg />
        </div>
    );
  
;

export default Header

【讨论】:

它对我不起作用:(你能发布你的 webpack.config.js 吗?也许我可以在那里发现我的错误。 仅在我重新启动后才为我工作npm start 这增加了 svg 内联?还是将 svg 包装在图像标签中?【参考方案2】:

实际上 Michelle 的回答为我指明了正确的方向,这非常适合使用 webpack 加载 svg 文件并将其用作您的 &lt;img&gt; src

然而,要真正获得内联 svg,我需要执行以下操作:

使用svg-inline-loader 作为您的 svg 加载器,而不是文件加载器:

test: /\.svg$/, loader: 'svg-inline-loader'

然后将svg内联加载到组件中:

import React,  Component  from 'react'
import logo from "./logo.svg";

class Header extends Component 

  render() 
    return (
        <div className='header'>
          <span dangerouslySetInnerhtml=__html: logo />
        </div>
    );
  
;

export default Header

看起来有一个用于反应 svg-inline-react 的内联 svg 包装器,这将是另一个选项,而不是 &lt;div dangerouslySetInnerHTML=__html: mySvg /&gt;

【讨论】:

只是一个注释,这对服务器渲染根本不起作用......所以不像我曾经想象的那么有用。我已经回到使用 svg 作为背景图像。它似乎也像内联 svg 一样使 javascript 包膨胀,当然这取决于 svg 的优化程度。 Twitter 发布了一个很好的案例研究,说明了为什么您应该使用 'dangerouslySetInnerHTML' 来显示 SVG:medium.com/@paularmstrong/…【参考方案3】:

老问题,但我在任何地方都没有看到这个解决方案,所以我决定发布它,希望它会对某人有所帮助。

如果您希望能够为这些 SVG 图标设置样式,您可能希望使用原始加载器加载它们:

webpack.config.js:

  
      test: /\.svg$/, 
      loader: 'raw-loader' 
  

我认为的导入:

import closeIcon from 'svg/ic_close_black_24px.svg'; 

模板(Mustache 使用 3 个括号插入未编码的 SVG 数据(URL)):

<button id="closeModal">
  closeIcon
</button>

这样,SVG 数据将被插入而不是括号,如下所示:

<button id="closeModal">
  <svg fill="#000000"  viewBox="0 0 24 24"  xmlns="http://www.w3.org/2000/svg">
    <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path>
    <path d="M0 0h24v24H0z" fill="none"></path>
  </svg>
</button>

我正在使用带有 Webpack 2.5.1 的 Mustache 模板引擎的 Backbone

【讨论】:

将使用基于字符串模板的库,如骨干 + mustache 或 vue,但不使用 react,因为它使用 JSX 而不是原始字符串。可能确实适用于“dangerouslySetInnerHTML”...【参考方案4】:

我希望我迟到的答案仍然对某人有用,因为我不喜欢上述任何选项。

react-svg-loader webpack 加载器允许您导入 SVG 图标,如 JSX 组件:

import Logo from './logo.svg';

class App extends Component 
  render() 
    return (
      <div className="App">
          <Logo fill="red" className="logo" width=50 height=50 />
      </div>
    );
  

最低配置如下所示:


  test: /\.svg$/,
  use: [
    
      loader: "babel-loader"
    ,
    
      loader: "react-svg-loader",
      options: 
        jsx: true // true outputs JSX tags
      
    
  ]

最好的部分是它只输出 svg 文件内容,没有任何额外的包装器和代码中的dangerouslySetInnerHTML

【讨论】:

这适用于最新的 React 16.10 和 Webpack 4.41。谢谢!【参考方案5】:

与使用 React 的另一个答案类似,还有一个方便的 Vue 插件。

vue-svg-loader 只需将其放入您的配置中并开始使用。好消息是它还会通过 SVGO 运行你的 svg 来优化它。

配置


    test: /\.svg$/,
  loader: 'vue-svg-loader', // `vue-svg` for webpack 1.x
  options: 
    // optional [svgo](https://github.com/svg/svgo) options
    svgo: 
      plugins: [
        removeDoctype: true,
        removeComments: true
      ]
    
  

用法

<template>
  <nav id="menu">
    <a href="...">
      <SomeIcon class="icon" />
      Some page
    </a>
  </nav>
</template>

<script>
import SomeIcon from './assets/some-icon.svg';

export default 
  name: 'menu',
  components: 
    SomeIcon,
  ,
;
</script>

【讨论】:

【参考方案6】:

这是一个简单的非反应解决方案。

    安装Svg inline loader 在 webpack.config.js 中添加 test: /\.svg$/, loader: 'svg-inline-loader' 在您的 js 文件中导入 svg 图像并将其添加到这样的 DOM 元素中
  import Svg from './svg.svg';

  function component() 
    const element = document.createElement('div');

    element.innerHTML = Svg;

    return element;
  

  document.body.appendChild(component());

【讨论】:

感谢您不依赖 react 并展示 vanilla ECMAScript【参考方案7】:

Angular 解决方案(2019 年):使用 svg-sprite-loader 将 SVG 组合成一个单独的精灵,该精灵与您的 Webpack 包一起延迟加载。

网页包


  test: /\.svg$/,
  use: [
    'svg-sprite-loader',
    'svgo-loader' // Optimize SVGs (optional)
  ]

HTML

<svg>
    <use xlink:href="#arrow"/>
</svg>

角度组件

export * from 'assets/images/icons/arrow.svg';

我使用导出(而不是导入)来防止 AOT 编译器在 tree-shaking 期间删除导入,同时允许组件中的代码最少,但如果您愿意,可以use import。

要以这种方式使用导出,您必须将编译器配置为预期 package.json 中 SVG 文件的副作用(即,您不能使用“sideEffects”:false)。见Webpack Tree Shaking Guide

"sideEffects": [
    "*.svg",
],

【讨论】:

【参考方案8】:

@svgr/webpack (npm) 是 create-react-app 使用的内联 svg 加载器。

将规则添加到您的 webpack 配置中:


  test: /\.svg$/,
  use: ['@svgr/webpack'],

然后你可以将 svgs 导入为 React 组件:

import Star from './star.svg'

const App = () => (
  <div>
    <Star />
  </div>
)

【讨论】:

【参考方案9】:

使用 svg-inline-loader 并遇到“找不到模块”错误的人尝试安装 babel-plugin-inline-react-svg 并将其添加到 babel 插件中:

"plugins": [
    ...
    ["inline-react-svg", ]
],
...

【讨论】:

以上是关于如何使用 webpack 设置内联 svg的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Web 服务动态导入 SVG 并内联渲染

如何从服务器加载SVG并将其插入内联

如何在 mouseover/mouseout (SMIL) 上为内联 SVG 的填充属性设置动画

Webpack QuillJS 输出 SVG 路径而不是内联它

Webpack 从我的样式表中的内联 SVG 中去除标签,我不知道为啥

如何设置背景/内联 SVG 的填充颜色? [复制]