如何在Nuxt项目中动态导入Font Awesome图标。

huangapple go评论89阅读模式
英文:

How to make dynamic import of fontawesome icon in nuxt project

问题

我刚刚使用 Nuxt 框架 v3.6.2 创建了一个新项目,想要使用 Font Awesome 图标。
为了保持可维护性并能够在其他情境中使用它们,我想将我的图标列表(名称和包)存储在一个数组中,并使用它来导入它们。

不幸的是,我正在使用的代码(见下文)似乎不起作用,因为它找不到模块并返回以下错误:

500

[vite-node] [ERR_LOAD_URL] import { faHouse as fasHouse } from
'@fortawesome/free-solid-svg-icons'

at import { faHouse as fasHouse } from
'@fortawesome/free-solid-svg-icons'

我认为这是由于配置错误导致无法执行动态导入。有没有人有解决方案的想法?

nuxt.config.ts

// 你的 Nuxt 配置文件

utils.ts

// 你的工具函数文件

fontawesome.ts

// 你的 Font Awesome 配置文件

我尝试将插件添加到 Nuxt 配置中,但没有太大改善。至于 Vite 配置,我也找不到太多相关信息。

英文:

I have just created a new project using the Nuxt framework v3.6.2, and I want to use Font Awesome icons.
For the sake of maintainability and to be able to use them in other contexts, I would like to keep the list of my icons (name and pack) in an array and use it to import them.

Unfortunately, the code I'm using (see below) doesn't seem to work because it can't find the module and returns the following error:

> 500
>
> [vite-node] [ERR_LOAD_URL] import { faHouse as fasHouse } from
> '@fortawesome/free-solid-svg-icons'
>
> at import { faHouse as fasHouse } from
> '@fortawesome/free-solid-svg-icons'

I think it's due to a configuration error that is preventing me from performing dynamic imports. Does anyone have any ideas for a solution?

nuxt.config.ts

export default defineNuxtConfig({
  app: {
    head: {
      title: 'front_social',
      meta: [
        {
          name: 'viewport',
          content: 'width=device-width, initial-scale=1'
        },
        {
          charset: 'utf-8'
        }
      ],
      link: [],
      style: [],
      script: [],
      noscript: [
        {
          children: 'JavaScript est obligatoire pour afficher cette page.'
        }
      ]
    },
    keepalive: false,
    layoutTransition: false,
    pageTransition: false
  },
  appConfig: {},
  buildDir: 'build',
  builder: 'vite',
  components: [
    {
      path: '~/components/global-social',
      prefix: 'S',
      pathPrefix: false
    }
  ],
  css: ['~/assets/css/main.scss', '@fortawesome/fontawesome-svg-core/styles.css'],
  debug: Boolean(process.env.NODE_ENV === 'development'),
  dev: Boolean(process.env.NODE_ENV === 'development'),
  devServer: {
    host: 'localhost',
    https: false,
    port: 8081,
    url: 'http://localhost:8081'
  },
  extensions: ['.js', '.jsx', '.mjs', '.ts', '.tsx', '.vue'],
  imports: {
    dirs: ['composables', 'utils', 'stores'],
    global: false
  },
  modules: ['@nuxtjs/eslint-module', '@nuxtjs/tailwindcss', '@nuxtjs/color-mode', '@pinia/nuxt'],
  eslint: {
    cache: true,
    include: ['~/**/*.{js,ts,vue}'],
    eslintPath: 'eslint',
    formatter: 'stylish',
    lintOnStart: true,
    emitWarning: true,
    emitError: true,
    failOnWarning: false,
    failOnError: false
  },
  tailwindcss: {
    cssPath: '~/assets/css/tailwind.css',
    configPath: 'tailwind.config.ts',
    exposeConfig: false,
    exposeLevel: 2,
    injectPosition: 'first',
    viewer: false
  },
  colorMode: {
    preference: 'system',
    fallback: 'light',
    hid: 'nuxt-color-mode-script',
    globalName: '__NUXT_COLOR_MODE__',
    componentName: 'ColorScheme',
    classPrefix: '',
    classSuffix: '',
    storageKey: 'nuxt-color-mode'
  },
  pinia: {
    autoImports: ['defineStore', 'acceptHMRUpdate']
  },
  modulesDir: ['node_modules'],
  pages: true,
  plugins: [],
  router: {},
  serverDir: 'server',
  sourcemap: {
    server: true,
    client: Boolean(process.env.NODE_ENV === 'development')
  },
  srcDir: 'src/',
  typescript: {
    includeWorkspace: false,
    shim: false,
    strict: true,
    tsConfig: {
      compilerOptions: {
        strict: true
      }
    },
    typeCheck: true
  },
  vite: {
    logLevel: 'info',
    define: {
      'process.dev': Boolean(process.env.NODE_ENV === 'development')
    },
    mode: process.env.NODE_ENV,
    resolve: {
      extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
    },
    server: {
      fs: {
        allow: ['build', 'node_modules']
      }
    },
    vue: {
      isProduction: Boolean(process.env.NODE_ENV === 'production')
    }
  }
})

utils.ts

import { IconStyle } from '@fortawesome/fontawesome-svg-core'

export const iconMap: Record<string, IconStyle[]> = {
  house: ['solid'],
  user: ['solid', 'regular']
}
export const iconVariants: string[] = Object.keys(iconMap)
export type IconVariants = keyof typeof iconMap
export const iconVariantsValidator = (variant: string) => iconVariants.includes(variant)

fontawesome.ts

import { library, config } from '@fortawesome/fontawesome-svg-core'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import { iconMap, iconVariants } from '~/components/global-social/basic/Icon/utils'

function generateIconImports() {
  const importMap: Record<string, Record<string, string>> = {
    solid: {
      prefix: 'fas',
      path: '@fortawesome/free-solid-svg-icons'
    },
    regular: {
      prefix: 'far',
      path: '@fortawesome/free-regular-svg-icons'
    },
    brands: {
      prefix: 'fab',
      path: '@fortawesome/free-brands-svg-icons'
    }
  }

  const imports = []
  for (const iconName of iconVariants) {
    const iconStyles = iconMap[iconName]

    imports.push(
      ...iconStyles.map(async iconStyle => {
        const name = `${iconName.charAt(0).toUpperCase()}${iconName.slice(1)}`
        return import(
          /* @vite-ignore */
          `import { fa${name} as ${importMap[iconStyle].prefix}${name} } from '${importMap[iconStyle].path}'`
        )
      })
    )
  }
  return imports
}

await Promise.all(generateIconImports()).then(icons => {
  for (const icon of icons) library.add(icon)
})

config.autoAddCss = false

export default defineNuxtPlugin(nuxtApp => {
  nuxtApp.vueApp.component('font-awesome-icon', FontAwesomeIcon)
})

I tried adding the plugin to the Nuxt configuration, but it didn't make much of a difference. As for the Vite configuration, I couldn't find much either.

答案1

得分: 1

以下是您要翻译的内容:

utils.ts

import { IconStyle, IconDefinition } from '@fortawesome/fontawesome-svg-core'
import { camelCaseToKebabCase, kebabCaseToPascalCase } from '~/utils/formats'

export const iconMap: Record<string, IconStyle[]> = {
  plus: ['solid'],
  trash: ['solid'],
  user: ['solid', 'regular'],
  'circle-notch': ['solid'],
  github: ['brands']
}

export const iconImports: string[] = Object.keys(iconMap).map(key => `fa${kebabCaseToPascalCase(key)}`)

export const getIconLibrary = (icons: any, prefix: string, pack: IconStyle) =>
  Object.keys(icons)
    .filter(
      key =>
        key !== prefix &&
        key !== 'prefix' &&
        iconImports.includes(key) &&
        iconMap[camelCaseToKebabCase(key).replace('fa-', '')].includes(pack)
    )
    .map(icon => icons[icon as keyof typeof icons]) as IconDefinition[]

fontawesome.ts

import { library, config } from '@fortawesome/fontawesome-svg-core'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import * as fasIcons from '@fortawesome/free-solid-svg-icons'
import * as farIcons from '@fortawesome/free-regular-svg-icons'
import * as fabIcons from '@fortawesome/free-brands-svg-icons'
import { getIconLibrary } from '~/components/global-social/forms/Icon/utils'

const fasIconList = getIconLibrary(fasIcons, 'fas', 'solid')
const farIconList = getIconLibrary(farIcons, 'far', 'regular')
const fabIconList = getIconLibrary(fabIcons, 'fab', 'brands')

library.add(...fasIconList, ...farIconList, ...fabIconList)

config.autoAddCss = false

export default defineNuxtPlugin(nuxtApp => {
  nuxtApp.vueApp.component('FontAwesomeIcon', FontAwesomeIcon)
})

请注意,我已经将代码部分从您提供的内容中翻译出来。

英文:

I'm not sure if it's the best way to solve the problem, but I found a fairly clean and functional solution.

Instead of importing only the icons I need, I import everything and only add to the library the ones that are actually used.

So, I have the following codes:

utils.ts

import { IconStyle, IconDefinition } from &#39;@fortawesome/fontawesome-svg-core&#39;
import { camelCaseToKebabCase, kebabCaseToPascalCase } from &#39;~/utils/formats&#39;

export const iconMap: Record&lt;string, IconStyle[]&gt; = {
  plus: [&#39;solid&#39;],
  trash: [&#39;solid&#39;],
  user: [&#39;solid&#39;, &#39;regular&#39;],
  &#39;circle-notch&#39;: [&#39;solid&#39;],
  github: [&#39;brands&#39;]
}

export const iconImports: string[] = Object.keys(iconMap).map(key =&gt; `fa${kebabCaseToPascalCase(key)}`)

export const getIconLibrary = (icons: any, prefix: string, pack: IconStyle) =&gt;
  Object.keys(icons)
    .filter(
      key =&gt;
        key !== prefix &amp;&amp;
        key !== &#39;prefix&#39; &amp;&amp;
        iconImports.includes(key) &amp;&amp;
        iconMap[camelCaseToKebabCase(key).replace(&#39;fa-&#39;, &#39;&#39;)].includes(pack)
    )
    .map(icon =&gt; icons[icon as keyof typeof icons]) as IconDefinition[]

fontawesome.ts

import { library, config } from &#39;@fortawesome/fontawesome-svg-core&#39;
import { FontAwesomeIcon } from &#39;@fortawesome/vue-fontawesome&#39;
import * as fasIcons from &#39;@fortawesome/free-solid-svg-icons&#39;
import * as farIcons from &#39;@fortawesome/free-regular-svg-icons&#39;
import * as fabIcons from &#39;@fortawesome/free-brands-svg-icons&#39;
import { getIconLibrary } from &#39;~/components/global-social/forms/Icon/utils&#39;

const fasIconList = getIconLibrary(fasIcons, &#39;fas&#39;, &#39;solid&#39;)
const farIconList = getIconLibrary(farIcons, &#39;far&#39;, &#39;regular&#39;)
const fabIconList = getIconLibrary(fabIcons, &#39;fab&#39;, &#39;brands&#39;)

library.add(...fasIconList, ...farIconList, ...fabIconList)

config.autoAddCss = false

export default defineNuxtPlugin(nuxtApp =&gt; {
  nuxtApp.vueApp.component(&#39;FontAwesomeIcon&#39;, FontAwesomeIcon)
})

huangapple
  • 本文由 发表于 2023年7月13日 17:01:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76677643.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定