Efficient management of pre-built assets in Vite

I am currently developing a Vue application using Vite. Within the content folder, I have numerous files (ranging from 10 to 100) located as follows:

content/block/paragraph.json
content/block/theorem.json
content/inliner/link.json
...

My goal is to create navigation data for my app and utilize this data within the app to generate a sidebar <nav>. In order to accomplish this, I need to extract specific data (the title property) from each individual json file.

Here's an example of the calculated nav structure that I aim to integrate into my app:

const nav = {
    "block/paragraph": "Paragraph", // Retrieved from 'content/block/paragraph.json'
    "block/theorem": "Theorem", // Extracted from 'content/block/theorem.json'
    // ...
}

The challenge lies in the fact that performing these operations within the Vue app itself is not ideal, as it may introduce delays and result in unnecessary network traffic due to loading all json files.

Is there a way to construct the nav object (or function) prior to initiating the Vue app, and then utilize the pre-generated data within the app?

In this scenario, three potential solutions come to mind, yet I'm uncertain which approach is optimal:

  1. Implement a separate script for generating the navigation data (although this method lacks the convenience of utilizing Vite features like advanced imports and necessitates running the script independently before npm run dev, while also creating a .temp folder for storing the nav data)
  2. Virtual Module. While promising, this solution entails converting the module into a string to function properly, a process I struggle to grasp completely...
  3. Consider some form of Vite plugin other than Virtual Module?

What represents the optimal strategy for resolving this predicament?

On a broader note, is there a convenient methodology for preparing data and conducting computations prior to launching the application, followed by employing said data within the app?

Answer №1

Utilize the power of import.meta.glob:

Discover more about glob import here!

In this code snippet, we are selectively importing only the title property from JSON files, optimizing performance:

const files = import.meta.glob('./content/**/*.json', { eager: true, import: 'title' });
export default Object.keys(files).reduce((result, key) => (result[key.slice(2, -5)] = files[key], result), {});

Answer №2

Resolved the issue by implementing Virtual Module:

// vite/nav.ts

/**
 * Reading files and more:
 *
 * const files = globSync(...);
 * fs.readFileSync(...);
 * ...
 */

class NavDataResult { /* ... */ }
const navData = /* ... */;
function fetchNavData(query: string) { /* ... */ }

//
// Vite Plugin
//

export default function navigation(): Plugin
{
    const moduleId = 'virtual:nav';
    const resolvedModuleId = '\0' + moduleId;

    return {
        name: 'generated-navigation',
        resolveId(id)
        {
            if (id === moduleId)
                return resolvedModuleId;
        },
        load(id)
        {
            if (id === resolvedModuleId)
            {
                return `
                    const NavDataResult = ${NavDataResult.toString()}
                    const navData = ${JSON.stringify(navData)}
                    export default ${fetchNavData.toString()}`;
            }
        }
    }
}

Next, in our vite.config.ts file we include the virtual module:

// vite.config.ts

import navigation from './vite/nav';

export default defineConfig({ /* ... */ plugins: [navigation()] });

We also add type definitions to vite-env.d.ts to prevent VS Code errors when importing from unknown virtual:nav:

// vite-env.d.ts

/// <reference types="vite/client" />

declare module 'virtual:nav' {
    type funcReturn = import('../vite/nav').NavDataResult;
    const result: (query: string) => funcReturn;
    export default result;
}

With these changes, the virtual module can now be utilized within our application. Great success!

<script setup lang="ts">
// Navigation.vue

import fetchNavData from 'virtual:nav';

console.log(fetchNavData('paragraph'));
</script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

In Stripe.js, the background color and height of the credit card input cannot be customized

I'm struggling with customizing the appearance of a Stripe credit card input within my Vue.js application. I want to adjust the background color to #f1f1f1 and set the height to 60px, but despite trying both base styles and css, I can't seem to g ...

Error encountered in React component: TypeScript TS2339 states that the property 'xyz' is not found on type 'IntrinsicAttributes...'

I am attempting to develop a straightforward React component that can accept any properties. The syntax below using any is causing issues (unexpected token just before <): export class ValidatedInput extends React.Component<any, any> {...} The p ...

Challenges arise when trying to access environment variables using react-native-dotenv in React

I am currently working on two separate projects, one being an app and the other a webapp. The app project is already set up with react-native-dotenv and is functioning as expected. However, when I attempt to use the same code for the webapp, I encounter an ...

The POST requests on Next JS Mock API endpoints include parameters passed in the req.body

I am currently running Next JS API tests using jest with a custom testClient. The code for the testClient is as follows: import { createServer } from 'http'; import type { NextApiHandler } from 'next'; import type { __ApiPreviewProps } ...

Loading Vue.js components with themes without using Vue.use

I am currently utilizing the Cool-Select package, which necessitates the following code to load its theme: import VueSelect from 'vue-cool-select' Vue.use(VueSelect, { theme:'material-design' }) The issue at hand is that I prefer no ...

Adjust the width of a div based on a dynamic value in VUE 3

I need assistance with setting the width of my div based on a computed value. Scenario: I have products that retrieve information from an API, and the length value varies depending on the selected product. Therefore, this component needs to be dynamic. T ...

Sharing OAuth token between Vue.js components

Once the OAuth login is successful, I retrieve the OAuth token in the SuccessOAuth.vue component. The token details are obtained as shown below: checkforTokens(){ const queryString = this.$route.query; console.log(query ...

Vue js is throwing an error message that says "Reading 'push' property of undefined is not possible"

I've encountered an issue while trying to navigate to other routes. The error I'm receiving is: Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'push') at eval (JoinRoom.vue?bd9d:74:1) This is how I pu ...

Why does it fire off numerous requests even though I only called it once?

Everything seemed to be working fine with my project. However, I noticed in the console network that one of my GET requests is being sent twice even though I only triggered it once. View network console here If I comment out the entire created function co ...

Guide to integrating Inversify with Mocha

In my TypeScript Node.js application, I am implementing Dependency Injection using Inversify. The functionality works perfectly during the app's execution. However, I encountered an issue with the @injectable() annotation when running tests. An error ...

The subscribe method in Angular TS may be marked as deprecated, but worry not as it is still

I have developed a function that retrieves new data from a service file each time it is called. Here is how the function looks: onCarChange() { this.carService.getCarData(this.selectedCar).subscribe( async (response: CarData) => { if (response?.d ...

The attribute 'y' is not found within the data type 'number'

Currently working on a project using Vue.js, Quasar, and TypeScript. However, encountering errors that state the following: Property 'y' does not exist on type 'number | { x: number[]; y: number[]; }'. Property 'y' does not ...

Switching Visibility of Map Layers through an External Component

Let me start by mentioning that I am a design student utilizing Vue.js for prototyping my senior project. This is merely a prototype of a diary app and not an actual working project. The issue at hand involves a map component created with Vue2Leaflet, whi ...

Installing the Quasar UI framework into an existing Vue JS project can be done with just a few

I am currently working on a Vue JS project and I am looking to incorporate some components, such as range sliders. However, I am struggling to understand how to integrate these components into my existing project. I have tried following tutorials for insta ...

Navigate to the parent element in the DOM

Looking to add some unique styling to just one of the many Mat dialog components in my project. It seems like modifying the parent element based on the child is trickier than expected, with attempts to access the DOM through the <mat-dialog-container> ...

Unable to execute OAuth2 with Okta using angular-oauth2-oidc framework

Looking to create an authentication module for an Angular application using Okta as the identity provider and implementing the angular-oauth2-oidc flow. Following a guide here: . However, encountering errors when running the web app. How can I troubleshoot ...

Receiving NULL data from client side to server side in Angular 2 + Spring application

I'm currently working on a project that involves using Angular 2 on the client side and Spring on the server side. I need to send user input data from the client to the server and receive a response back. However, I'm encountering an issue where ...

Trouble with Vue select not linking to the model

I am working with a basic select element in VueJS: <select v-model="country" class="dropdown-input"> <option v-for="c in countries" v-bind:key="c.CountryCode" v-bind:value="c.CountryCode&q ...

Enhancing JEST testing efficiency using vue.js

I am currently working on a basic app with a few components and only one test for the Login.vue component. Whenever I run jest, it seems to take around 10 to 20 seconds each time. I was wondering if there are any ways to improve the performance or if this ...

Using CKEditor5 to Capture and Edit Key Presses

I'm currently working on capturing input from a CKEditor5 within an Angular application using TypeScript. While I am able to successfully display the CKEditor and confirm its presence through logging, I am facing difficulties in capturing the actual i ...