Add a Svelte Project

The code for this example is available on Github:

Supported Features

Because we are not using a Nx plugin for Svelte, there are a few items we'll have to configure manually. We'll have to configure our own build system. There are no pre-created Svelte-specific code generators. And we'll have to take care of updating any framework dependencies as needed.

✅ Run Tasks ✅ Cache Task Results ✅ Share Your Cache ✅ Explore the Graph ✅ Distribute Task Execution ✅ Integrate with Editors ✅ Automate Updating Nx ✅ Enforce Module Boundaries 🚫 Use Task Executors 🚫 Use Code Generators 🚫 Automate Updating Framework Dependencies

Setup workspace

Create a new Nx workspace

npx create-nx-workspace@latest workspace --preset=react-monorepo --style=css --bundler=vite --nx-cloud=true --appName=acme

Add @nx/vite, svelte, and other dependencies to your workspace

npm install --save-dev @nx/vite @nx/js vitest vite svelte svelte-check @sveltejs/vite-plugin-svelte

Nx 15 and lower use @nrwl/ instead of @nx/

Create the application

Before we start to create our application, let's remove the React application that was created for us.

rm -rf apps/acme/src/app/*

Update your apps/acme/src/index.html to the following:

1<!DOCTYPE html> 2<html lang="en"> 3 <head> 4 <meta charset="UTF-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 <title>Acme</title> 7 </head> 8 <body> 9 <div id="app"></div> 10 <script type="module" src="./src/main.ts"></script> 11 </body> 12</html> 13

Navigate to apps/acme/src/main.tsx and change it to apps/acme/src/main.ts and add the following content:

1import App from './app/App.svelte'; 2 3const app = new App({ 4 target: document.getElementById('app'), 5}); 6 7export default app; 8

Create a new file apps/acme/src/app/App.svelte and add the following content:

1<script lang="ts"> 2 let count: number = 0 3 const increment = () => { 4 count += 1 5 } 6 </script> 7 8 <button on:click={increment}> 9 count is {count} 10 </button> 11 12

Configure Nx to build and serve the application

Navigate to vite.config.ts update the file name to vite.config.mts and add the following content:

1// Add this to your imports 2import { svelte } from '@sveltejs/vite-plugin-svelte'; 3 4export default defineConfig({ 5 plugins: [ 6 //... 7 svelte(), 8 ], 9 10 server: { 11 port: 4200, 12 host: 'localhost', 13 }, 14}); 15
Why use the .mts file extension?

We change vite.config.ts to vite.config.mts because '@sveltejs/vite-plugin-svelte' is an ESM only package. As a result, we need to use the .mts extension to tell Nx to use the ESM loader. See more here: ESM Package

Update your tsconfig.app.json with the following content:

/apps/acme/tsconfig.app.json
1{ 2 "extends": "./tsconfig.json", 3 "compilerOptions": { 4 "moduleResolution": "node", 5 "target": "esnext", 6 "ignoreDeprecations": "5.0", 7 "isolatedModules": true, 8 "sourceMap": true, 9 "types": ["svelte", "node", "vite/client"], 10 "strict": false, 11 "esModuleInterop": true, 12 "skipLibCheck": true, 13 "forceConsistentCasingInFileNames": true, 14 "checkJs": true 15 }, 16 "include": [ 17 "src/**/*.d.ts", 18 "src/**/*.ts", 19 "src/**/*.js", 20 "src/**/*.svelte", 21 "vite.config.mts" 22 ], 23 "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] 24} 25

Navigate to project.json and update it with the following content:

/apps/acme/project.json
1{ 2 "targets": { 3 "build": { 4 "executor": "@nx/vite:build", 5 "outputs": ["{options.outputPath}"], 6 "defaultConfiguration": "production", 7 "options": { 8 "outputPath": "dist/apps/acme" 9 }, 10 "configurations": { 11 "development": { 12 "mode": "development" 13 }, 14 "production": { 15 "mode": "production" 16 } 17 } 18 }, 19 "serve": { 20 "executor": "@nx/vite:dev-server", 21 "defaultConfiguration": "development", 22 "options": { 23 "buildTarget": "acme:build" 24 }, 25 "configurations": { 26 "development": { 27 "buildTarget": "acme:build:development", 28 "hmr": true 29 }, 30 "production": { 31 "buildTarget": "acme:build:production", 32 "hmr": false 33 } 34 } 35 } 36 } 37} 38
Nx 15 and lower use @nrwl/ instead of @nx/

We also need to add a svelte.config.js file to the project root with the following content:

1import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; 2 3export default { 4 // Consult https://svelte.dev/docs#compile-time-svelte-preprocess 5 // for more information about preprocessors 6 preprocess: vitePreprocess(), 7}; 8

Update your package.json to include:

/package.json
1{ 2 "type": "module" 3} 4
Why use the type: module?

We need to add "type": "module" to our package.json file because we are using ESM only packages. See more here: ESM Package

Test it out

Build the application

nx build acme

Your build artifacts should be in dist/apps/acme

Serve the application

nx serve acme

Navigate to http://localhost:4200 and you should see your application.

Create a library

Instead of having our Counter directly defined in App.svelte file, let's create a library that we can import into our application.

nx generate @nx/js:library --name=Counter --unitTestRunner=vitest --bundler=vite --importPath=@acme/counter

Nx 15 and lower use @nrwl/ instead of @nx/

Create the Counter component at libs/counter/src/lib/Counter.svelte and copy the contents of your apps/acme/src/App.svelte file into it.

Update your libs/counter/src/lib/index.ts to export your Counter component.

1export { default as Counter } from './Counter.svelte'; 2
Remember the default keyword

The default is import here as due to the aliasing we'll be doing later, we'll need to import the Counter component as import { Counter } from '@acme/counter'.

Update your project's /apps/acme/vite.config.mts to include the following:

1export default defineConfig({ 2 //... other config 3 resolve: { 4 alias: { 5 '@acme/counter': fileURLToPath( 6 new URL('/libs/counter/src/index.ts', import.meta.url) 7 ), 8 }, 9 }, 10}); 11

This allows the runtime to resolve the @acme/counter import to the correct location.

Finally update your apps/acme/src/App.svelte to use the counter component.

1<script lang="ts"> 2 import { Counter } from '@acme/counter'; 3</script> 4 5<Counter /> 6

Now we can build and serve our application again.

nx build acme

To generate the build artifact at dist/apps/acme.

nx serve acme

To serve the application at http://localhost:4200.

More Documentation

A larger example including libraries, test and more is available at Nx Svelte Example on Github.