Challenges with Asset Management in Vite Compilation Result

I'm encountering a problem with structuring assets in the output directory while utilizing Vite for my project. I have set up the output.assetFileNames option to categorize assets into subfolders based on their types (css, fonts, img, js), but it's not functioning as anticipated.

Here is my Vite Configuration:

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import autoprefixer from 'autoprefixer';
import imagemin from 'imagemin';
import imageminWebp from 'imagemin-webp';
// Specify the input and output directories for img minify
const inputDir = './src/assets/img';
const outputDir = './dist/assets';

export default defineConfig({
    server: {
        host: true,
        port: 8080,
        open: true,
        https: false,
        proxy: {
            '/api': {
                target: 'https://jsonplaceholder.typicode.com',
                changeOrigin: true,
                rewrite: path => path.replace(/^\/api/, ''),
            },
        },
    },
    css: {
        postcss: {
            plugins: [
                autoprefixer(), // Add CSS prefixes
            ],
        },
    },
    build: {
        plugins: [
            vue(),
            autoprefixer(), // Add CSS prefixes
            // Minify images
            imagemin([`${inputDir}/*.{jpg,png}`], {
                destination: outputDir,
                plugins: [
                    imageminWebp({
                        quality: 75, // Adjust the quality (0 to 100)
                    }),
                ],
            }),
        ],
        assetsDir: 'assets',
        minify: 'terser', // or 'esbuild' for esbuild-based minification
        sourcemap: true,
        cssCodeSplit: true,
        rollupOptions: {
            output: {
                assetFileNames: ({ name, ext }) => {
                    // Organize assets based on file type
                    if (ext === '.css') {
                        return `assets/css/${name}`;
                    } else if (ext === '.woff' || ext === '.woff2') {
                        return `assets/fonts/${name}`;
                    } else if (ext === '.jpg' || ext === '.webp') {
                        return `assets/img/${name}`;
                    } else if (ext === '.js') {
                        return `assets/js/${name}`;
                    }
                    // For other file types, use the default output format with hash
                    return `assets/${name}`;
                },
            },
        },
    },

});

I tried various approaches, but this closely resembles the structure with this configuration

Project Structure:

dist
 ┣ assets
 ┃ ┣ arslaner.jpg
 ┃ ┣ arslaner.webp
 ┃ ┣ index-gT3gkYz_.js.map
 ┃ ┣ index.css
 ┃ ┣ rawert.jpg
 ┃ ┣ rawert.webp
 ┃ ┣ SegoeUI-VF.woff
 ┃ ┗ SegoeUI-VF.woff2
 ┣ index.html
 ┗ vite.svg

Expected Output:

dist
 ┣ assets
 ┃ ┣ css
 ┃ ┃ ┗ index.css
 ┃ ┣ fonts
 ┃ ┃ ┣ SegoeUI-VF.woff
 ┃ ┃ ┗ SegoeUI-VF.woff2
 ┃ ┣ img
 ┃ ┃ ┣ arslaner.jpg
 ┃ ┃ ┣ arslaner.webp
 ┃ ┃ ┣ rawert.jpg
 ┃ ┃ ┗ rawert.webp
 ┃ ┗ js
 ┃ ┃ ┗ index-gT3gkYz_.js.map
 ┣ index.html
 ┗ vite.svg

Issue: Despite setting up the output.assetFileNames function, the assets are not getting structured into the specified subdirectories. I've double-checked the file extensions, revisited the Vite configuration, and attempted a clean build, but the problem persists.

Your assistance in resolving this matter would be greatly appreciated. If additional information is required, please don't hesitate to ask. Thank you!

Answer №1

Managing Assets

When it comes to handling files that are categorized as assets, excluding the core index-….js and index.html files, their locations can be customized using the assetFileNames option. The documentation for output asset file names states:

Type:
Type:  string| ((assetInfo: AssetInfo) => string)

[…]

When a function is used, the assetInfo parameter is a simplified version of the one found in generateBundle without the fileName.

Referencing the Rollup source code where assetFileNames is utilized, we can observe how the functionality is implemented:

typeof outputOptions.assetFileNames === 'function'
  ? outputOptions.assetFileNames({ name, source, type: 'asset' })
  : outputOptions.assetFileNames,

It's important to note that the property ext does not exist within the object passed to assetFileNames. Consequently, when defining your function like this:

assetFileNames: ({ name, ext }) => {

The value of ext will be undefined for all asset files, leading to specific code paths not being accessed. To work around this, consider extracting the extension manually:

// …
import path from 'node:path';
// …
export default defineConfig({
  // …
  build: {
    // …
    rollupOptions: {
      output: {
        assetFileNames: ({ name }) => {
          const ext = path.extname(name);

Source Mapping

As for the index-gT3gkYz_.js.map sourcemap file, utilizing the output.sourcemapFileNames Rollup setting is essential. Here's an example of how to configure it:

// …
export default defineConfig({
  // …
  build: {
    // …
    rollupOptions: {
      output: {
        // …
        sourcemapFileNames: 'assets/js/[name].[hash].js.map',

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

What is the common approach for directing a setState Redux action?

I am looking to streamline my state update actions in multiple react-redux reducers by creating a general setState action. This will allow me to have consistent syntax for dispatching both local and redux scope updates. For local updates, I would use this. ...

Using jQuery to delay hiding for 2 seconds

Hey there! I'm facing an issue with my code. The function is supposed to make #aboutPopOut slide to the left, and then after a 2-second delay, fade out the fadescreen by hiding it. The sliding part works fine, but the waiting and hiding do not seem to ...

Unable to Submit Form in JSP Page

I have encountered an issue with a JSP page that contains a form which I am submitting using JavaScript. When the page has a smaller number of items, between 10-50, the submission works perfectly fine. However, when there are around 500 items or more on t ...

What is the best way to send information from a component on one page to a component on another page in React/Next.js?

Overview In my Next.js application, I have two pages: index.js and results.js. The index page features two Location Autocomplete fields that provide the address and LatLng of a selected location. This data is stored in a variable named markers on the inde ...

Local comparison causing unit test failure

Uncertain as to why this is not working properly with Dojo doh.t(formatedValue.localeCompare("16,91 $CA") === 0, "incorrect french formatting") The value of formattedValue is definitely "16,91 $CA" so I am certain it should be a match. However, when I at ...

Execute an AJAX call to remove a comment

Having some trouble deleting a MySQL record using JavaScript. Here is the JavaScript function I am trying to use: function deletePost(id){ if(confirm('Are you sure?')){ $('#comment_'+id).hide(); http.open("get","/i ...

Securing the Firebase Admin SDK JSON file within a NextJS project for optimal protection

I'm currently working on a NextJS app that uses the Firebase Admin SDK, but I'm unsure of where to securely store the JSON file containing all the keys. It seems that integrating secret keys in JSON files with an .env.local file is not possible. ...

Add data to a size guide

My coding project involved creating a sizing chart using HTML, CSS, and JavaScript. The chart allows users to select their preferred units of measurement (metric or imperial). I used JavaScript to dynamically update the values in the chart based on the sel ...

Error: Unable to access the 'map' property of an undefined object......Instructions on retrieving a single post

import React,{useEffect, useState} from 'react' //import {Link} from 'react-router-dom' import { FcLikePlaceholder, FcComments } from "react-icons/fc"; const SinglePost = () => { const [data,setdata] = useState([]) co ...

Tips for utilizing ng-checked and ng-disabled in conjunction with ng-repeat

I encountered a challenge with ng-repeat while incorporating ng-checked and ng-disable alongside it. <div ng-repeat="module in modulelist"> <input id="switch{{$index}}" ng-init="setState($index);" type="checkbox" ng-checked="switch.checked" ng-di ...

What are the steps to execute a filter operation on a table by utilizing two select box values with jQuery?

I have a challenge with two dropdown menus. One contains names and the other subjects, along with a table displaying information in three columns: name, subject, and marks. I would like to implement a filter based on the selections in these two dropdowns. ...

What is the best way to send multiple input box values to a function set in the controller?

I am attempting to send the values of two input boxes to a single controller function. <div class="container" ng-controller="MainCtrl"> <div class="row"> <div class="col-lg-6"> <input type="text" ...

Is there a way to display a bootstrap modal when the page is refreshed?

Is there a way to automatically display a Bootstrap modal box without the need for clicking anywhere? I want the modal to appear every time the page is refreshed, rather than requiring a click event. Can anyone provide guidance on achieving this? < ...

Iframe Interactivity

My goal is to create an interactive iframe that will match the current parent URL (). For example, if I have an iframe pointing to http://www.google.com and click a link within the iframe, it should update the parent URL to , and then load the clicked con ...

Error encountered while attempting to retrieve an environment variable: Invalid token found

I am currently facing an issue while trying to add an environment variable inside the .env file in my Nuxt project. The version of Nuxt.js I am using is 2.15.3 Below is a snippet from my nuxt.config.js: export default { publicRuntimeConfig: { baseU ...

What is the method to advance the opposing line in the dynamic chart?

Here is the link to the code for a dynamic graph. I am struggling with keeping the red line updated and moving forward together with the blue line. I cannot figure out why the red line remains static in the dynamic graph. Any suggestions on how to solve t ...

Is it possible to maintain the component's DOM state when navigating away and then returning in Angular?

After spending several days researching this issue, I find myself at a dead end. I thought I was dealing with a common scenario: A user navigates to a specific page, makes some changes (such as editing an input field, scrolling through grid data, or chang ...

Is it possible to manipulate the content inside a div tag using JavaScript in HTML?

What is the most efficient way to dynamically adjust a data offset value within an HTML tag using JavaScript? For example: <div class="box" data-offset="2s"></div> I am looking to update the value within the data-offset attribute based on s ...

How to load MTL files from local storage using Three.js in Chrome

I'm encountering an issue when attempting to load MTL files using Three.js on Chrome. While everything runs smoothly on Safari, I keep running into a cross-origin request error in Chrome when working with local files. I'm at a loss on how to reso ...

Utilizing Various Perspectives in Angular with the ng-view Directive

Can anyone assist me with a challenge I'm facing regarding views? While this is a hypothetical scenario and there's no code available to review... Let's imagine a simple site with three routes: /signin /users /users/:id Upon accessing t ...