Skip to content

TypeScript Type Hints for Configuration Items in Vite

The default configuration file for vite is vite.config.ts, and the most basic configuration file format is as follows:

ts
export default {
  // configuration options
};

We can also specify a configuration file using the --config command line option, by entering: vite --config configFile.js.

When adding vite configuration using the vscode editor, there are no hints from the compiler, which is not user-friendly! (The hint in the image below is not a vite configuration hint, but rather a general JS syntax hint from the plugin)

WebStorm has excellent syntax completion functionality, while vscode does not. Therefore, to enable intelligent hints from the compiler, we can use the following two special approaches.

defineConfig

Using the official defineConfig, you can see configuration item hints.

Looking at the source code:

ts
export type UserConfigFn = (
  env: ConfigEnv
) => UserConfig | Promise<UserConfig>;
export type UserConfigExport =
  | UserConfig
  | Promise<UserConfig>
  | UserConfigFn;

/**
 * Type helper to make it easier to use vite.config.ts
 * accepts a direct {@link UserConfig} object, or a function that returns it.
 * The function receives a {@link ConfigEnv} object that exposes two properties:
 * `command` (either `'build'` or `'serve'`), and `mode`.
 */
export function defineConfig(config: UserConfigExport): UserConfigExport {
  return config;
}

We can see that it essentially uses TypeScript for type hints.

JSDoc Comment Method

JSDoc is an API documentation generator for JavaScript, official website.

Using comments to provide type hints for referenced objects:

ts
/** @type import("vite").UserConfig  */

Environment Mode Configuration

In the webpack era, developers typically set up different configuration files based on different environments, such as: webpack.dev.config, webpack.prod.config, webpack.base.config...

In vite, to set different configurations based on different environments, you just need to export a function like this:

ts
export default defineConfig(({ command, mode, ssrBuild }) => {
  if (command === 'serve') {
    return {
      // dev-specific configuration
    };
  } else {
    // command === 'build'
    return {
      // build-specific configuration
    };
  }
});

Optimized writing style:

ts
import { defineConfig } from 'vite';
import viteBaseConfig from './vite.base.config';
import viteDevConfig from './vite.dev.config';
import viteProdConfig from './vite.prod.config';

const envResolver = {
  // build: () => ({...viteBaseConfig,viteProdConfig}) this way also works
  // The {} in Object.assign is to prevent viteBaseConfig from being modified.
  build: () => ({ ...viteBaseConfig, ...viteProdConfig }),
  serve: () => ({ ...viteBaseConfig, ...viteDevConfig })
};
export default defineConfig(({ command, mode, ssrBuild }) => {
  return envResolver[command]();
});

Additionally, defineConfig also supports asynchronous configuration. If the configuration needs to call an asynchronous function, you can export an asynchronous function instead:

ts
export default defineConfig(async ({ command, mode }) => {
  const data = await asyncFunction();
  return {
    // vite configuration
  };
});

Contributors

Changelog

Discuss

Released under the CC BY-SA 4.0 License. (dbcbf17)