背景
我们在使用vite搭建项目的时候,需要引入部分资源文件,我们如果通过相对路径../的形式来导入不同模块下的文件,这样就会存在很繁琐的问题。此时呢,vite提供了一个配置项resolve.alias来设置路径别名。
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import ViteAlias from './src/plugins/ViteAlias';
// https://vite.dev/config/
export default defineConfig({
plugins: [vue(), ViteAlias()],
resolve: {
alias: {
'@': path.resolve(process.cwd(), './src'),
},
},
});
我们一般通过resolve.alias来进行配置,当然我们也可以直接使用第三方插件vite-aliases来自动实现。
vite-aliases用法
首先安装一下 pnpm i vite-aliases ,然后在vite.config.js文件中使用该插件即可,其他配置项都是默认的即可。
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
// import ViteAlias from './src/plugins/ViteAlias';
import { ViteAliases } from 'vite-aliases';
// https://vite.dev/config/
export default defineConfig({
plugins: [vue(), ViteAliases()],
});
这样就直接完成了 别名插件的导入了,然后在项目中只要是src文件下的文件夹都可以通过@/xxx来进行识别啦。
插件原理解析
这个插件的原理其实比较简单的,就是识别当前项目src文件夹下的文件夹,然后配置一个配置项,通过插件的形式供vite源码读取并合并最终的config配置项。
在写插件过程中,需要注意vite的插件也是像vue3一样具备生命周期的,在不同的阶段提供不同的钩子函数。(插件 API | Vite 官方中文文档),为完成本节的目的,我们使用了config钩子函数进行插件的编写。
config钩子函数 是在vite处理vite.config.js文件之前进行的,这个函数返回一个对象(部分配置内容),而vite.config.js返回的也是部分内容,在vite中会将两部分内容合并然后进行处理。这个钩子函数中的config参数是vite.config.js中的内容。
// 插件都是函数哈,类似于express/koa中的中间件
// config参数:(config: UserConfig, env: { mode: string, command: string }) => UserConfig | null | void
//用法一 返回部分配置(推荐)
const partialConfigPlugin = () => (
{ name: 'return-partial',
config: () => ({ resolve: { alias: { foo: 'bar' } } })
}
)
// 用法二 直接改变配置(应仅在合并不起作用时使用)
const mutateConfigPlugin = () => (
{
name: 'mutate-config',
config(config, { command }) {
if (command === 'build') {
config.root = 'foo'
}
}
})
在了解了上述内容之后我们可以编写一个类似于vite-aliases的插件啦
插件复现
import fs from 'fs';
import path from 'path';
export default function ViteAlias({ aliasKey = '@', rootPath = './src' } = {}) {
return {
name: 'vite-alias',
config: (config, env) => {
console.log(config, env);
if (env.mode === 'development') {
const alias = {
[aliasKey]: path.resolve(process.cwd(), rootPath),
};
const dirs = fs.readdirSync(alias[aliasKey]);
dirs.forEach(dir => {
const fileStats = fs.statSync(
path.resolve(process.cwd(), `./src/${dir}`)
);
if (fileStats.isDirectory()) {
const key = `${aliasKey}/${dir}`;
alias[key] = path.resolve(process.cwd(), `./src/${dir}`);
}
});
return {
resolve: {
alias,
},
};
}
},
};
}
完成之后我们需要在vite.config.js文件中去使用该插件。核心原理就是读取文件路径然后替换,最终返回resolve.alias内容,然后vite会将插件返回的内容和配置的vite.config.js内容合并 然后进行接下来的其他处理。插件返回的配置项通常会覆盖 vite.config.js 中的相同配置项。
知识点总结
- fs模块:
- readdirSync函数:同步读取文件夹下得内容文件内容
- statSync函数:读取当前文件的源信息(文件创建的时候就自带的)
- 该函数返回一个对象,可以继续调用其方法判断是否是文件是否是文件夹等信息,具体看NodeJs官网File system | Node.js v23.6.1 Documentation
- path模块:
- resolve函数:用法类似于cd的形式,例子:resolve(path1,path2,path3),类似于cd path1 然后cd path2 然后 cd path3,如果路径之间没用递进关系的话就会进入新的路径中,有的话就是递进。path.resolve()的终极理解_path.resolve作用-CSDN博客
- process.cwd():返回当前执行进程的目录,在写第三方插件的时候推荐用这个路径。
- config函数:用于重写vite.config.js中的配置信息的一个钩子函数。