Vite源码分析01 目录结构和构建

779 阅读2分钟

Vite源码分析

为了更好的在工作中使用Vite,分析Vite源码,了解Vite的运行流程。 另外,通过源码学习,了解Vite中用的一些框架。扩展自己的知识面。 和大家分享我的学习成果,如果有什么问题?请大家及时纠正。

Vite 目录结构和构建

Github上下载Vite 3.1.0的最新代码。

vite代码地址

安装pnpm

安装命令参照官网:pnpm官网

curl -fsSL https://get.pnpm.io/install.sh | sh -

进入项目根目录安装依赖

pnpm install

workspace package 理解

打开pnpm-workspace.yaml文件,可以看到下面的代码。pnpm-workspace说明

packages:
  - 'packages/*'
  - 'playground/**'

简单的说,配置了pnpm-workspace以后,项目的安装包可以引入workspace文件夹里面的js文件。可以看到,我们可以安装packagesplayground里面的程序。

  // package.json
  "devDependencies": {
    "vite": "workspace:*"
  },

vite 目录理解

vite目录结构如下:

viteDir.jpg

clientnode是源码存放的目录,不能直接使用,需要编译后才能运行。bin目录里的vite.js是程序的入口,可以看到调用的是编译后的cli.js

// 从vite.js里面找到程序入口
function start() {
  return import('../dist/node/cli.js')
}

types文件夹里面,放的是各种type定义文件

types.jpg

打包编译Vite

打开Vite文件夹下的package.json,配置如下:

  "scripts": {
    "dev": "rimraf dist && pnpm run build-bundle -w",
    "build": "rimraf dist && run-s build-bundle build-types",
    "build-bundle": "rollup --config rollup.config.ts --configPlugin typescript",
    "build-types": "run-s build-temp-types patch-types roll-types check-dist-types",
    "build-temp-types": "tsc --emitDeclarationOnly --outDir temp/node -p src/node",
    "patch-types": "tsx scripts/patchTypes.ts",
    "roll-types": "api-extractor run && rimraf temp",
    "check-dist-types": "tsc --project tsconfig.check.json",
    "lint": "eslint --cache --ext .ts src/**",
    "format": "prettier --write --cache --parser typescript \"src/**/*.ts\"",
    "prepublishOnly": "npm run build"
  },

可以看到build-bundle主要是通过rollup进行代码编译打包的,所以打开rollup.config.ts查看各种入口文件:

// env输入文件是env.ts
const envConfig = defineConfig({
  input: path.resolve(__dirname, 'src/client/env.ts'),
  plugins: [
    typescript({
      tsconfig: path.resolve(__dirname, 'src/client/tsconfig.json')
    })
  ],
  output: {
    file: path.resolve(__dirname, 'dist/client', 'env.mjs'),
    sourcemap: true
  }
})

// client输入文件是client.ts
const clientConfig = defineConfig({
  input: path.resolve(__dirname, 'src/client/client.ts'),
  external: ['./env', '@vite/env'],
  plugins: [
    typescript({
      tsconfig: path.resolve(__dirname, 'src/client/tsconfig.json')
    })
  ],
  output: {
    file: path.resolve(__dirname, 'dist/client', 'client.mjs'),
    sourcemap: true
  }
})

// nodeConfig的输入文件有index.ts(各种types定义) cli.ts(核心程序) contants.ts(各种常量)
function createNodeConfig(isProduction: boolean) {
  return defineConfig({
    ...sharedNodeOptions,
    input: {
      index: path.resolve(__dirname, 'src/node/index.ts'),
      cli: path.resolve(__dirname, 'src/node/cli.ts'),
      constants: path.resolve(__dirname, 'src/node/constants.ts')
    },
    output: {
      ...sharedNodeOptions.output,
      sourcemap: !isProduction
    },
    external: [
      'fsevents',
      ...Object.keys(pkg.dependencies),
      ...(isProduction ? [] : Object.keys(pkg.devDependencies))
    ],
    plugins: createNodePlugins(
      isProduction,
      !isProduction,
      // in production we use api-extractor for dts generation
      // in development we need to rely on the rollup ts plugin
      isProduction ? false : path.resolve(__dirname, 'dist/node')
    )
  })
}

进入vite文件夹根目录,运行npm run build进行打包,生成dist文件夹以及里面的js文件

build.jpg

Tips小知识

通过rollupapi-extractor,可以把所有的typescript定义文件都集中生成在一个index.d.ts文件里面。 api-extractor相关知识