From 2180268d9dba32bdb4f3f35f1f5226f61ce87cab Mon Sep 17 00:00:00 2001 From: Nicholas Cunningham Date: Thu, 17 Aug 2023 03:30:10 -0600 Subject: [PATCH] docs(core): Add svelte docs recipe (#18590) --- docs/generated/manifests/menus.json | 24 ++ docs/generated/manifests/nx.json | 30 ++ docs/map.json | 6 + docs/shared/recipes/add-stack/add-svelte.md | 316 ++++++++++++++++++++ docs/shared/recipes/add-stack/add-vue.md | 12 +- docs/shared/reference/sitemap.md | 1 + 6 files changed, 383 insertions(+), 6 deletions(-) create mode 100644 docs/shared/recipes/add-stack/add-svelte.md diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index 9d3e95d28cca1..92001d0a19108 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -3679,6 +3679,14 @@ "children": [], "disableCollapsible": false }, + { + "name": "Add a Svelte Project", + "path": "/showcase/example-repos/add-svelte", + "id": "add-svelte", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Powering Up React Development With Nx", "path": "/showcase/example-repos/react-nx", @@ -3844,6 +3852,14 @@ "children": [], "disableCollapsible": false }, + { + "name": "Add a Svelte Project", + "path": "/showcase/example-repos/add-svelte", + "id": "add-svelte", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Powering Up React Development With Nx", "path": "/showcase/example-repos/react-nx", @@ -3967,6 +3983,14 @@ "children": [], "disableCollapsible": false }, + { + "name": "Add a Svelte Project", + "path": "/showcase/example-repos/add-svelte", + "id": "add-svelte", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Powering Up React Development With Nx", "path": "/showcase/example-repos/react-nx", diff --git a/docs/generated/manifests/nx.json b/docs/generated/manifests/nx.json index 44336dfc75155..216b558e22905 100644 --- a/docs/generated/manifests/nx.json +++ b/docs/generated/manifests/nx.json @@ -4587,6 +4587,16 @@ "path": "/showcase/example-repos/add-vue", "tags": [] }, + { + "id": "add-svelte", + "name": "Add a Svelte Project", + "description": "Add a Svelte project to your repo", + "file": "shared/recipes/add-stack/add-svelte", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/add-svelte", + "tags": [] + }, { "id": "react-nx", "name": "Powering Up React Development With Nx", @@ -4794,6 +4804,16 @@ "path": "/showcase/example-repos/add-vue", "tags": [] }, + { + "id": "add-svelte", + "name": "Add a Svelte Project", + "description": "Add a Svelte project to your repo", + "file": "shared/recipes/add-stack/add-svelte", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/add-svelte", + "tags": [] + }, { "id": "react-nx", "name": "Powering Up React Development With Nx", @@ -4949,6 +4969,16 @@ "path": "/showcase/example-repos/add-vue", "tags": [] }, + "/showcase/example-repos/add-svelte": { + "id": "add-svelte", + "name": "Add a Svelte Project", + "description": "Add a Svelte project to your repo", + "file": "shared/recipes/add-stack/add-svelte", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/add-svelte", + "tags": [] + }, "/showcase/example-repos/react-nx": { "id": "react-nx", "name": "Powering Up React Development With Nx", diff --git a/docs/map.json b/docs/map.json index 7b6db817213a5..de94302ea9107 100644 --- a/docs/map.json +++ b/docs/map.json @@ -1075,6 +1075,12 @@ "description": "Add a Vue project to your repo", "file": "shared/recipes/add-stack/add-vue" }, + { + "name": "Add a Svelte Project", + "id": "add-svelte", + "description": "Add a Svelte project to your repo", + "file": "shared/recipes/add-stack/add-svelte" + }, { "name": "Powering Up React Development With Nx", "id": "react-nx", diff --git a/docs/shared/recipes/add-stack/add-svelte.md b/docs/shared/recipes/add-stack/add-svelte.md new file mode 100644 index 0000000000000..7281f0c20e9be --- /dev/null +++ b/docs/shared/recipes/add-stack/add-svelte.md @@ -0,0 +1,316 @@ +# Add a Svelte Project + +The code for this example is available on Github: + +{% github-repository url="https://github.com/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. + +{% pill url="/core-features/run-tasks" %}✅ Run Tasks{% /pill %} +{% pill url="/core-features/cache-task-results" %}✅ Cache Task Results{% /pill %} +{% pill url="/core-features/remote-cache" %}✅ Share Your Cache{% /pill %} +{% pill url="/core-features/explore-graph" %}✅ Explore the Graph{% /pill %} +{% pill url="/core-features/distribute-task-execution" %}✅ Distribute Task Execution{% /pill %} +{% pill url="/core-features/integrate-with-editors" %}✅ Integrate with Editors{% /pill %} +{% pill url="/core-features/automate-updating-dependencies" %}✅ Automate Updating Nx{% /pill %} +{% pill url="/core-features/enforce-module-boundaries" %}✅ Enforce Module Boundaries{% /pill %} +{% pill url="/core-features/plugin-features/use-task-executors" %}🚫 Use Task Executors{% /pill %} +{% pill url="/core-features/plugin-features/use-code-generators" %}🚫 Use Code Generators{% /pill %} +{% pill url="/core-features/automate-updating-dependencies" %}🚫 Automate Updating Framework Dependencies{% /pill %} + +## Setup workspace + +**Create a new Nx workspace** + +```shell +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** + +{% tabs %} +{%tab label="npm"%} + +```shell +npm install --save-dev @nx/vite @nx/js vitest vite svelte svelte-check @sveltejs/vite-plugin-svelte +``` + +{% /tab %} +{%tab label="yarn"%} + +```shell +yarn add --dev @nx/vite @nx/js vitest vite svelte svelte-check @sveltejs/vite-plugin-svelte +``` + +{% /tab %} + +{%tab label="pnpm"%} + +```shell +pnpm add --save-dev @nx/vite @nx/js vitest vite svelte svelte-check @sveltejs/vite-plugin-svelte +``` + +{% /tab %} +{% /tabs %} + +## Create the application + +Before we start to create our application, let's remove the React application that was created for us. + +```shell +rm -rf apps/acme/src/app/* +``` + +Update your `apps/acme/src/index.html` to the following: + +```html + + + + + + Acme + + +
+ + + +``` + +Navigate to `apps/acme/src/main.tsx` and change it to `apps/acme/src/main.ts` and add the following content: + +```ts +import App from './app/App.svelte'; + +const app = new App({ + target: document.getElementById('app'), +}); + +export default app; +``` + +Create a new file `apps/acme/src/app/App.svelte` and add the following content: + +```ts + + + + +``` + +## 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: + +```ts +// Add this to your imports +import { svelte } from '@sveltejs/vite-plugin-svelte'; + +export default defineConfig({ + plugins: [ + //... + svelte(), + ], + + server: { + port: 4200, + host: 'localhost', + }, +}); +``` + +{%callout type="Note" title="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](https://vitejs.dev/guide/troubleshooting.html#this-package-is-esm-only) +{% /callout %} + +Update your `tsconfig.app.json` with the following content: + +```json {% fileName="/apps/acme/tsconfig.app.json" %} +{ + "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: + +```json {% fileName="/apps/acme/project.json" %} +{ + "targets": { + "build": { + "executor": "@nx/vite:build", + "outputs": ["{options.outputPath}"], + "defaultConfiguration": "production", + "options": { + "outputPath": "dist/apps/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 + } + } + } + } +} +``` + +We also need to add a `svelte.config.js` file to the project root with the following content: + +```js +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; + +export default { + // Consult https://svelte.dev/docs#compile-time-svelte-preprocess + // for more information about preprocessors + preprocess: vitePreprocess(), +}; +``` + +Update your `package.json` to include: + +```json {% fileName="/package.json" %} +{ + "type": "module" +} +``` + +{% callout "Note" title="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](https://vitejs.dev/guide/troubleshooting.html#this-package-is-esm-only) +{% /callout %} + +Test it out + +**Build the application** + +```shell +nx build acme +``` + +Your build artifacts should be in `dist/apps/acme` + +**Serve the application** + +```shell +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. + +```shell +nx generate @nx/js:library --name=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. + +```ts +export { default as Counter } from './Counter.svelte'; +``` + +{% callout "Note" title="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'`. +{% /callout %} + +Update your project's `/apps/acme/vite.config.mts` to include the following: + +```ts +export default defineConfig({ + //... other config + resolve: { + alias: { + '@acme/counter': fileURLToPath( + new URL('/libs/counter/src/index.ts', import.meta.url) + ), + }, + }, +}); +``` + +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. + +```ts + + + +``` + +Now we can build and serve our application again. + +```shell +nx build acme +``` + +To generate the build artifact at `dist/apps/acme`. + +```shell +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](https://github.com/nrwl/nx-recipes/tree/main/svelte) on Github. + +- [Nx Vite Plugin](https://nx.dev/packages/vite) +- [Vite](https://vitejs.dev/) +- [Svelte](https://svelte.dev/) diff --git a/docs/shared/recipes/add-stack/add-vue.md b/docs/shared/recipes/add-stack/add-vue.md index c340cf5ce1c68..e7ed39826cd41 100644 --- a/docs/shared/recipes/add-stack/add-vue.md +++ b/docs/shared/recipes/add-stack/add-vue.md @@ -181,7 +181,7 @@ Navigate to `project.json` and update it with the following content: "outputs": ["{options.outputPath}"], "defaultConfiguration": "production", "options": { - "outputPath": "dist/test-vue" + "outputPath": "dist/acme" }, "configurations": { "development": { @@ -196,15 +196,15 @@ Navigate to `project.json` and update it with the following content: "executor": "@nx/vite:dev-server", "defaultConfiguration": "development", "options": { - "buildTarget": "test-vue:build" + "buildTarget": "acme:build" }, "configurations": { "development": { - "buildTarget": "test-vue:build:development", + "buildTarget": "acme:build:development", "hmr": true }, "production": { - "buildTarget": "test-vue:build:production", + "buildTarget": "acme:build:production", "hmr": false } } @@ -241,7 +241,7 @@ Update your `libs/counter/src/lib/index.ts` to export your Counter component. export { default as Counter } from './Counter.vue'; ``` -{% callout "Note" %} +{% callout type="Note" %} 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'`. {% /callout %} @@ -291,6 +291,6 @@ nx serve acme A larger example including libraries, tests, and more is available at [Nx Vue Example](https://github.com/nrwl/nx-recipes/tree/main/vue) on Github. -- [Nx Vite Plugin](https://nx.dev/latest/vue/vite/overview) +- [Nx Vite Plugin](https://nx.dev/packages/vite) - [Vite](https://vitejs.dev/) - [Vue](https://v3.vuejs.org/) diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index 177e2cd086804..9d489f288866c 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -184,6 +184,7 @@ - [Add a Nuxt Project](/showcase/example-repos/add-nuxt) - [Add an Astro Project](/showcase/example-repos/add-astro) - [Add a Vue Project](/showcase/example-repos/add-vue) + - [Add a Svelte Project](/showcase/example-repos/add-svelte) - [Powering Up React Development With Nx](/showcase/example-repos/react-nx) - [Using Apollo GraphQL](/showcase/example-repos/apollo-react) - [Using Prisma with NestJS](/showcase/example-repos/nestjs-prisma)