Manually set up your project to use Vite.js

Use our generator!

It is recommended that you use the @nrwl/vite:configuration generator to do convert an existing project to use Vite.

You can use the @nrwl/vite:dev-server,@nrwl/vite:build and @nrwl/vite:test executors to serve, build and test your project using Vite and Vitest. To do this, you need to make a few adjustments to your project. It is recommended that you use the @nrwl/vite:configuration generator to do this, but you can also do it manually.

A reason you may need to do this manually, is if our generator does not support conversion for your project, or if you want to experiment with custom options.

The list of steps below assumes that your project can be converted to use the @nrwl/vite executors. However, if it's not supported by the @nrwl/vite:configuration generator, it's likely that your project will not work as expected when converted. So, proceed with caution and always commit your code before making any changes.

1. Change the executors in your project.json

The serve target

This applies to applications, not libraries.

In your app's project.json file, change the executor of your serve target to use @nrwl/vite:dev-server and set it up with the following options:

//... "my-app": { "targets": { //... "serve": { "executor": "@nrwl/vite:dev-server", "defaultConfiguration": "development", "options": { "buildTarget": "my-app:build", }, "configurations": { ... } }, } }
Other options

Any extra options that you may need to add to your server's configuration can be added in your project's vite.config.ts file. You can find all the options that are supported in the Vite.js documentation. You can see which of these options you can add in your project.json in the @nrwl/vite:dev-server documentation.

The build target

In your project's project.json file, change the executor of your build target to use @nrwl/vite:build and set it up with the following options:

//... "my-app": { "targets": { //... "build": { "executor": "@nrwl/vite:build", ... "options": { "outputPath": "dist/apps/my-app" }, "configurations": { ... } }, } }
Other options

You can specify more options in the vite.config.ts file (see Step 2 below).

2. Configure Vite.js

TypeScript paths

You need to use the vite-tsconfig-paths plugin to make sure that your TypeScript paths are resolved correctly in your monorepo.

React plugin

If you are using React, you need to use the @vitejs/plugin-react plugin.

How your vite.config.ts looks like

Add a vite.config.ts file to the root of your project. If you are not using React, you can skip adding the react plugin, of course.

apps/my-app/vite.config.ts
import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import ViteTsConfigPathsPlugin from 'vite-tsconfig-paths'; export default defineConfig({ plugins: [ react(), ViteTsConfigPathsPlugin({ root: '../../', }), ], });

If you are converting a library (rather than an application) to use vite, your vite.config.ts file should look like this:

libs/my-lib/vite.config.ts
import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import viteTsConfigPaths from 'vite-tsconfig-paths'; import dts from 'vite-plugin-dts'; import { join } from 'path'; export default defineConfig({ plugins: [ dts({ tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'), // Faster builds by skipping tests. Set this to false to enable type checking. skipDiagnostics: true, }), react(), viteTsConfigPaths({ root: '../../../', }), ], // Configuration for building your library. // See: https://vitejs.dev/guide/build.html#library-mode build: { lib: { // Could also be a dictionary or array of multiple entry points. entry: 'src/index.ts', name: 'pure-libs-rlv1', fileName: 'index', // Change this to the formats you want to support. // Don't forgot to update your package.json as well. formats: ['es', 'cjs'], }, rollupOptions: { // External packages that should not be bundled into your library. external: ['react', 'react-dom', 'react/jsx-runtime'], }, }, });
The `root` path

Make sure the root path in the ViteTsConfigPathsPlugin options is correct. It should be the path to the root of your workspace.

In that config file, you can configure Vite.js as you would normally do. For more information, see the Vite.js documentation.

3. Move index.html and point it to your app's entrypoint

This applies to applications, not libraries.

First of all, move your index.html file to the root of your app (e.g. from apps/my-app/src/index.html to apps/my-app/index.html).

Then, add a module script tag pointing to the main.tsx (or main.ts) file of your app:

apps/my-app/index.html
... <body> <div id="root"></div> <script type="module" src="src/main.tsx"></script> </body> </html>

4. Add a public folder

You can add a public folder to the root of your project. You can read more about the public folder in the Vite.js documentation.

myorg/ ├── apps/ │ ├── my-app/ │ │ ├── src/ │ │ │ ├── app/ │ │ │ ├── assets/ │ │ │ ├── ... │ │ │ └── main.tsx │ │ ├── index.html │ │ ├── public/ | . | . | ├── favicon.ico │ │ │ └── my-page.md │ │ ├── project.json │ │ ├── ... │ │ ├── tsconfig.app.json │ │ ├── tsconfig.json │ │ └── tsconfig.spec.json

You can use the public folder to store static assets, such as images, fonts, and so on. You can also use it to store Markdown files, which you can then import in your app and use as a source of content.

5. Adjust your project's tsconfig.json

Change your app's tsconfig.json (e.g. apps/my-app/tsconfig.json) compilerOptions to the following:

For React apps

apps/my-app/tsconfig.json
... "compilerOptions": { "jsx": "react-jsx", "allowJs": false, "esModuleInterop": false, "allowSyntheticDefaultImports": true, "forceConsistentCasingInFileNames": true, "isolatedModules": true, "lib": ["DOM", "DOM.Iterable", "ESNext"], "module": "ESNext", "moduleResolution": "Node", "noEmit": true, "resolveJsonModule": true, "skipLibCheck": true, "strict": true, "target": "ESNext", "types": ["vite/client"], "useDefineForClassFields": true }, ...

For Web apps

apps/my-app/tsconfig.json
... "compilerOptions": { "target": "ESNext", "useDefineForClassFields": true, "module": "ESNext", "lib": ["ESNext", "DOM"], "moduleResolution": "Node", "strict": true, "resolveJsonModule": true, "isolatedModules": true, "esModuleInterop": true, "noEmit": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "skipLibCheck": true, "types": ["vite/client"] }, "include": ["src"], ...

You can read more about the TypeScript compiler options in the Vite.js documentation.

6. Use Vite.js

Now you can finally serve and build your app using Vite.js:

Serve the app

nx serve my-app

or

nx run my-app:serve

Now, visit http://localhost:4200 to see your app running!

Build the app

nx build my-app

or

nx run my-app:build