Vite 插件
看下面的示例, index.vue文件默认名称文件名称 svg引入自动转换为组件
vue
<!-- views/text/index.vue -->
<script lang="ts" setup>
import demoSvg from '~/assets/svg/demo.svg?component'
if (import.meta.hot) {
import.meta.hot.on('yang-code', (payload) => {
console.log(payload)
})
}
</script>
<template>
<div>
<demo-svg />
</div>
</template>
Svg转换组件
通过正则匹配文件id 使用node:fs 读入文件内容 借助于@vue/compiler-sfc compileTemplate进行编译
ts
import { basename, dirname } from 'node:path'
import { readFileSync } from 'node:fs'
import { compileTemplate } from '@vue/compiler-sfc'
import type { Plugin, ViteDevServer } from 'vite'
export default function Yang(): Plugin {
const virtualModuleId = 'virtual:yang-module'
const resolvedVirtualModuleId = `\0${virtualModuleId}`
let server: ViteDevServer
return {
name: 'yang-plugin',
transform(code, id) {
if (/\.svg(\?(component))/.test(id)) {
const filepath = id.split('?')[0]
try {
const context = readFileSync(filepath, { encoding: 'utf-8' })
const { code } = compileTemplate({
id,
source: context,
filename: basename(id).split('.')[0],
transformAssetUrls: false
})
return `${code}\nexport default { render: render }`
}
catch (error) {
console.log(error)
}
}
}
}
}
组件 name
自动生成
正则匹配文件id,通过正则匹配_name 进行替换操作
ts
import { MagicString } from '@vue/compiler-sfc'
import type { Plugin, ViteDevServer } from 'vite'
export default function Yang(): Plugin {
const virtualModuleId = 'virtual:yang-module'
const resolvedVirtualModuleId = `\0${virtualModuleId}`
let server: ViteDevServer
return {
name: 'yang-plugin',
transform(code, id) {
if (/index.vue$/.test(id)) {
const _dirname = dirname(id).split('/').at(-1)
if (_dirname) {
server.ws.send('yang-code', code)
const s = new MagicString(code)
s.replace(/(?<=__name: ")\w+/, _dirname)
return {
id,
code: s.toString()
}
}
}
}
}
}
类型提示
解决类型提示错误 import demoSvg from '~/assets/svg/demo.svg?component'
ts
// src/env.d.ts
declare module '*?component' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<object, object, any>
export default component
}