Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new URL broken when using alias or subpath imports together with template #18676

Open
7 tasks done
brokenmass opened this issue Nov 14, 2024 · 0 comments
Open
7 tasks done

Comments

@brokenmass
Copy link

brokenmass commented Nov 14, 2024

Describe the bug

Summary:

code like

new URL(`#images/${brand}/image.png`, import.meta.url).toString()

does not work as expected and simply return undefined.

Issue

This code

new URL(`#images/${brand}/image.png`, import.meta.url)

is converted to

new URL(import.meta.glob(`#images/**/image.png`, {eager: true, import: 'default', query: 'url'})[`#images/${brand}/image.png`], import.meta.url)

Unfortunately this does not work because import.meta.glob return an object where the keys are the path of the resolved assets from the project root (because it interpret the template as an 'absolute path' as it does not start with a .) while the 'resolution' key is the non transformed template string.

// import.meta.glob(`#images/**/image.png`, {eager: true, import: 'default', query: 'url'}
{
  '/path/to/images/BRAND1/image.png': xxx,
  '/path/to/images/BRAND2/image.png': yyy,
}

Solutions:

I wrote 2 possible solutions, please let me know which one is the preferred one (or suggest an alternative approach) and i'll raise a PR.

Solution 1:

modify import.meta.glob to 'remap' keys to the original 'query'

// import.meta.glob(`#images/**/image.png`, {eager: true, import: 'default', query: 'url'}
{
  '#images/BRAND1/image.png': xxx,
  '#images/BRAND2/image.png': yyy,
}

this is done by looking at the input globs and at their resolution and by applying the 'reverse' transformation to the resolved files.

if this is the preferred option it's possible to leave the 'current' keys in place in order to not make this a breaking change.

// import.meta.glob(`#images/**/image.png`, {eager: true, import: 'default', query: 'url'}
{
  '#images/BRAND1/image.png': xxx,
  '/path/to/images/BRAND1/image.png': xxx,

  '#images/BRAND2/image.png': yyy,
  '/path/to/images/BRAND2/image.png': yyy,
}

or could add an option to import.meta.resolve, like remapToGlob and apply that transformation only if it's true.

at this point the new URL code works because the expected key is actually defined

this is probably the best solution as otherwise import.meta.glob , even when used 'directly', returns unexpected results if used together with aliases/subpathImports

Solution 2:

leave import.meta.glob as it is but modify 'access' key.

this is done by resolving the glob pattern (in the example #images/**/image.png to the full path (let's say /root/dev/project/path/to/images/**/image.png , converting it to a path relative to the project root (/path/to/images/**/image.png), then swapping the prefixes (anything before the first ** in the resolved relative path and everythign before the ${ in the template string )

that generates

new URL(import.meta.glob(`#images/**/image.png`, {eager: true, import: 'default', query: 'url'})[`/path/to/images/${brand}/image.png`], import.meta.url)

another related bug

There's an error in the resolve plugin when resolving subpath imports:

const resolvedImports = resolveSubpathImports(id, importer, options)
      if (resolvedImports) {
        id = resolvedImports

        if (resolveOpts.custom?.['vite:import-glob']?.isSubImportsPattern) {
          return normalizePath(path.join(root, id))
        }
      }

this should instead be

const resolvedImports = resolveSubpathImports(id, importer, options)
      if (resolvedImports) {
        id = resolvedImports

        if (resolveOpts.custom?.['vite:import-glob']?.isSubImportsPattern) {
          return normalizePath(path.join(path.dirname(importer as string), id))
        }
      }

that's because resolveSubpathImports returns globs relative to the importer, not to the project root (

importsPath = path.relative(basedir, path.join(pkgData.dir, importsPath))
)

Reproduction

https://stackblitz.com/edit/vitejs-vite-3mn974

Steps to reproduce

No response

System Info

n/a

Used Package Manager

npm

Logs

No response

Validations

@brokenmass brokenmass changed the title new URL broken when using alias or subpath imports together with template new URL broken when using alias or subpath imports together with templates Nov 14, 2024
@brokenmass brokenmass changed the title new URL broken when using alias or subpath imports together with templates new URL broken when using alias or subpath imports together with template Nov 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant