Vite+Vue3+TypeScript+Element Plus (六) 搭建企业级轻量框架实践

2,403 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

项目开发中图标是不可缺少的部分,一套好的图标解决方案可以大大提高我们开发效率和项目运行效率,本章教程中的静态图标库包含任何图标集 - 超过 10,000 个图标、徽标、表情符号等的 100 多个流行集。由Iconify提供支持。在Iconify中可以找到很多通用常用的图标,unplugin-icons提供了按需加载的技术支持。如果想使用自定义的SVG图标也是支持的。

推荐阅读

vite.config.ts 之 Plugins 篇 (六)

unplugin-icons

  • 安装
# 选择一个你喜欢的包管理器

# NPM
npm install unplugin-icons -D

# Yarn
yarn add unplugin-icons -D

# PNPM
pnpm install unplugin-icons -D

Iconify

我们使用Iconify作为图标数据源(支持 100 多个图标集)。

您有两种安装方式:

  • 安装完整集合
# 选择一个你喜欢的包管理器

# NPM
npm install @iconify/json -D

# Yarn
yarn add @iconify/json -D

# PNPM
pnpm install @iconify/json -D

@iconify/json(~120MB) 包括来自 Iconify 的所有图标集,因此您可以安装一次并根据需要使用其中的任何一个(只有您实际使用的图标才会捆绑到生产版本中)。

如果您只想使用几个图标集而不想下载整个集合,您也可以使用@iconify-json/[collection-id]。 该collection字段遵循Iconify 的集合 IDs。例如,要安装Remix Icons,你可以这样做:

# 选择一个你喜欢的包管理器

# NPM
npm install @iconify-json/ri -D

# Yarn
yarn add @iconify-json/ri -D

# PNPM
pnpm install @iconify-json/ri -D

为了提高您的工作流程,还可以unplugin-icons通过启用该autoInstall选项来处理该安装。 当您导入它们时,它将安装图标集。将自动检测到正确的包管理器(npmyarnpnpm

Icons({
  // expiremental
  autoInstall: true
})
  • Vue 3 支持

需要对等依赖@vue/compiler-sfc在第一章我们已经安装对等版本的依赖这里就不需要再次安装了

Icons({
  compiler: 'vue3',
  // expiremental
  autoInstall: true
})
  • 类型声明

skipLibCheck解决无法打包问题

// tsconfig.json 
{  
  "compilerOptions" : { 
    "types" : [ 
      "vite/client",
      "unplugin-icons/types/vue" , 
    ],
    "skipLibCheck": true, // 解决打包报`vue-tsc --noEmit && vite build`的错,忽略所有的声明文件(*.d.ts)的类型检查
  } 
}
  • 自定义图标

您现在可以加载自己的图标了!unplugin-icons提供FileSystemIconLoader方法用于加载自定义图标。 assets目录下创建icons文件夹导入自己的*.svg图标文件

💡 SVG 编写 Tips:

  • 要使图标的颜色具有适应性,请在SVG中设置'fill=“currentColor”或'stroke=“currentColor”。
  • 不指定“高度”和“宽度”,我们会为您设置。
// 加载器助手
import  {  FileSystemIconLoader  }  from  'unplugin-icons/loaders' 
Icons({
    compiler: "vue3",
    customCollections: {
      // 这里是存放svg图标的文件地址,custom是自定义图标库的名称
      custom: FileSystemIconLoader("./src/assets/icons"),
    },
    autoInstall: true,
  });

与解析器一起使用prefix指定图标前缀名,customCollections明确解析那些图标库。使用组件解析器时,您必须遵循名称转换才能正确推断图标。 {prefix}-{collection}-{icon}

// vite.config.js
import Vue from '@vitejs/plugin-vue'
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'
import Components from 'unplugin-vue-components/vite'

export default {
  plugins: [
    Vue(),
    Components({
      resolvers: [
        IconsResolver({ prefix: "icon", customCollections: ["custom"] }),
      ]
    }),
    Icons(),
  ],
}
  • 完整配置
// unplugin.ts
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import Icons from 'unplugin-icons/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import IconsResolver from 'unplugin-icons/resolver'
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
export function configAutoImportPlugin() {
  return AutoImport({
    imports: ['vue'],
    resolvers: [ElementPlusResolver({ importStyle: false })],
    // 指定文件生成路径
    dts: 'config/unplugin/auto-imports.d.ts',
  })
}
export function configVueComponentsPlugin() {
  return Components({
    // 用于搜索组件的目录的相对路径。
    dirs: ['src/components'],
    resolvers: [
      ElementPlusResolver(),
      IconsResolver({ prefix: 'icon', customCollections: ['custom'] }),
    ],
    // 指定文件生成路径
    dts: 'config/unplugin/components.d.ts',
    // 组件的有效文件扩展名。
    extensions: ['vue'],
    // 允许子目录作为组件的命名空间前缀。
    directoryAsNamespace: false,
    deep: true,
  })
}

export function configVueIconsPlugin() {
  return Icons({
    compiler: 'vue3',
    customCollections: {
      // 这里是存放svg图标的文件地址,custom是自定义图标库的名称
      custom: FileSystemIconLoader('./src/assets/icons'),
    },
    autoInstall: true,
  })
}

  • 添加到plugin中
import vue from '@vitejs/plugin-vue'
import vueSetupExtend from 'vite-plugin-vue-setup-extend'
import legacy from '@vitejs/plugin-legacy'
import OptimizationPersist from 'vite-plugin-optimize-persist'
import PkgConfig from 'vite-plugin-package-config'
import { configCompressPlugin } from './compress'
import { configImageminPlugin } from './imagemin'
import { configStyleImportPlugin } from './style'
import { configAutoImportPlugin, configVueComponentsPlugin, configVueIconsPlugin } from './unplugin'
export function createVitePlugins(isBuild: boolean) {
  const plugins = [
    vue(),
    vueSetupExtend(),
    legacy({
      targets: ['ie >= 11'],
      additionalLegacyPolyfills: ['regenerator-runtime/runtime'],
    }),
    PkgConfig(),
    OptimizationPersist(),
  ]
  if (isBuild) {
    // vite-plugin-compress
    plugins.push(configCompressPlugin())
    // vite-plugin-imagemin
    plugins.push(configImageminPlugin())
  }
  // unplugin-auto-import
  plugins.push(configAutoImportPlugin())
  // unplugin-vue-components
  plugins.push(configVueComponentsPlugin())
  // vite-plugin-style-import
  plugins.push(configStyleImportPlugin())
  // unplugin-icons
  plugins.push(configVueIconsPlugin())
  return plugins
}

  • 使用
// App.vue
<script setup lang="ts" name="App">
</script>

<template>
  <!-- assets/icons/vuejs-fill.svg -->
  <icon-custom-vuejs-fill />
  <!-- https://icones.js.org/collection/ri -->
  <icon-ri-e-bike-2-fill />
  <HelloWorld msg="Hello Vue 3 + TypeScript + Vite" />
</template>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

运行

npm run dev 

打包

npm run build 

生成目录

npm install --global treer
treer -e ./result.md -i "/node_modules|git|dist/"

本章最终目录如下:

├─index.html
├─package.json
├─pnpm-lock.yaml
├─README.md
├─tsconfig.json
├─vite.config.ts
├─src
|  ├─App.vue
|  ├─env.d.ts
|  ├─main.ts
|  ├─components
|  |     └HelloWorld.vue
|  ├─assets
|  |   ├─logo.png
|  |   ├─icons
|  |   |   └vuejs-fill.svg
├─public
|   └favicon.ico
├─config
|   ├─index.ts
|   ├─unplugin
|   |    ├─auto-imports.d.ts
|   |    └components.d.ts
|   ├─plugins
|   |    ├─compress.ts
|   |    ├─imagemin.ts
|   |    ├─index.ts
|   |    ├─style.ts
|   |    └unplugin.ts
├─.vscode
|    ├─extensions.json
|    └settings.json
{
  "name": "admin-vite",
  "private": true,
  "version": "0.0.6",
  "author": {
    "name": "SunHongYu",
    "email": "17600616235@163.com",
    "url": "https://juejin.cn/"
  },
  "resolutions": {
    "bin-wrapper": "npm:bin-wrapper-china"
  },
  "scripts": {
    "bootstrap": "pnpm install",
    "dev": "vite",
    "build": "vue-tsc --noEmit && vite build",
    "preview": "npm run build && vite preview",
    "preview:dist": "vite preview",
    "clean": "rimraf node_modules",
    "clean:cache": "rimraf node_modules/.cache/ && rimraf node_modules/.vite"
  },
  "dependencies": {
    "element-plus": "^2.0.2",
    "vue": "^3.2.31"
  },
  "devDependencies": {
    "@iconify-json/ri": "^1.1.0",
    "@vitejs/plugin-legacy": "^1.7.1",
    "@vitejs/plugin-vue": "^2.2.0",
    "@vue/compiler-sfc": "^3.2.31",
    "consola": "^2.15.3",
    "typescript": "^4.5.5",
    "unplugin-auto-import": "^0.6.1",
    "unplugin-icons": "^0.13.2",
    "unplugin-vue-components": "^0.17.21",
    "vite": "^2.8.2",
    "vite-plugin-compression": "^0.5.1",
    "vite-plugin-imagemin": "^0.6.1",
    "vite-plugin-optimize-persist": "^0.1.2",
    "vite-plugin-package-config": "^0.1.1",
    "vite-plugin-style-import": "^2.0.0",
    "vite-plugin-vue-setup-extend": "^0.4.0",
    "vue-global-api": "^0.4.1",
    "vue-tsc": "^0.31.2"
  },
  "vite": {
    "optimizeDeps": {
      "include": [
        "element-plus/es",
        "element-plus/es/components/button/style/css",
        "element-plus/es/components/link/style/css",
        "vue",
        "vue-global-api"
      ]
    }
  }
}

继续学习

废话只说一句:码字不易求个👍,收藏 === 学会,快行动起来吧!🙇‍🙇‍🙇‍。

# Vite+Vue3+TypeScript+Element (七) 搭建企业级轻量框架实践