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

我想知道如何使用 webpack 设置内联 svg?

我正在关注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

【问题讨论】:

    标签: javascript svg reactjs webpack loader


    【解决方案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" height="24" viewBox="0 0 24 24" width="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】:

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

      1. 安装Svg inline loader
      2. 在 webpack.config.js 中添加{ test: /\.svg$/, loader: 'svg-inline-loader' }
      3. 在您的 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", {}]
          ],
          ...
          

          【讨论】:

            猜你喜欢
            • 2016-11-16
            • 1970-01-01
            • 2021-11-23
            • 2018-07-08
            • 1970-01-01
            • 2015-07-18
            • 2021-08-14
            • 2023-03-18
            相关资源
            最近更新 更多