vite icon indicating copy to clipboard operation
vite copied to clipboard

Dynamic import fails in route with brackets or parenthesis

Open oreilles opened this issue 2 years ago • 3 comments

Describe the bug

This bug was initially reported to Sveltekit (https://github.com/sveltejs/kit/issues/8516), but it likely is a bug with Vite, related to https://github.com/vitejs/vite/issues/9833, but affecting direct imports rather than glob imports.

Dynamically importing a module in a route with [parameters] or (group), for example:

// src/routes/[foo]/+page.js
export async load = ({ params }) => (await import(`./index.${params.foo}.js`).data;


// src/routes/(foo)/bar/+page.js
export async load = ({ url }) => (await import(`./index.${url.params.get('foo'}.js`).data;

Fails with the following error:

Error: Unknown variable dynamic import: ../[foo]/index.foo.js
    at vite/dynamic-import-helper:7:96
    at new Promise (<anonymous>)
    at __vite_ssr_exports__.default (vite/dynamic-import-helper:6:12)
    at load (/src/routes/[foo]/+page.js:2:59)
    at Module.load_data (/node_modules/@sveltejs/kit/src/runtime/server/page/load_data.js:110:43)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async eval (/node_modules/@sveltejs/kit/src/runtime/server/page/index.js:195:13)

Reproduction

https://stackblitz.com/edit/sveltejs-kit-template-default-peg2jd?file=src/routes/[foo]/+page.js

Steps to reproduce

Navigate to the header links /(foo)/baz or /[foo] from the reproduction stackblitz.

System Info

System:
    OS: Windows 10 10.0.19045
    CPU: (20) x64 12th Gen Intel(R) Core(TM) i7-12700H
    Memory: 13.96 GB / 31.68 GB
  Binaries:
    Node: 16.17.0 - C:\Program Files\nodejs\node.EXE  
    npm: 8.15.0 - C:\Program Files\nodejs\npm.CMD     
  Browsers:
    Edge: Spartan (44.19041.1266.0), Chromium (109.0.1518.61)
    Internet Explorer: 11.0.19041.1566
  npmPackages:
    vite: ^4.0.0 => 4.0.4

Used Package Manager

npm

Logs

No response

Validations

oreilles avatar Jan 26 '23 13:01 oreilles

Here's a simpler repro, that doesn't involve SvelteKit:

https://github.com/Rich-Harris/vite-dynamic-import-repro

Rich-Harris avatar Jan 28 '23 00:01 Rich-Harris

Added a repro for https://github.com/sveltejs/kit/issues/8490 for good measure — these are treated differently (note the ' vs `):

console.log(Object.keys(import.meta.glob(`./\\(parens\\)/data-*.js`)).length);
console.log(Object.keys(import.meta.glob('./\\(parens\\)/data-*.js')).length);

Rich-Harris avatar Jan 28 '23 00:01 Rich-Harris

As a temporary solution for SvelteKit users facing this issue, rather than (which currently breaks):

export async load = ({ params }) => {
  const module = await import(`./index.${params.foo}.js`);
  return module.data;
}

do instead:

export async load = ({ params }) => {
  const modules = import.meta.glob('./index.*.js');
  const module = await modules[`./index.${params.foo}.js`]();
  return module.data;
}

The expected vite code should be the same for those two snippets.

oreilles avatar Jan 28 '23 12:01 oreilles

As found in https://github.com/vitejs/vite/pull/11839#issuecomment-1411656243, this would need to be fixed upstream in @rollup/plugin-dynamic-import-vars

bluwy avatar Apr 01 '23 12:04 bluwy

I made a PR that fixes the upstream issue: https://github.com/rollup/plugins/pull/1636 But even with that, it seems there's a bug in Vite side too.

IIUC this newRawPattern should not use toAbsoluteGlob, otherwise ( will be escaped. https://github.com/vitejs/vite/blob/0654d1b52448db4d7a9b69aee6aad9e015481452/packages/vite/src/node/plugins/dynamicImportVars.ts#L131-L134

sapphi-red avatar Nov 22 '23 12:11 sapphi-red