resolve的alias配置

3 阅读2分钟

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.jsonnamealiased-module

"@vitejs/test-resolve-linked": "workspace:*"

  • workspace:*表示是pnpm里的安装路径,会安装本地仓库的包,方便调试

源码逻辑分析

_createServer

  1. 解析config
  2. 启动服务
  3. 静态资源中间件
  4. 路径解析中间件
// 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,在这里对请求路径处理