vite
vite copied to clipboard
Vue + Vite + SSR: Referencing public assets with the root path (`/myimage.jpg`) inside the `public` directory results in a Rollup error
Describe the bug
Using vite-plugin-ssr with Vue, running build
with an asset referenced from the root path (e.g. /myimage.jpg
) results in a Rollup error. This doesn't occur during dev
.
Also, the issue doesn't occur when used with a generic Vue SPA.
However, @brillout noted that vite-plugin-ssr doesn't do anything about the public directory
Here's a detailed explanation of the scenarios:
Scenario A: VPS with Vue using npm init vite-plugin-ssr@latest
"vite": "^3.0.9",
"vite-plugin-ssr": "^0.4.32",
"@vitejs/plugin-vue": "^3.0.3"
myimage.jpg
can be found in public
directory, inside the root component in the template:
this breaks:
<img src="/myimage.jpg" />
this works:
<img src="http://localhost:3000/myimage.jpg" />
Scenario B: Vue 3 project using npm init vue@latest
"vite": "^3.0.9",
"@vitejs/plugin-vue": "^3.0.3"
myimage.jpg
can be found in public
directory, inside the root component in the template:
this works:
<img src="/myimage.jpg" />
this works:
<img src="http://localhost:3000/myimage.jpg" />
Reproduction
https://github.com/truumahn/vps-public-image-repro
System Info
System:
OS: Linux 5.10 Ubuntu 20.04.2 LTS (Focal Fossa)
CPU: (12) x64 AMD Ryzen 5 4600H with Radeon Graphics
Memory: 5.76 GB / 15.31 GB
Container: Yes
Shell: 5.8 - /usr/bin/zsh
Binaries:
Node: 16.16.0 - /mnt/wslg/runtime-dir/fnm_multishells/31022_1662972639084/bin/node
npm: 8.11.0 - /mnt/wslg/runtime-dir/fnm_multishells/31022_1662972639084/bin/npm
Browsers:
Chrome: 96.0.4664.45
npmPackages:
@vitejs/plugin-vue: ^3.0.3 => 3.1.0
vite: ^3.0.9 => 3.1.0
Used Package Manager
pnpm
Logs
Click to expand!
[vite]: Rollup failed to resolve import "/politecat.jpg" from "renderer/PageShell.vue?vue&type=script&setup=true&lang.ts".
This is most likely unintended because it can break your application at runtime.
If you do want to externalize this module explicitly add it to
`build.rollupOptions.external`
[vite-plugin-ssr:autoFullBuild] [vite]: Rollup failed to resolve import "/politecat.jpg" from "renderer/PageShell.vue?vue&type=script&setup=true&lang.ts".
This is most likely unintended because it can break your application at runtime.
If you do want to externalize this module explicitly add it to
`build.rollupOptions.external`
error during build:
Error: [vite]: Rollup failed to resolve import "/politecat.jpg" from "renderer/PageShell.vue?vue&type=script&setup=true&lang.ts".
This is most likely unintended because it can break your application at runtime.
If you do want to externalize this module explicitly add it to
`build.rollupOptions.external`
at onRollupWarning (file:///path/to/project/vite-ssr-project/node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-665b0112.js:45824:19)
at onwarn (file:///path/to/project/vite-ssr-project/node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-665b0112.js:45622:13)
at Object.onwarn (file:///path/to/project/vite-ssr-project/node_modules/.pnpm/[email protected]/node_modules/rollup/dist/es/shared/rollup.js:23225:13)
at ModuleLoader.handleResolveId (file:///path/to/project/vite-ssr-project/node_modules/.pnpm/[email protected]/node_modules/rollup/dist/es/shared/rollup.js:22352:26)
at file:///path/to/project/vite-ssr-project/node_modules/.pnpm/[email protected]/node_modules/rollup/dist/es/shared/rollup.js:22313:26
ELIFECYCLE Command failed with exit code 1.
Validations
- [X] Follow our Code of Conduct
- [X] Read the Contributing Guidelines.
- [X] Read the docs.
- [X] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- [X] Make sure this is a Vite issue and not a framework-specific issue. For example, if it's a Vue SFC related bug, it should likely be reported to vuejs/core instead.
- [X] Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- [X] The provided reproduction is a minimal reproducible example of the bug.
Vite-plugin-ssr doesn't do anything with public/
assets, so it's likely a Vite issue during SSR building.
It seems it does not reproduce with a simple setup. https://stackblitz.com/edit/github-marmex?file=src%2FApp.vue
And it happens with vite-plugin-ssr + react too. https://stackblitz.com/edit/github-6pyqmj?file=renderer%2FPageShell.jsx
And it happens with vite-plugin-ssr + react too.
Only because you imported the images, not used them with the root path as /logo.svg
directly at the src
attribute of the img
element. It successfully builds like this: https://stackblitz.com/edit/github-6pyqmj-wrxz1m?file=renderer/PageShell.jsx
The same doesn't work with Vue though.
plugin-vue transforms <img src="/logo.svg">
into
<template>
<img :src="logoSvg" />
</template>
<script setup>
import logoSvg from '/logo.svg'
</script>
So something is not working around resolving /logo.svg
.
And since it does not happen with Vite only, I guess something in vite-plugin-ssr is interacting it.
It builds successfully with the following vite.config.ts
:
import vue from "@vitejs/plugin-vue";
import ssr from "vite-plugin-ssr/plugin";
import { UserConfig } from "vite";
const config: UserConfig = {
plugins: [
vue({
template: {
transformAssetUrls: {
img: [],
},
},
}),
ssr({ prerender: true }),
],
};
export default config;
https://stackblitz.com/edit/vitejs-vite-nsfvwb?file=vite.config.ts
So it is indeed the Vue plugin that causes this. I'm just checking the documentation: https://github.com/vitejs/vite/tree/main/packages/plugin-vue#asset-url-handling
This behaviour was introduced in 3.x
.
It seems that @vitejs/plugin-vue
tries to resolve src
if it doesn't match a public/
asset.
Vite-plugin-ssr 0.4 changed Vite's config publicDir
to false
for SSR, which explains the problem.
I reverted that change and released a new version [email protected]
which should fix the problem.
@truumahn Let me know if you run into any other issues. We can close this in the meantime.
@sapphi-red The proper fix would be to stop separating the client-side and server-side building process into two isolated processes. FYI, this is one of many reasons why I believe the decision the Vite team took here https://github.com/vitejs/vite/discussions/9496#discussioncomment-3384709 was a mistake. Separating both builds is asking for trouble.
The proper fix would be to stop separating the client-side and server-side building process into two isolated processes. FYI, this is one of many reasons why I believe the decision the Vite team took here https://github.com/vitejs/vite/discussions/9496#discussioncomment-3384709 was a mistake. Separating both builds is asking for trouble.
I created a discussion #10097 - Unify client-side and server-side build steps about this.
It seems that
@vitejs/plugin-vue
tries to resolvesrc
if it doesn't match apublic/
asset.
Yes. This is because of https://github.com/vitejs/vite/issues/10082#issuecomment-1243764867.
Vite-plugin-ssr 0.4 changed Vite's config
publicDir
tofalse
for SSR, which explains the problem.
What is the purpose of changing this? Avoiding the public directory to be copied? I think it's correct not to resolve public assets when publicDir: false
is set.
Yes, to avoid the public directory being copied twice at dist/client/assets/
and dist/server/assets/
. If the user has a couple of gigabytes of images, that's significant.
I'm closing this as the original issue has been resolved. The discussion can be continued in https://github.com/vitejs/vite/discussions/10097