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

2,270 阅读5分钟

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

推荐阅读

vite.config.ts 之 Plugins 篇 (二)

unplugin-vue-components - 自动导入、按需导入组件

自动导入组件,以往使用组件时必须要import导入后在使用。通过unplugin-auto-import实现自动导入,配合Element Plus组件库也可以实现按需加载(其他主流组件库也支持)

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

# NPM
npm install unplugin-vue-components -D

# Yarn
yarn add unplugin-vue-components -D

# PNPM
pnpm install unplugin-vue-components -D
  • 配置
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueSetupExtend from 'vite-plugin-vue-setup-extend'
import legacy from '@vitejs/plugin-legacy'
import compressPlugin from 'vite-plugin-compression'
import viteImagemin from 'vite-plugin-imagemin'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    ...省略插件配置,
    Components({
      dirs: ['src/components'],
      resolvers: [ElementPlusResolver()],
      // 组件的有效文件扩展名。
      extensions: ['vue'],
      // 允许子目录作为组件的命名空间前缀。
      directoryAsNamespace: false,
      deep: true,
    }),
  ],
})

去掉 import HelloWorld from './components/HelloWorld.vue'代码也可以正常使用HelloWorld组件

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

<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <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>

运行打包会自动生成components.d.ts文件内容如下:

// generated by unplugin-vue-components
// We suggest you to commit this file into source control
// Read more: https://github.com/vuejs/vue-next/pull/3399

declare module 'vue' {
  export interface GlobalComponents {
    HelloWorld: typeof import('./src/components/HelloWorld.vue')['default']
  }
}

export { }

element-plusVue 3 的桌面端组件库

Element Plus 目前还处于快速开发迭代中。目前使用2.0.1版可以结合vite-plugin-style-import插件按需加载样式。 unplugin-vue-components 按需自动导入组件 使用 Element Plus组件时可以直接使用

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

# NPM
npm install element-plus --save

# Yarn
yarn add element-plus

# pnpm
pnpm install element-plus

vite-plugin-style-import - 按需引入组件库样式

vite-plugin-style-import新最新版本(新版本需安装consola才能正常运行)

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

# NPM
npm install vite-plugin-style-import consola -D

# Yarn
yarn add vite-plugin-style-import consola -D

# PNPM
pnpm install vite-plugin-style-import consola -D 
  • 配置
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueSetupExtend from 'vite-plugin-vue-setup-extend'
import legacy from '@vitejs/plugin-legacy'
import compressPlugin from 'vite-plugin-compression'
import viteImagemin from 'vite-plugin-imagemin'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import { createStyleImportPlugin, ElementPlusResolve } from 'vite-plugin-style-import'
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    ...省略插件配置,
    Components({
      // 指明组件存放目录
      dirs: ['src/components'],
      resolvers: [ElementPlusResolver()],
      // 组件的有效文件扩展名。
      extensions: ['vue'],
      // 允许子目录作为组件的命名空间前缀。
      directoryAsNamespace: false,
      deep: true,
    }),
    createStyleImportPlugin({ resolves: [ElementPlusResolve()] }),
  ],
})

使用Element PlusUI库自动导入样式,unplugin-vue-components 按需自动导入组件

  • 使用
// HelloWorld.vue
<script setup lang="ts">
import { ref } from 'vue'

defineProps<{ msg: string }>()

const count = ref(0)
</script>

<template>
  <h1>{{ msg }}</h1>

  <p>
    Recommended IDE setup:
    <el-link type="danger" href="https://code.visualstudio.com/" target="_blank">VSCode</el-link>
    +
    <el-link  type="primary" href="https://github.com/johnsoncodehk/volar/" target="_blank">Volar</el-link>
  </p>

  <p>See <code>README.md</code> for more information.</p>

  <p>
    <el-link type="success" href="https://vitejs.dev/guide/features.html" target="_blank">
      Vite Docs
    </el-link>
    |
    <el-link type="success" href="https://v3.vuejs.org/" target="_blank">Vue 3 Docs</el-link>
  </p>
  <el-button type="primary"  @click="count++">count is: {{ count }}</el-button>
  <p>
    Edit
    <code>components/HelloWorld.vue</code> to test hot module replacement.
  </p>
</template>

<style scoped>
a {
  color: #42b983;
}

label {
  margin: 0 0.5em;
  font-weight: bold;
}

code {
  background-color: #eee;
  padding: 2px 4px;
  border-radius: 4px;
  color: #304455;
}
</style>

unplugin-auto-import - API自动导入

setup语法让我们不用再一个一个的把变量和方法都return出去就能在模板上使用,大大的解放了我们的双手。然而对于一些常用的VueAPI,比如refcomputedwatch等,还是每次都需要我们在页面上手动进行import { ref } from 'vue'
可以通过unplugin-auto-import实现自动导入,无需import即可在文件里使用Vue的API。

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

# NPM
npm install unplugin-auto-import -D

# Yarn
yarn add unplugin-auto-import -D

# PNPM
pnpm install unplugin-auto-import -D 
  • 配置
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueSetupExtend from 'vite-plugin-vue-setup-extend'
import legacy from '@vitejs/plugin-legacy'
import compressPlugin from 'vite-plugin-compression'
import viteImagemin from 'vite-plugin-imagemin'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import { createStyleImportPlugin, ElementPlusResolve } from 'vite-plugin-style-import'
import AutoImport from 'unplugin-auto-import/vite'
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    ...省略插件配置,
    Components({
      dirs: ['src/components'],
      resolvers: [ElementPlusResolver()],
      // 组件的有效文件扩展名。
      extensions: ['vue'],
      // 允许子目录作为组件的命名空间前缀。
      directoryAsNamespace: false,
      deep: true,
    }),
    createStyleImportPlugin({ resolves: [ElementPlusResolve()] }),
    AutoImport({
      imports: ['vue'],
      resolvers: [ElementPlusResolver({ importStyle: false })],
    }),
  ],
})

HelloWorld.vue组件去掉,import { ref } from 'vue' 可以正常使用

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

defineProps<{ msg: string }>()

const count = ref(0)
</script>

<template>
  <h1>{{ msg }}</h1>

  <p>
    Recommended IDE setup:
    <el-link type="danger" href="https://code.visualstudio.com/" target="_blank">VSCode</el-link>+
    <el-link type="primary" href="https://github.com/johnsoncodehk/volar/" target="_blank">Volar</el-link>
  </p>

  <p>
    See
    <code>README.md</code> for more information.
  </p>

  <p>
    <el-link type="success" href="https://vitejs.dev/guide/features.html" target="_blank">Vite Docs</el-link>|
    <el-link type="success" href="https://v3.vuejs.org/" target="_blank">Vue 3 Docs</el-link>
  </p>
  <el-button type="primary" @click="count++">count is: {{ count }}</el-button>
  <p>
    Edit
    <code>components/HelloWorld.vue</code> to test hot module replacement.
  </p>
</template>

<style scoped>
a {
  color: #42b983;
}

label {
  margin: 0 0.5em;
  font-weight: bold;
}

code {
  background-color: #eee;
  padding: 2px 4px;
  border-radius: 4px;
  color: #304455;
}
</style>

运行打包会自动生成auto-imports.d.ts文件内容如下:

// Generated by 'unplugin-auto-import'
// We suggest you to commit this file into source control
declare global {
  const computed: typeof import('vue')['computed']
  const createApp: typeof import('vue')['createApp']
  const customRef: typeof import('vue')['customRef']
  const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
  const defineComponent: typeof import('vue')['defineComponent']
  const effectScope: typeof import('vue')['effectScope']
  const EffectScope: typeof import('vue')['EffectScope']
  const getCurrentInstance: typeof import('vue')['getCurrentInstance']
  const getCurrentScope: typeof import('vue')['getCurrentScope']
  const h: typeof import('vue')['h']
  const inject: typeof import('vue')['inject']
  const isReadonly: typeof import('vue')['isReadonly']
  const isRef: typeof import('vue')['isRef']
  const markRaw: typeof import('vue')['markRaw']
  const nextTick: typeof import('vue')['nextTick']
  const onActivated: typeof import('vue')['onActivated']
  const onBeforeMount: typeof import('vue')['onBeforeMount']
  const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
  const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
  const onDeactivated: typeof import('vue')['onDeactivated']
  const onErrorCaptured: typeof import('vue')['onErrorCaptured']
  const onMounted: typeof import('vue')['onMounted']
  const onRenderTracked: typeof import('vue')['onRenderTracked']
  const onRenderTriggered: typeof import('vue')['onRenderTriggered']
  const onScopeDispose: typeof import('vue')['onScopeDispose']
  const onServerPrefetch: typeof import('vue')['onServerPrefetch']
  const onUnmounted: typeof import('vue')['onUnmounted']
  const onUpdated: typeof import('vue')['onUpdated']
  const provide: typeof import('vue')['provide']
  const reactive: typeof import('vue')['reactive']
  const readonly: typeof import('vue')['readonly']
  const ref: typeof import('vue')['ref']
  const resolveComponent: typeof import('vue')['resolveComponent']
  const shallowReactive: typeof import('vue')['shallowReactive']
  const shallowReadonly: typeof import('vue')['shallowReadonly']
  const shallowRef: typeof import('vue')['shallowRef']
  const toRaw: typeof import('vue')['toRaw']
  const toRef: typeof import('vue')['toRef']
  const toRefs: typeof import('vue')['toRefs']
  const triggerRef: typeof import('vue')['triggerRef']
  const unref: typeof import('vue')['unref']
  const useAttrs: typeof import('vue')['useAttrs']
  const useCssModule: typeof import('vue')['useCssModule']
  const useCssVars: typeof import('vue')['useCssVars']
  const useSlots: typeof import('vue')['useSlots']
  const watch: typeof import('vue')['watch']
  const watchEffect: typeof import('vue')['watchEffect']
}
export {}

vue-global-api

解决使用unplugin-auto-import开发时VSCode出现错误提示、并且无法打包问题

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

# NPM
npm install vue-global-api -D

# Yarn
yarn add vue-global-api -D

# PNPM
pnpm install vue-global-api -D 
  • 配置
// main.ts
import 'vue-global-api'
import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

运行

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
├─tsconfig.node.json
├─vite.config.ts
├─src
|  ├─App.vue
|  ├─env.d.ts
|  ├─main.ts
|  ├─components
|  |     └HelloWorld.vue
|  ├─assets
|  |   └logo.png
├─public
|   └favicon.ico
├─.vscode
|    ├─extensions.json
|    └settings.json
{
  "name": "admin-vite",
  "private": true,
  "version": "0.0.2",
  "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": {
    "@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-vue-components": "^0.17.21",
    "vite": "^2.8.2",
    "vite-plugin-compression": "^0.5.1",
    "vite-plugin-imagemin": "^0.6.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+Vue3+TypeScript+Element (三) 搭建企业级轻量框架实践