vite icon indicating copy to clipboard operation
vite copied to clipboard

Vite4 build does not respect the assets path

Open jorrete opened this issue 2 years ago • 9 comments

Describe the bug

Vite4 does not generate the same path for associated assets when building than Vite3.

I'm working with a Vite+Django integration. When building assets, it's important to keep the same path to allow Django found related files. With vite3 when building the file "/my-code/index.js" an asset was build at "/my-code/index.css". Now with vite4, the assets for file "/my-code/index.js" it's build at "/index.css". I've tried to get the right info with the "assetFileNames" functions to no avail. I've used the "build.rollupOptions.input" and the "build.lib.entry" configurations, but nothing changes. There is a link with a repo with a setup to see the difference with both versions.

Reproduction

https://github.com/jorrete/vite-styles-build.git

Steps to reproduce

npm install && npm run build

System Info

System:
    OS: Linux 6.0 Fedora Linux 37 (Workstation Edition)
    CPU: (12) x64 AMD Ryzen 5 PRO 4650U with Radeon Graphics
    Memory: 13.25 GB / 22.70 GB
    Container: Yes
    Shell: 5.2.9 - /bin/bash
  Binaries:
    Node: 18.12.1 - /usr/bin/node
    npm: 8.19.2 - /usr/bin/npm
  Browsers:
    Chrome: 108.0.5359.124
    Firefox: 108.0

Used Package Manager

npm

Logs

No response

Validations

jorrete avatar Dec 19 '22 11:12 jorrete

I have the same issue since I have started using vite4.

Mcdostone avatar Dec 22 '22 15:12 Mcdostone

try

 "rollupOptions": {
      "output": {
        "assetFileNames": "my-folder/[name][extname]"
      },
}

sun0day avatar Dec 29 '22 02:12 sun0day

From what I understand, there's something wrong with vite4: According to the documentation:

Note that it is possible when using the object form to put entry points into different sub-folders by adding a / to the name. The following will generate at least two entry chunks with the names entry-a.js and entry-b/index.js, i.e. the file index.js is placed in the folder entry-b:

Mcdostone avatar Dec 29 '22 19:12 Mcdostone

try

 "rollupOptions": {
      "output": {
        "assetFileNames": "my-folder/[name][extname]"
      },
}

Yes, that works, but it is not exactly the "problem" I want to point. In Vite3 the base name ([name]) had already his path embed, where in Vite4 [name] is the basename only. My use case is to gather files from a folder and pass it with the "input" object. The keys of the object are the relative paths and I expect that the assets also are placed at the same folder of the "entryFileNames".

jorrete avatar Dec 29 '22 19:12 jorrete

I have the same issue.

assetFileNames: (assetInfo: any) => {
  const base = dirname(assetInfo.name)
  return `${base}/[name].[hash].[ext]`
},

I used this to have /app/css/style.css in /app/dist/css/style.css
This no longer works. You cannot have './[name].[hash].[ext]' as value either in 4.0.0. It doesn't allow having a relative path which starts with ./

woldtwerk avatar Jan 09 '23 14:01 woldtwerk

I've run into this same issue. Nested paths to assets in my source are getting flattened during build in the output directory.

This is pretty frustrating since it worked before.

seangwright avatar Jan 26 '23 21:01 seangwright

Same issue, can't keep assets path tree after build. Everithing goes into one big heap. It was broken in v4.0.0-alpha.2

Profesor08 avatar Feb 01 '23 10:02 Profesor08

This commit? https://github.com/vitejs/vite/commit/78c77beb5bf6112588581c0cbb47bc4d3bfed681

@patak-dev

kuoruan avatar Feb 01 '23 14:02 kuoruan

@kuoruan I think so, because in v4.0.0-alpha.1 it is ok.

Profesor08 avatar Feb 01 '23 14:02 Profesor08

Has anyone found a workaround? How to get all original paths of all assets? Example: entry point - main.js import './style.css' style.css .block { background-image: url(/images/javascript.svg); } I can't get this asset in any hook

Semdevmaster avatar Feb 11 '23 19:02 Semdevmaster

I'm facing the same issue. I'm trying to have a library build setup to have separated React components with their own CSS next to them. So I can load the component alongside its CSS in a separate project with some sort of loader. But the result is always the same.

├── dist
    ├── Foo
    │   └── index.js
    ├── Bar
    │     └── index.js
    └── index.css

So I end up creating a script to wrap around the build function.

import { build } from "vite";
import { resolve } from "path";

const dirs = ["Foo", "Bar"];

dirs.forEach(async (dir) => {
  await build({
    build: {
      lib: {
        entry: resolve("src", dir),
        name: dir,
        formats: ["es"],
        fileName: `${dir}/index`,
      },
      rollupOptions: {
        external: ["react", "react/jsx-runtime"],
        output: {
          assetFileNames: `${dir}/[name][extname]`,
        },
      },
    },
  });
});

So the result looks like

├── dist
    ├── Foo
    │   ├── index.css
    │   └── index.js
    └── Bar
        ├── index.css
        └── index.js

But there is a problem with this setup. If there is shared code, it won’t be an extra chunk next to the build result but included in every index.js which imports it.

It could be nice to have a new token for entry different from the name token to be used in a assetFileNames config under lib. And also respect the build.cssCodeSplit. Something like this.

{
  build: {
    cssCodeSplit: true,
    lib: {
      entry: {
        Foo: resolve("src", "Foo"),
        Bar: resolve("src", "Bar"),
      },
      formats: ["es"],
      fileName: `[entry]/index`,
      assetFileNames: `[entry]/[name][extname]`,
    },
    rollupOptions: {
      external: ["react", "react/jsx-runtime"],
    },
  },
}

diego-toro avatar Mar 25 '23 15:03 diego-toro

Duplicate of #12072

sapphi-red avatar Aug 20 '23 11:08 sapphi-red

me too I want to make the image path of the code and the path of the build file the same ex) code src ---- assets -------- comoponentA ---------------- ***.png -------- componentB ---------------- ***.png

after build _dist ---- img -------- comoponentA ---------------- ***.png -------- componentB ---------------- ***.png

like this

but vite 4.0 not working any more it's work in only vite 3.x.x because vite 4.0 does not respect the assets path

assetFileNames(assetInfo) {
    const dirMaintain = (assetName: string) => {
        const assetIndex = assetName.indexOf("assets");
        const dirArray = assetName.substring(assetIndex).split("/");
        return dirArray.splice(1, dirArray.length - 2).join("/");
    };
    let extType = assetInfo.name.split(".").at(1);
    const base = dirname(assetInfo.name);
    if (/\.css$/.test(base)) {
        extType = "css";
    } else if (/\.png|\.webp|\.svg$/.test(base)) {
        extType = dirMaintain(base);
    } 
    return `${extType}/[name][extname]`;
},

anyone solve this provlem??

haryan248 avatar Aug 25 '23 05:08 haryan248