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

create-nx-workspace@latest acme --preset=ts-standalone --nx-cloud=true

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

touch index.html

And add the following content:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Acme</title> </head> <body> <div id="app"></div> <script type="module" src="./src/main.ts"></script> </body> </html>

Navigate to src/index.ts and change it to src/main.ts and add the following content:

import App from './App.svelte'; const app = new App({ target: document.getElementById('app'), }); export default app;

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

<script lang="ts"> let count: number = 0 const increment = () => { count += 1 } </script> <button on:click={increment}> count is {count} </button>

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:

// Add this to your imports import { svelte } from '@sveltejs/vite-plugin-svelte'; export default defineConfig({ plugins: [ //... svelte(), ], server: { port: 4200, host: 'localhost', }, });

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.lib.json to be tsconfig.app.json and add the following content:

{ "extends": "./tsconfig.json", "compilerOptions": { "moduleResolution": "node", "target": "esnext", "ignoreDeprecations": "5.0", "isolatedModules": true, "sourceMap": true, "types": ["svelte", "node", "vite/client"], "strict": false, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "checkJs": true }, "include": [ "src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte", "vite.config.mts" ], "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] }

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

"build": { "executor": "@nx/vite:build", "outputs": ["{options.outputPath}"], "defaultConfiguration": "production", "options": { "outputPath": "dist/acme" }, "configurations": { "development": { "mode": "development" }, "production": { "mode": "production" } } }, "serve": { "executor": "@nx/vite:dev-server", "defaultConfiguration": "development", "options": { "buildTarget": "acme:build" }, "configurations": { "development": { "buildTarget": "acme:build:development", "hmr": true }, "production": { "buildTarget": "acme:build:production", "hmr": false } } },
Nx 15 and lower use @nrwl/ instead of @nx/

This allows us to use nx build and nx serve to build and serve or Svelte application.

Test it out

Build the application

nx build acme

Your build artifacts should be in dist/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 counter/src/lib/Counter.svelte and copy the contents of your src/App.svelte file into it.

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

export { default as Counter } from './Counter.svelte';

The default is very import here as it allows us to import the component using import { Counter } from '@acme/counter' instead of import Counter from '@acme/counter'.

Update your root ./vite.config.mts to include the following:

export default defineConfig({ //... other config resolve: { alias: { '@acme/counter': fileURLToPath( new URL('./counter/src/index.ts', import.meta.url) ), }, }, });

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

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

<script lang="ts"> import { Counter } from '@acme/counter'; </script> <Counter />

Now we can build and serve our application again.

nx build acme

To generate the build artifact at dist/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.