nuxt-svgo
nuxt-svgo

用於將最佳化後的 SVG 檔案作為 Vue 元件載入的 Nuxt 模組

nuxt-svgo

npm versionnpm downloadslicense

nuxt-svgo 是一個 Nuxt 模組,用於將最佳化後的 SVG 檔案作為 Vue 元件載入。

StackBlitz 上試用!

安裝

npx nuxi@latest module add nuxt-svgo

使用

透過將 'nuxt-svgo' 新增到 Nuxt 配置的 modules 部分,使用預設配置

// 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-svgo 提供的 nuxt-icon 元件一樣。

示例

// 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,請確保安裝了此模組的對等依賴項 (vue-svg-loader,svgo-loader, vue-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 作為資料 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 查詢的重要說明

資料 URI 工作需要 xmlns="http://www.w3.org/2000/svg" 屬性。在某些極少數情況下,它可能不存在。使用 url_encode 查詢時請確保它存在,否則影像將不會顯示。

與 TypeScript 一起使用

在 TypeScript 中匯入 SVG 元件時,您會收到“找不到模組”錯誤。為了解決這個問題,您應該在模組配置中啟用 dts 選項。這將自動為 SVG 匯入生成 TypeScript 宣告檔案。僅適用於 nuxt-svgo v4.1.0 及更高版本。

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

如果您使用的模組版本低於 v4.1.0,您需要手動提供型別宣告以告訴 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 prop 將它們傳遞給元件。

元件屬性

  • filled:當 true 時,使用圖示的原始顏色
  • fontControlled:您可以將此 prop 設定為 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

表達您的支援

如果此專案對您有幫助,請給個 ⭐!

📝 許可證

版權所有 © 2025 Corey Psoinos

本專案採用 MIT 許可證。