Learning vite
- Vite serve node_modules package with esm module, so we can import package directly in browser. But it only support esm module, so we need to add
type: modulein package.json. - Each import will create a request to dev server.
- For example, we can import lodash in browser with
import _ from 'lodash'directly. - Vite will create a virtual file for each package in node_modules, and it will be cached in
node_modules/.vite/depsfolder. So it will be faster when we import package next time.
- When import the css file, we are requesting the js file which contains the js code to inject the css file into html by creating a
styletag. - For inline style, we can use
import style from 'xxx.css?inline'to import the css file and inject this style string into html by creating astyletag.
- We can use
import style from 'xxx.module.css'to import css module. - We can use
style.xxxto access the class name in css module. - Vite will transform the css module to js module, and the js module will export a object which contains the class name as key and the class name as value. This key will be hashed by vite. So css module can avoid the conflict of class name and scope the class name in the component.
- Can config the css module in
vite.config.jsref: https://vitejs.dev/config/shared-options.html#css-modules
export default defineConfig({
css: {
modules: {
scopeBehaviour: 'local',
localsConvention: 'camelCaseOnly'
}
}
});- Install tailwindcss and postcss
npm install -D tailwindcss postcss autoprefixer- Create
postcss.config.jsandtailwind.config.jsin root folder. - We can config postcss in
vite.config.jsref: https://vitejs.dev/config/shared-options.html#css-postcss
import { defineConfig } from 'vite';
import tailwindcss from 'tailwindcss';
import autoprefixer from 'autoprefixer';
export default defineConfig({
css: {
postcss: {
plugins: [
tailwindcss,
autoprefixer,
],
},
},
});-Note if an inline config is provided, Vite will not search for other PostCSS config sources.
- Vite support preprocessors like sass, less, stylus.
- There is no need to install Vite-specific plugins for them, but the corresponding pre-processor itself must be installed.
- Can add additional data to the preprocessor by using
additionalDataoption.
import { defineConfig } from 'vite';
export default defineConfig({
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "./src/styles/variables.scss";`,
},
},
},
});Built-in support for importing common static asset types, including images, fonts, and media files. Ref: https://vitejs.dev/guide/assets.html#static-asset-handling
Vite will transform json files to js module, and the js module will export a object which contains the json data. Add ?url to the end of the import path to get the url of the json file.
import data from './data.json';
// data is the json object
import data from './data.json?url';
// data is path of the json fileImporting a static asset will return the resolved public URL when it is served:
import imgUrl from 'src/assets/logo.png';For example, imgUrl will be /src/assets/logo.png during development, and become /assets/logo.2d8efhg.png in the production build.
Browser will request http://localhost:5173/src/assets/logo.png?import to get the script
and http://localhost:5173/src/assets/logo.png to get the image in development mode
and ${base}/assets/logo.2d8efhg.png to get the image in production mode.
Raw assets can be imported as strings using the ?raw suffix:
import img from './img.png?raw';- Vite will serve the files in public folder as static assets.
- The public folder is not part of the build output, and will be directly copied to the root of your build directory.
- The public folder is also useful for assets that need to maintain the same URL across builds, such as
robots.txtorfavicon.ico. - Vite will serve the files at
/path, so we can access the files in public folder directly.
- Vite support multiple pages by creating multiple entry .html files in root folder. Also can nested the .html files in sub folder. But when navigate to the sub page, the url will be
http://localhost:5173/nested/. - Config the build need to do is to specify multiple .html files as entry points
export default defineConfig({
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
nested: resolve(__dirname, 'nested/index.html'),
},
},
},
});- Vite support react and jsx out of the box.JSX transpilation is also handled via esbuild.
- If not use react, config
jsxFactoryandjsxFragmentinvite.config.jsto avoid the warning.
export default defineConfig({
esbuild: {
jsxFactory: 'your-jsx-factory',
jsxFragment: 'Fragment',
},
});- You can inject the JSX helpers using jsxInject (which is a Vite-only option) to avoid manual imports:
export default defineConfig({
esbuild: {
jsxInject: `import React from 'react'`,
},
});- Add
@vitejs/plugin-reactto support react refresh, use the automatic JSX runtime and custom babel plugins.
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
});- Vite support typescript out of the box. It will use esbuild to transform typescript to js.
- Vite does not type-check your code by default.
- Vite config can be a typescript file, so we can use typescript to config vite by create
tsconfig.node.jsonin root folder.- Add
tsconfig.node.jsontoreferencesintsconfig.json - Install
@types/nodeto support node types invite.config.ts - Add
esModuleInteroptocompilerOptionsintsconfig.node.jsonto supportimportsyntax invite.config.ts
- Add
- For client type add
vite.d.tsin root folder and add"vite.d.ts"toincludesintsconfig.jsonor addvite/clienttotypesintsconfig.json- Asset imports (e.g. importing an .svg file)
- Types for the Vite-injected env variables on
import.meta.env - Types for the Vite-specific
import.meta.hotAPI
// vite.d.ts
/// <reference types="vite/client" />- Install
eslint,eslint-config-prettier,eslint-plugin-prettierfor analyzing code and formatting code. - Install
@typescript-eslint/eslint-plugin,@typescript-eslint/parserfor custom eslint parser and plugin.- Now eslint will use
@typescript-eslint/parserto parse typescript file and use@typescript-eslint/eslint-pluginto analyze typescript code base on thetsconfig.json. - Include file that need to be analyzed in
includesintsconfig.json.
- Now eslint will use
- Vite does not support path alias out of the box,
- If the project use typescript, we can use
baseUrlandpathsintsconfig.jsonto support path alias. - Config
aliasinvite.config.jsto support path alias in js file.
import { defineConfig } from 'vite';
export default defineConfig({
resolve: {
alias: {
src: path.resolve(__dirname, './src'),
},
},
});- Alternatively, you can use the
vite-tsconfig-pathsplugin to sync thepathsintsconfig.jsonto Vite's alias config.
import tsconfigPaths from 'vite-tsconfig-paths';
export default defineConfig({
plugins: [tsconfigPaths()],
});-
Vite expose the environment variables to the browser by injecting the variables into the
import.meta.envobject. -
Built-in variables
import.meta.env.DEV: boolean,trueindev environmentandfalseinproduction environment. (When runviteorNODE_ENV=development vite)import.meta.env.PROD: boolean,trueinproduction environmentandfalseindev environment. (When runvite buildorNODE_ENV=production vite)import.meta.env.BASE_URL: string, the value ofbaseinvite.config.jsimport.meta.env.SSR: boolean,trueinserver side renderingandfalseinclient side rendering.import.meta.env.MODE: string, the value ofmodeinvite --mode <mode>orvite build --mode <mode>, related with.env.<mode>file.
-
When running
viteorvite build, the environment variables will be loaded from.envfile in root folder. -
The
.envfile will be loaded in all mode. -
The
.envfile can be a.env.localfile, which will be ignored by git. -
The
.env.localfile will be loaded in all mode. -
The
.env.localfile can be a.env.<mode>file, which will be ignored by git. The.env.<mode>file will be loaded in the corresponding mode. -
For example
vite --mode stagingwill load.env.staging.local>.env.staging>.env.local>.envfile. -modefor load the.envfile andNODE_ENVfor detect our is built or developing. More difference betweenmodeandNODE_ENVcan find here: https://vitejs.dev/guide/env-and-mode.html#node-env-and-modes. -
Only variables start with
VITE_will expose to the browser. For example,VITE_APP_TITLE=My Appwill exposeimport.meta.env.VITE_APP_TITLEto the browser.
- Vite provide a
vitefunction to create a dev server.
// dev-server.ts
import { createServer } from 'vite';
const server = await createServer({
root: __dirname,
server: {
port: 3000,
},
});- We can use
ts-nodeto run the script directly. But sinceviteusing ES module, we need to usets-node-esmto run the script.
ts-node-esm scripts/dev-server.ts- By default,
vitewill search thevite.config.jsfile in root folder. We can specify the config file by passing theconfigFileoption.
const server = await createServer({
root: __dirname,
configFile: path.resolve(__dirname, '../vite.config.ts'),
server: {
port: 3000,
},
});or set false to disable the config file.
const server = await createServer({
root: __dirname,
configFile: false,
server: {
port: 3000,
},
});- We can import the config file and pass the config object to
vitefunction. But if invite.config.ts,__dirnameis not available in es module, so we need to do some extra work to get the__dirnamein es module.
import { createServer } from 'vite';
import config from '../vite.config';
const server = await createServer({
...config,
server: {
port: 3000,
},
});// vite.config.ts
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);import.meta.urlgives you a URL string that represents the location of the current module. This is something likefile:///path/to/current/module.js.fileURLToPath(import.meta.url)converts this URL string to a file path string.path.dirname(__filename)gives you the directory name of the file path string. This is something like/path/to/current. Equivalent to__dirnamein CommonJS.