Sharing components between multiple Nuxt projects
22nd Oct 2022 • 5 min read — by Aleksandar Trpkovski
Nuxt 3 and its new foundation come with many powerful new features, such as the new server engine Nitro that made the framework lighter and faster and supported by Vue's 3 Composition API and Vite.
But one of Nuxt's features that not many people talk about is the ability to merge two or more applications and share functionalities between them. The extends feature in Nuxt 3 allows us to set a relative config path or remote git repositories such as GitHub, GitLab, Bitbucket or https:// pointing to the source directories of a project.
This feature is a perfect use case for complex projects such us developing applications with a few different pieces, for example, an Admin and a User area that are designed separately but share the same components.
Let's see how this works with an example.
Setting up a base Nuxt 3 project
Create a new Nuxt project:
npx nuxi init nuxt-base
Navigate to the nuxt-base
directory and install the dependencies:
cd nuxt-base
npm install
We will come back to this project a bit later. Next, let's create the other Nuxt project nuxt-components
.
Setting up a second Nuxt 3 project
Let's repeat what we've done previously with the new project.
npx nuxi init nuxt-components
cd nuxt-components
npm install
We should create both projects in the same folder:
/root
/nuxt-base
app.vue
nuxt.config.ts
package.json
...
/nuxt-components
app.vue
nuxt.config.ts
package.json
...
We will create a directory called components in the root of the nuxt-components
project. Inside we will add two .vue
files:
random-message.vue
containing the following code:
<template>
<div>
<h1>{{ msg }}</h1>
<button @click="changeMsg">Generate a Message</button>
</div>
</template>
<script setup>
import { ref } from "vue";
const msg = ref("");
const changeMsg = () => {
msg.value = makeid(getRandomInt(100));
};
function makeid(length) {
var result = "";
var characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var charactersLength = characters.length;
for (var i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
</script>
And random-word.vue
containing the following code:
<template>
<div>
<h1>{{ word }}</h1>
<button @click="generateRandomWord">Generate a Word</button>
</div>
</template>
<script setup>
import { ref } from "vue";
import randomWords from "random-words";
const word = ref("");
function generateRandomWord() {
word.value = randomWords();
}
</script>
We also need to install the random-word
npm package so let's do it:
npm install random-words
The idea with these two components we just created above is to use them in our nuxt-base
project.
Before we move to the next-base
project again, let's add configuration in the nuxt.config.ts
file:
export default defineNuxtConfig({
components: [{ path: "./components", prefix: "UI" }],
});
We added a prefix UI
to all components in the /components
directory. We can use these two components like this:
<UIRandomMessage />
<UIRandomWord />
Adding random-message.vue
and random-word.vue
to the nuxt-base
project
In the app.vue
file inside the nuxt-base
project, we will use random-message.vue
and random-word.vue
components.
Our app.vue
file should look like the following:
<template>
<div>
<UIRandomMessage />
<UIRandomWord />
</div>
</template>
Next, we need to tell Nuxt that we want to extend our nuxt-base
project with nuxt-components
. We can do so by adding the following in the nuxt.config.ts
file:
export default defineNuxtConfig({
components: true,
extends: ["../nuxt-components"],
});
And that's it. We can run our application and see two components in action:
npm run dev
Generate static site
Our application works as expected, running locally on our dev server. However, there is one problem if we try to generate statically. If we run npm run generate
, we will get the following error:
ERROR [vite]: Rollup failed to resolve import "vue/server-renderer" from "../nuxt-components/components/random-message.vue".
This is most likely unintended because it can break your application at runtime.
If you do want to externalize this module explicitly add it to
`build.rollupOptions.external`
To fix this issue, we need to create a vite.config.ts
file in the root of our nuxt-base
project and add the following code:
import { defineConfig } from "vite";
export default defineConfig({
build: {
rollupOptions: {
external: ["vue/server-renderer"],
},
},
});
That's it. Now we can generate our nuxt-base
app without any problems.
All examples above can be found in the following Github repositories: nuxt-base
, nuxt-components
.
Conclusion
- One of Nuxt's features that not many people talk about is the ability to merge two or more applications and share functionalities between them. A perfect use case will be designing an Admin and a User area that are developed separately but share the same components.
- We can merge multiple projects by using the extends feature in Nuxt 3.
- The extends feature allows us to set a relative config path or remote git repositories such as GitHub, GitLab, Bitbucket or https:// pointing to the source directories of a project.
- To use another project inside our Nuxt app, we need to include the project’s path in the
nuxt.config.ts
file. - To generate our project statically, we need to add
"vue/server-renderer"
to ourvite.config.ts
file.