Skip to content

__vitePreload dependencies could be relative to import.meta.url #2009

@Rich-Harris

Description

@Rich-Harris

Describe the bug

__vitePreload includes assumptions about where assets are being served from. In a normal Vite project those assumptions hold true, but in more bespoke situations they may not.

Additionally, in the case where CSS dependencies fail to load (whether due to a network failure, or because of the situation described above) the promise returned from __vitePreload will never resolve.

Reproduction

https://github.com/Rich-Harris/vite-preload-repro

Given sources like this...

// src/index.js
import('./foo.js').then((foo) => {
  foo.hello();
});
// src/foo.js
import './foo.css';

export function hello() {
  document.body.innerHTML = `<h1>Hello!</h1>`;
}
// src/foo.css
h1 {
  color: red;
}

...and a config like this...

const config = {
  build: {
    cssCodeSplit: true,
    lib: {
      entry: resolve('src/index.js'),
      name: 'app', // this doesn't seem to do anything?
      formats: ['es']
    },
    outDir: 'dist',
    minify: false,
    rollupOptions: {
      output: {
        entryFileNames: '[name]-[hash].js',
        chunkFileNames: '[name]-[hash].js',
        assetFileNames: '[name]-[hash][extname]'
      }
    }
  }
};

...the resulting dist/index-ed8ec7ff.js file contains this line:

__vitePreload(() => import("./foo-5368ca0f.js"), true ? ["/foo-5368ca0f.js","/foo-0a0d0fb0.css"] : void 0).then((foo) => {

In the case where assets are served from somewhere other than / (for example, on an external CDN), the /foo-5368ca0f.js and /foo-0a0d0fb0.css paths are meaningless. If they were relative paths instead, the implementation of __vitePreload could add the following...

  return Promise.all(deps.map((dep) => {
+   dep = new URL(dep, import.meta.url).href;
    if (dep in seen)
      return;

...and the resulting files would be more portable.

Meanwhile, to prevent the promise from hanging:

    if (isCss) {
-     return new Promise((res) => {
-       link.addEventListener("load", res);
+     return new Promise((res, rej) => {
+       link.addEventListener("load", res);
+       link.addEventListener("error", rej);
      });
    }

System Info

  • vite version: 2.0.0-beta.69
  • Operating System: Mac OS
  • Node version: 12.18.3
  • Package manager (npm/yarn/pnpm) and version: npm 6.14.6

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestp3-downstream-blockerBlocking the downstream ecosystem to work properly (priority)

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions