resolve的alias配置
vite的alias,可以配置路径的别名。 主要用来 简化路径、模块替换。
看一下源码里的列子 playground/alias/vite.config.js
// playground/alias/vite.config.js
import path from 'node:path'
import module from 'node:module'
import { defineConfig } from 'vite'
const require = module.createRequire(import.meta.url)
export default defineConfig({
resolve: {
alias: [
{ find: 'fs', replacement: path.resolve(__dirname, 'test.js') },
{ find: 'fs-dir', replacement: path.resolve(__dirname, 'dir') },
{ find: 'dep', replacement: '@vitejs/test-resolve-linked' },
{
find: /^regex\/(.*)/,
replacement: `${path.resolve(__dirname, 'dir')}/$1`,
},
{ find: '/@', replacement: path.resolve(__dirname, 'dir') },
// aliasing an optimized dep
{ find: 'vue', replacement: 'vue/dist/vue.esm-bundler.js' },
// aliasing an optimized dep to absolute URL
{
find: '@vue/shared',
replacement: require.resolve('@vue/shared/dist/shared.cjs.prod.js'),
},
// aliasing one unoptimized dep to an optimized dep
{ find: 'foo', replacement: 'vue' },
{
find: 'custom-resolver',
replacement: path.resolve(__dirname, 'test.js'),
customResolver(id) {
return id.replace('test.js', 'customResolver.js')
},
},
],
},
build: {
minify: false,
},
define: {
__VUE_OPTIONS_API__: true,
__VUE_PROD_DEVTOOLS__: true,
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,
},
})
// playground/alias/index.html
<h1>Alias</h1>
<p class="fs"></p>
<p class="fs-dir"></p>
<p class="regex"></p>
<p class="dep"></p>
<p class="from-script-src"></p>
<p class="aliased-module"></p>
<p class="custom-resolver"></p>
<div class="optimized"></div>
<script type="module">
// no node: protocol intentionally
import { msg as fsMsg } from 'fs'
import { msg as fsDirMsg } from 'fs-dir/test'
import { msg as regexMsg } from 'regex/test'
import { msg as depMsg } from 'dep'
import { msg as moduleMsg } from 'aliased-module/index.js'
import { msg as customResolverMsg } from 'custom-resolver'
function text(el, text) {
document.querySelector(el).textContent = text
}
text('.fs', fsMsg)
text('.fs-dir', fsDirMsg)
text('.regex', regexMsg + ' via regex')
text('.dep', depMsg)
text('.aliased-module', moduleMsg)
text('.custom-resolver', customResolverMsg)
import { createApp } from 'vue'
import { ref } from 'foo'
// vue is aliased to the full browser build AND optimized.
// should resolve as expected
createApp({
template: '[{{ msg }}] alias optimized dep',
setup() {
return {
msg: ref('success'),
}
},
}).mount('.optimized')
// aliased to an absolute URL in CJS, should be optimized
import { isFunction } from '@vue/shared'
// also check name clash for aliased deps
export { isFunction } from '@vue/shared'
console.log(isFunction(() => {}))
</script>
<script type="module" src="/@/from-script-src.js"></script>
<link rel="stylesheet" href="/@/test.css" />
// playground/alias/package.json
{
"name": "@vitejs/test-alias",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"debug": "node --inspect-brk ../../packages/vite/bin/vite",
"preview": "vite preview"
},
"dependencies": {
"aliased-module": "file:./dir/module",
"vue": "^3.5.13",
"@vue/shared": "^3.5.13"
},
"devDependencies": {
"@vitejs/test-resolve-linked": "workspace:*"
}
}
看一下例子 一下就知道干什么用的了。里面有个特殊的用法
"aliased-module": "file:./dir/module",
- 在引入
aliased-module
时,会从当前目录去找,dir/module
下面肯定也有一个package.json
的name
是aliased-module
"@vitejs/test-resolve-linked": "workspace:*"
workspace:*
表示是pnpm
里的安装路径,会安装本地仓库的包,方便调试
源码逻辑分析
在_createServer
里
- 解析config
- 启动服务
- 静态资源中间件
- 路径解析中间件
// packages/vite/src/node/server/index.ts
export async function _createServer(){
// 解析config
const config = await resolveConfig(inlineConfig, 'serve')
// 启动服务
const middlewares = connect() as Connect.Server
const httpServer = middlewareMode
? null
: await resolveHttpServer(serverConfig, middlewares, httpsOptions)
// 注册路径转换的中间件,访问资源主要靠这个
middlewares.use(transformMiddleware(server))
// 注册静态资源中间件
middlewares.use(serveStaticMiddleware(server))
}
访问http://localhost:5173/
时,
会请求到入口的html文件
vite会自动在头部注册/@vite/client
用来热更新用的
还会请求一个dist/client/env.mjs
用来在浏览器访问环境变量的
所有的请求都会经过中间件transformMiddleware
,在这里对请求路径处理