question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

manifest.json does not include assets

See original GitHub issue

Describe the bug

Statically imported assets (SVG file in my case) will get bundled and created in the outDir, but are missing in the generated manifest.json.

vite.config.js

import { defineConfig } from 'vite';
import legacy from '@vitejs/plugin-legacy';

export default defineConfig({
    base: '/static/',
    publicDir: 'assets/static/',
    build: {
        manifest: true,
        outDir: 'public/static/',
        assetsInlineLimit: 0,
        rollupOptions: {
            input: 'assets/main.ts',
        },
    },
    plugins: [legacy()],
});

assets/main.ts

import './icon.svg';

manifest.json

{
  "assets/main-legacy.ts": {
    "file": "assets/main-legacy.dd90b2c6.js",
    "src": "assets/main-legacy.ts",
    "isEntry": true
  },
  "assets/main.ts": {
    "file": "assets/main.9470b65c.js",
    "src": "assets/main.ts",
    "isEntry": true
  }
}

output files

  • main.9470b65c.js
  • main-legacy.dd90b2c6.js
  • icon.a0d73e22.svg

System Info

  • vite version: 2.0.5
  • Operating System: Windows 10
  • Node version: 12.16.1
  • Package manager (npm/yarn/pnpm) and version: npm 7.5.3

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:3
  • Comments:20 (6 by maintainers)

github_iconTop GitHub Comments

21reactions
rynpsccommented, Sep 29, 2021

Had a look and Vite is already tracking and outputting any assets regardless of their usage so I think it makes sense to expose them in the manifest so those integrating with a backend can take advantage of Vite for processing assets not directly used by Vite.

In my testing importing static assets via import.meta.glob is enough for Vite to process them even if not referenced.

src
├── entry.scss
├── files
│   └── favicon.svg
├── fonts
│   ├── my-font.woff
│   └── my-font.woff2
├── main.scss
└── main.ts

vite.config.js

export default defineConfig({
  build: {
    rollupOptions: {
      input: 'src/main.ts'
    }
  }
})

src/main.ts


import './main.scss'

let files = import.meta.glob('./files/**/*');

// The "files" variable doesn't need to used for imports to get processed.

src/main.scss

@font-face {
  font-family: "Font";
  font-style: normal;
  font-weight: 400;
  src:
    url("/src/fonts/my-font.woff2") format("woff2"),
    url("/src/fonts/my-font.woff") format("woff");
}

With the above Vite will process and output files matching the glob ./files/**/*. The only missing bit is a way to get the final path. Looking at generateBundle the asset chunks are present but not exposed so I propose we add a _assets entry within the manifest that contains all assets Vite has processed e.g.

{
  "_assets": {
    "src/files/favicon.svg": "assets/favicon.17e50649.svg",
    "src/fonts/my-font.woff2": "assets/my-font.bf47658a.woff2",
    "src/fonts/my-font.woff": "assets/my-font.80d4cac9.woff",
    "main.css": "assets/main.eac10a5f.css"
  },
  "src/main.ts": {
    "file": "assets/main.6097d7e4.js",
    "src": "src/main.ts",
    "isEntry": true,
    "css": [
      "assets/main.eac10a5f.css"
    ],
    "assets": [
      "assets/my-font.bf47658a.woff2",
      "assets/my-font.80d4cac9.woff"
    ]
  }
}

The _assets entry contains assets both used within chunks i.e. fonts and non used assets i.e. those imported via the glob. This is desirable as it then allows you to more easily reference files like fonts for things like generating preload directives and other assets such as favicons or static assets referenced in the frameworks templating language.

I’ve quickly modified vite/packages/vite/src/node/plugins/manifest.ts to achieve the above but I’m likely missing something.

if (chunk.type === 'asset') {
  if (!manifest['_assets']) {
    manifest['_assets'] = {}
  }
  let name = normalizePath(
    path.relative(config.root, chunk.name)
  )
  manifest['_assets'][name] = chunk.fileName
}

The only thing that isn’t quite right is how css is handled as Vite considers it an asset but the full path is stripped by the time the manifest is generated i.e. instead of src/main.scss it appears as main.css.

I’m not sure if we should remove the CSS properties or try to add the full path back in. If we did it keep it and use the source path it would then be possible to use css as an entry.

export default defineConfig({
  build: {
    rollupOptions: {
      input: [
        'src/main.ts',
        'src/entry.scss',
      ]
    }
  }
})

This is currently possible (not sure if intentional) but you’d have to remember to reference your css by the file name (entry.scss) rather than path (src/entry.scss) and I’m assuming that relying on filename only will result in conflicts.

<link rel="stylesheet" href="/assets/{{ manifest['_assets']['entry.css'] }}" />

But by keeping the original path things would work as expected.

{
  "_assets": {
    "src/files/favicon.svg": "assets/favicon.17e50649.svg",
    "src/fonts/my-font.woff2": "assets/my-font.bf47658a.woff2",
    "src/fonts/my-font.woff": "assets/my-font.80d4cac9.woff",
    "src/main.scss": "assets/main.eac10a5f.css",
    "src/entry.scss": "assets/entry.wef646xf.css"
  },
  "src/main.ts": {
    "file": "assets/main.6097d7e4.js",
    "src": "src/main.ts",
    "isEntry": true,
    "css": [
      "assets/main.eac10a5f.css"
    ],
    "assets": [
      "assets/my-font.bf47658a.woff2",
      "assets/my-font.80d4cac9.woff"
    ]
  }
}
<link rel="stylesheet" href="/assets/{{ manifest['_assets']['src/entry.scss'] }}" />

To summarise there are two things to look at:

  • Exposing all assets in the manifest via something like _assets
  • Providing the full source path for css
17reactions
thasmocommented, Oct 12, 2021

I feel like a “web bundle manifest” specification/standard would be really helpful. As some already mentioned, I would also assume all files, which end up in the final bundle/dist/build directory, to be present in the manifest.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Symfony Error: "An exception has been thrown during the ...
"An exception has been thrown during the rendering of a template ("Asset manifest file "/../public/build/manifest.json" does not exist.") It ...
Read more >
What's assets-manifest.json and how does it work? #6436
The objective of manifest is to create an asset map for tools as per comments in the source code. I am not sure...
Read more >
Assets Manifest | Eightshift Development kit
If there is no manifest.json file or you provided the wrong asset name, there will be a descriptive message for you. If you...
Read more >
Missing Asset-Manifest.json - WordPress.org
It seems I have a 404 error of a file calling for /asset-manifest.json on my root directory. My host says it could be...
Read more >
Using Webpack Encore for your website assets
Webpack Encore is a tool to manage your javascript and css assets. ... To enable it, add the following line to the config/bundles.php...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found