7.3 KiB
Add a Vue Project
The code for this example is available on Github:
{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/vue" /%}
Supported Features
We'll be using an Nx plugin for Vue called @nx/vite. Although we are using @nx/vite, not all dependencies will be able to be automatically updated. So we'll have to update 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
create-nx-workspace@latest acme --preset=ts-standalone --nx-cloud=true
Add @nx/vite, vue, and other dependencies to your workspace
{% tabs %} {%tab label="npm"%}
npm install --save-dev @nx/vite @nx/js vue vue-tsc vitest vite-tsconfig-paths vite-plugin-dts vite @vitejs/plugin-vue @vitejs/plugin-vue-jsx
{% /tab %} {%tab label="yarn"%}
yarn add --dev @nx/vite @nx/js vue vue-tsc vitest vite-tsconfig-paths vite-plugin-dts vite @vitejs/plugin-vue @vitejs/plugin-vue-jsx
{% /tab %} {%tab label="pnpm"%}
pnpm add --dev @nx/vite @nx/js vue vue-tsc vitest vite-tsconfig-paths vite-plugin-dts vite @vitejs/plugin-vue @vitejs/plugin-vue-jsx
{% /tab %} {% /tabs %}
Create the application
touch index.html
And add the following content:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Acme</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="./favicon.ico" />
</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 { createApp } from 'vue';
import App from './App.vue';
createApp(App).mount('#app');
Create a new file src/App.vue with the following content:
<script setup lang="ts">
import { ref } from 'vue';
const count = ref(0);
function increment() {
count.value++;
}
</script>
<template>
<div>count is {{ count }}</div>
<button @click="increment">Increment</button>
</template>
Configure Nx to use build and serve your Vue application
Navigate to vite.config.ts and add the following content:
// Add this to your imports
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
export default defineConfig({
plugins: [
//.... other plugins
vue(),
vueJsx(),
],
});
Create a new file env.d.ts for example at the root of the project and add the following content:
/// <reference types="vite/client" />
/* eslint-disable */
declare module '*.vue' {
import type { DefineComponent } from 'vue';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const component: DefineComponent<object, object, any>;
export default component;
}
We need this file to ensure that Vue types are available to the compiler.
Update your tsconfig.lib.json to be tsconfig.app.json an add the following content:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "dist/out-tsc",
"types": ["node", "vite/client"],
"jsxImportSource": "vue"
},
"files": [],
"exclude": [
"src/**/*.spec.ts",
"src/**/*.test.ts",
"src/**/*.spec.tsx",
"src/**/*.test.tsx",
"src/**/*.spec.js",
"src/**/*.test.js",
"src/**/*.spec.jsx",
"src/**/*.test.jsx"
],
"include": [
"src/**/*.ts",
"src/**/*.d.ts",
"src/**/*.tsx",
"**/*.vue",
"vite.config.ts",
"env.d.ts"
]
}
We include vite.config.ts and env.d.ts to ensure that the types are available to the compiler.
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
}
}
},
This allows us to use nx build and nx serve to build and serve our Vue application.
Test it out
Build
nx build acme
Serve
nx serve acme
Create a library
Instead of having our Counter directly defined in the app we can instead create a library that exports the Counter component.
Create a new library nx generate @nx/js:library --name=Counter --unitTestRunner=vitest --bundler=vite --importPath=@acme/counter
Create your Counter component at counter/src/lib/Counter.vue and copy the contents of your src/App.vue into it.
Update your libs/counter/src/lib/index.ts to export your Counter component.
export { default as Counter } from './Counter.vue';
{% 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 %}
Update your root ./vite.config.ts 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.vue to use the Counter component.
<script setup lang="ts">
import { Counter } from '@acme/counter';
</script>
<template>
<Counter />
</template>
Test it out
Build
nx build acme
Serve
nx serve acme
More Documentation
A larger example including libraries, tests, and more is available at Nx Vue Example on Github.