Nuxt Nation 大会即将到来。加入我们,时间为 11 月 12-13 日。

nuxt-svgo
nuxt-svgo

Nuxt 模块,用于将优化的 SVG 文件加载为 Vue 组件

nuxt-svgo

npm versionnpm downloadslicense

nuxt-svgo 是一个 Nuxt 模块,用于将优化的 SVG 文件加载为 Vue 组件。

StackBlitz 上试用!

安装

npx nuxi@latest module add nuxt-svgo

使用

通过在 Nuxt 配置文件的 modules 部分添加 'nuxt-svgo' 来使用 默认配置

// nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'

export default defineNuxtConfig({
  modules: ['nuxt-svgo'],
})

然后,在任何 .vue 文件中,导入您的资源并将其用作组件

<template>
  <div>
    <!-- font size controls width & height by default: -->
    <IconHome class="text-xl" />
    <!-- you can disable it: -->
    <IconHome class="w-5 h-5" :fontControlled="false" />
  </div>
</template>

<script setup lang="ts">
  import IconHome from '~/assets/icon-home.svg'
</script>

或者,如果您使用的是 vite,则在任何 .vue 文件中,只需使用图标名称加上 svgo 前缀作为组件名称即可

<template>
  <div>
    <SvgoHome class="text-xl" />
    <!-- Or -->
    <svgo-home class="text-xl" />
  </div>
</template>

默认情况下,它会自动从 assets/icons/ 文件夹导入您的图标。您可以通过在配置中传递 autoImportPath 来配置此选项

// nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'

export default defineNuxtConfig({
  modules: ['nuxt-svgo'],
  svgo: {
    autoImportPath: './assets/other-icons/',
  },
})

如果您想使用自动导入,但不想使用 nuxt-icon 组件(默认使用),您可以通过使用 defaultImport: 'component' 来实现

// nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'

export default defineNuxtConfig({
  modules: ['nuxt-svgo'],
  svgo: {
    defaultImport: 'component',
  },
})

您还可以使用您自己的自定义组件来代替内置的 nuxt-icon 组件,方法是使用 customComponent 选项。此自定义组件必须具有 icon 属性,就像 nuxt-icon 组件一样 nuxt-svgo 提供的

示例

// nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'

export default defineNuxtConfig({
  modules: ['nuxt-svgo'],
  svgo: {
    customComponent: 'YourComponent',
  },
})

默认情况下,模块会在全局范围内注册 autoImportPath 中的所有图标。这可能是不可取的行为,因为它会为每个要全局使用的图标生成代码块,如果您有很多图标,这将导致大量文件。如果您想禁用全局注册,只需在模块选项中使用 global: false

// nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'

export default defineNuxtConfig({
  modules: ['nuxt-svgo'],
  svgo: {
    global: false,
  },
})

要禁用自动导入,只需将 autoImportPath 设置为 false

// nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'

export default defineNuxtConfig({
  modules: ['nuxt-svgo'],
  svgo: {
    autoImportPath: false,
  },
})

子文件夹

图标的组件名称将遵循 Nuxt 的组件前缀约定。因此,如果为您的组件启用了前缀,例如 assets/icons/admin/badge.svg 的组件名称将为 svgo-admin-badge

<svgo-admin-badge />

componentPrefix

您可以使用 componentPrefix 选项将默认前缀(svgo)更改为您自己的自定义前缀

// nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'

export default defineNuxtConfig({
  modules: ['nuxt-svgo'],
  svgo: {
    componentPrefix: 'i',
  },
})
// in your template
<template>
  <div>
    <i-home />
  </div>
</template>

工作原理

Vite

如果您的 Nuxt 应用使用 Vite,则此模块会将 vite-svg-loader 添加到底层的 Vite 配置中。所有功劳都归功于 vite-svg-loader 的作者,@jpkleemans

我们使用此 vite 插件的修改版本来自动加载图标,并使用 nuxt-icon 组件进行额外的控制。

Webpack

如果您的 Nuxt 应用使用 Webpack,则此模块会将 vue-svg-loadersvgo-loader 添加到底层的 Webpack 配置中。如 此问题 中所述,vue-svg-loader 使用 SVGO 的版本 1。 vue-svg-loader 似乎没有维护,最新的 beta 版本已经超过两年了。我们禁用了 vue-svg-loader 的 SVGO 功能,而是依靠 svgo-loader 来执行优化,基本上使 vue-svg-loader 将 svg 内容包装在 <template></template> 标记中。

所有功劳都归功于 vue-svg-loader 的作者,@damianstasik。所有功劳都归功于 svgo-loader 的作者,@svg

如果您使用的是 webpack,请确保安装此模块的 peer 依赖项(vue-svg-loadersvgo-loadervue-loader)。

配置

使用您自己的自定义 SVGO 选项

// nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'

export default defineNuxtConfig({
  modules: ['nuxt-svgo'],
  svgo: {
    svgoConfig: {
      multipass: true,
      plugins: [
        {
          name: 'preset-default',
          params: {
            overrides: {
              // customize default plugin options
              inlineStyles: {
                onlyMatchedOnce: false,
              },

              // or disable plugins
              removeDoctype: false,
              removeViewBox: false,
            },
          },
        },
      ],
    },
  },
})

完全禁用 SVGO

// nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'

export default defineNuxtConfig({
  modules: ['nuxt-svgo'],
  svgo: {
    svgo: false,
  },
})

导入查询(仅限 Vite.js)

以下是导入 SVG 文件时可能使用的查询

  • url_encode:将优化的 svg 加载为 data uri(使用 svgo + mini-svg-data-uri
  • raw:将内容加载为文本
  • raw_optimized:将优化的 svg 加载为文本
  • skipsvgo:将内容加载为组件(未优化,没有 nuxt-icon
  • component:将优化的 svg 加载为组件
  • componentext:使用 nuxt-icon 组件加载优化的 svg

例如

<template>
  <div>
    <IconHome />
  </div>
</template>

<script setup lang="ts">
  import IconHome from '~/assets/icon-home.svg?componentext' // the default
</script>

关于 url_encode 查询的重要说明

xmlns="http://www.w3.org/2000/svg" 属性是 uri 数据正常工作所必需的。在某些极少数情况下,它可能不存在。使用 url_encode 查询时,请确保它存在,否则图像将不会显示。

与 TypeScript 结合使用

在 TypeScript 中导入 SVG 组件时,您将收到“无法找到模块”错误。为了解决此问题,您需要提供类型声明来告诉 TypeScript 如何处理 SVG 组件。以下是一个示例,使用应用程序根目录下的 custom.d.ts 文件

// custom.d.ts
declare module '*.svg' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent
  export default component
}

nuxt-icon 组件

最初从 nuxt-icons 模块 复制而来,但后来进行了大量修改以支持 tree shaking 和 SSR。不建议直接使用它。但是,您可以直接导入您的图标并将它们传递给组件,方法是使用 icon 属性。

组件属性

  • filled:当 true 时,使用图标的原始颜色
  • fontControlled:您可以通过将此属性设置为 false 来禁用按字体大小缩放的默认行为
  • iconnuxt-icon 将呈现为的组件。这在内部用于控制图标。

从 v1.x 迁移到 v2.x

如果您之前使用过 nuxt-icon 组件,则需要像这样更改您的代码

<!-- from: -->
<nuxt-icon name="home" filled />
<nuxt-icon name="special/home" filled />
<!-- to: -->
<svgo-home filled />
<svgo-special-home filled />

从 v2.x 迁移到 v3.x

v3 现在默认使用一个有主见的默认 svgo 配置,要使其像以前一样工作,只需将 {} 传递给 svgoConfig 选项

export default defineNuxtConfig({
  // ...
  svgo: {
    svgoConfig: {},
  },
})

此外,从 v3 开始,simpleAutoImport 选项已删除,defaultImport 已更改为 componentext。如果您使用以下代码,并且依赖于 defaultImport,请更改它

<template>
  <div>
    <IconHome class="text-xl" />
  </div>
</template>

<script setup lang="ts">
  // change this:
  import IconHome from '~/assets/icon-home.svg'
  // to this:
  import IconHome from '~/assets/icon-home.svg?component'
</script>

开发

  • 运行 pnpm dev:prepare 以生成类型存根。
  • 使用 pnpm dev 在开发模式下启动 playground

作者

Corey Psoinos

Javad Mnjd

展示您的支持

如果此项目对您有所帮助,请给一个 ⭐️!

📝 许可证

版权所有 © 2024 Corey Psoinos

此项目是 MIT 许可的。