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), {});

https://i.sstatic.net/60oPxRBM.png

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

As I attempt to log in, the GitHub API is sending back a message stating that authentication

const fetchUser = async () =>{ let usernameValue : any = (document.getElementById('username') as HTMLInputElement).value; let passwordValue : any = (document.getElementById('password') as HTMLInputElement).value; const ...

How can I populate dropdown options from an API in a react JS project using typescript and react saga?

Check out my page, where I am trying to fetch brand options from an API. Below is the saga I have implemented: Action.tsx export const getBrandsForDropdown = (request: IPagination) => { return { type: actions, payload: request ...

Issue with CSS files in Jest"errors"

I'm currently facing an issue while trying to pass my initial Jest Test in React with Typescript. The error message I am encountering is as follows: ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){.App ...

Retrieving the final selection made in vuetify v-select

Can someone please explain how to retrieve the last selected or removed value in a vuetify v-select when using the multiple property? For example, let's say we have a v-select with items [ 'Choice A', 'Choice B', 'Choice C&ap ...

Guide to releasing a NestJs library on npm using the nrwl/nx framework

Struggling with creating a publishable NestJS library using NX. Despite reading numerous documentations, I still can't figure it out. I've developed a NestJS library within an NX monorepository and now I want to publish just this library on NPM, ...

Unable to dispatch actions within the mounted lifecycle hook in Vuex?

Can anyone explain why the json data I fetch with axios is not populating my state.pages as expected? Interestingly, when I make a change to the file and vite reloads, the data appears on the page. However, it disappears again upon refreshing the browser. ...

Sort through the files for translation by utilizing a feature within Typewriter

I am looking to implement Typewriter in a project that involves translating many C# files into TypeScript using WebEssentials. Is there a way to configure the template so that only class files containing a specific attribute are translated in this mann ...

Having difficulty displaying multiple markers on a map using a Vue browser script

When I hard code the markers' latitude and longitude, it works fine. However, when built using a function, it does not plot correctly. In the code below, only two markers are appearing instead of three. I have tried using a complete vue browser scrip ...

Ways to retrieve the identifier of a specific element within an array

After successfully retrieving an array of items from my database using PHP as the backend language, I managed to display them correctly in my Ionic view. However, when I attempted to log the id of each item in order to use it for other tasks, it consistent ...

Ways to trigger the keyup function on a textbox for each dynamically generated form in Angular8

When dynamically generating a form, I bind the calculateBCT function to a textbox like this: <input matInput type="text" (keyup)="calculateBCT($event)" formControlName="avgBCT">, and display the result in another textbox ...

The specified data type is not compatible with the current context and cannot be treated as an array

Just starting out with TypeScript and I've encountered an issue that's preventing me from successfully building my app. Everything runs smoothly on my local environment, but as soon as I try to build it, an error pops up. Here's a snippet o ...

Angular is not able to access the value of a promise in a different function after it has been retrieved

I have a form with default values that should be added to the form fields when it appears. There are two functions: #1 for fetching data from the backend and #2 for displaying the form: person$: any; ngOnInit() { this.getPersonData(123) this.buildPer ...

Data that is loaded asynchronously will not display rendered

I have async data loading via jayson from a server. After the data has finished loading, the boolean "loading" is set to false but my content does not re-render. Even though I can see on the console that the data was loaded correctly. var App = new Vue( ...

React | Utilizing ForwardedRefs with React Components

I'm currently working on a React project where I am creating a custom component that needs to be exported using forwardedRef. However, as I attempt to do this, an error keeps popping up: error This is the code snippet causing the issue: export inter ...

Tips for retrieving and presenting information from a JSON document in a React TypeScript application

I am struggling to display data in a list format using TypeScript. I am able to fetch the data but unable to display it properly. I am currently using map to iterate through an array of JSON objects. //json file [ { "id": "6s", ...

Is it possible to use Angular signals instead of rxJS operators to handle API calls and responses effectively?

Is it feasible to substitute pipe, map, and observable from rxjs operators with Angular signals while efficiently managing API calls and their responses as needed? I attempted to manage API call responses using signals but did not receive quick response t ...

Data has not been loaded into the Angular NGX Datatable

As a beginner in Angular, I am struggling to set data from the module. ngOnInit() { this.populate(); } public populate() { this.productService.getAllProduct('6f453f89-274d-4462-9e4b-c42ae60344e4').subscribe(prod => { this. ...

Guide to making a Material Design Radial effect animation

I am looking to create a unique toolbar effect by following the material design radial reaction choreography guideline. https://i.stack.imgur.com/6oB8r.gif I want to achieve this using an angular 2 transition, but I need some guidance on how to implement ...

What is the best way to retrieve the value of the selected mat-option?

I've been struggling to extract the selected value of a mat-option using this specific HTML and TypeScript code. html <mat-form-field appearance="outline" floatLabel="always"> <mat-label>TRA Type</mat-label> ...

Interpolating SVG and HTML attributes in Vue.js

Wondering if this is the proper method to interpolate a value into an svg attribute using Vue. It seems to be effective for me, but I can't find any mention of it in their documentation. <svg :stroke-width="`${strokeWidth} px`" > ...