Manually set up your project to use Vite.js
Use our generator!It is recommended that you use the @nx/vite:configuration
generator to do convert an existing project to use Vite.
You can use the @nx/vite:dev-server
,@nx/vite:build
and @nx/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 @nx/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 @nx/vite
executors. However, if it's not supported by the @nx/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 @nx/vite:dev-server
and set it up with the following options:
//...
"my-app": {
"targets": {
//...
"serve": {
"executor": "@nx/vite:dev-server",
"defaultConfiguration": "development",
"options": {
"buildTarget": "my-app:build",
},
"configurations": {
...
}
},
}
}
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 @nx/vite:dev-server
documentation.
The build
target
In your project's project.json
file, change the executor of your build
target to use @nx/vite:build
and set it up with the following options:
//...
"my-app": {
"targets": {
//...
"build": {
"executor": "@nx/vite:build",
...
"options": {
"outputPath": "dist/apps/my-app"
},
"configurations": {
...
}
},
}
}
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.
DTS plugin
If you are building a library, you need to use the vite-plugin-dts
plugin to generate the .d.ts
files for your library.
Skip diagnostics
If you are building a library, you can set the skipDiagnostics
option to true
to speed up the build. This means that type diagnostic will be skipped during the build process. However, if there are some files with type errors which interrupt the build process, these files will not be emitted and .d.ts
declaration files will not be generated.
If you choose to skip diagnostics, here is what your 'vite-plugin-dts'
plugin setup will look like:
...
import dts from 'vite-plugin-dts';
import { join } from 'path';
...
...
export default defineConfig({
plugins: [
...,
dts({
entryRoot: 'src',
tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'),
skipDiagnostics: true,
}),
Do not skip diagnostics
If you are building a library, and you want to make sure that all the files are type checked, you can set the skipDiagnostics
option to false
to make sure that all the files are type checked. This means that type diagnostic will be run during the build process.
If you choose to enable diagnostics, here is what your 'vite-plugin-dts'
plugin setup will look like:
...
import dts from 'vite-plugin-dts';
...
...
export default defineConfig({
plugins: [
...,
dts({
root: '../../',
entryRoot: 'libs/my-lib/src',
tsConfigFilePath: 'libs/my-lib/tsconfig.lib.json',
include: ['libs/my-lib/src/**/*.ts'],
outputDir: 'dist/libs/my-lib',
skipDiagnostics: false,
}),
You can read more about the configuration options in the vite-plugin-dts
plugin documentation).
How your vite.config.ts
looks like
For applications
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.
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import ViteTsConfigPathsPlugin from 'vite-tsconfig-paths';
export default defineConfig({
plugins: [
react(),
ViteTsConfigPathsPlugin({
root: '../../',
}),
],
});
For libraries
If you are setting up a library (rather than an application) to use vite, your vite.config.ts
file should look like this:
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({
entryRoot: 'src',
tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'),
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'],
},
},
});
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:
...
<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
...
"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
...
"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