Add a Svelte Project
The code for this example is available on Github:
Example repository/nrwl/nx-recipes/tree/main/svelte
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
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
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
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:
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:
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
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:
1{
2 "type": "module"
3}
4
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.
The command below uses the as-provided
directory flag behavior, which is the default in Nx 16.8.0. If you're on an earlier version of Nx or using the derived
option, omit the --directory
flag. See the workspace layout documentation for more details.
❯
nx generate @nx/js:library --name=Counter --directory=libs/counter --unitTestRunner=vitest --bundler=vite --importPath=@acme/counter
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
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.