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

feat(assets): allow new URL to resolve package assets #7837

Merged
merged 5 commits into from Sep 23, 2022

Conversation

kherock
Copy link
Contributor

@kherock kherock commented Apr 20, 2022

Description

This change allows modules to resolve asset URLs for assets located underneath a package path. E.g. new URL('@scope/component/assets/logo.png', import.meta.url)

close #6918

Additional context

I Implemented this in a backwards-compatible way by using a resolver which prefers relative paths and makes the root path resolve to the public base path.


What is the purpose of this pull request?

  • Bug fix
  • New Feature
  • Documentation update
  • Other

Before submitting the PR, please make sure you do the following

  • Read the Contributing Guidelines.
  • Read the Pull Request Guidelines and follow the Commit Convention.
  • Check that there isn't already a PR that solves the problem the same way to avoid creating a duplicate.
  • Provide a description in this PR that addresses what the PR is solving, or reference the issue that it solves (e.g. fixes #123).
  • Ideally, include relevant tests that fail without this PR but pass with it.

@kherock
Copy link
Contributor Author

kherock commented Apr 20, 2022

I'm facing an issue where I can't seem to get my changes to get package paths to resolve while running the dev server. I'm having trouble attaching to the dev server worker or getting any logs to diagnose the problem. I'd appreciate any insight on how to debug this!

I've resolved this by including the assets plugin for serve mode. This doesn't have any negative consequences as far as I can tell.

@poyoho
Copy link
Member

poyoho commented Apr 21, 2022

Thanks for your PR. But I'm not sure if this is necessary, because the type of new URL is

constructor (input: string, base?: string | URL);

the second params is base, if you support the new URL('@/hello.js', import.meta.url) I think it's a little confusing, but to be honest, I like it.

Maybe new URL('@/hello.js') or new URL('/hello.js') are better. But I'm not sure if there will be boundary conditions in this expression.

@bluwy bluwy added the p2-nice-to-have Not breaking anything but nice to have (priority) label Apr 21, 2022
@poyoho
Copy link
Member

poyoho commented Apr 21, 2022

I'm facing an issue where I can't seem to get my changes to get package paths to resolve while running the dev server. I'm having trouble attaching to the dev server worker or getting any logs to diagnose the problem. I'd appreciate any insight on how to debug this!

because the plugin only run in build mode.

assetImportMetaUrlPlugin(config),

You can refer to workerImportMetaUrl

if (isBuild) {
url = await workerFileToUrl(this, config, file, query)
} else {
url = await fileToUrl(cleanUrl(file), config, this)
url = injectQuery(url, WORKER_FILE_ID)
url = injectQuery(url, `type=${workerType}`)
}

You can also add this logic here and supplementary documentation if you like

@kherock kherock force-pushed the patch-2 branch 2 times, most recently from e833819 to cfb8b39 Compare April 21, 2022 14:50
@kherock
Copy link
Contributor Author

kherock commented Apr 21, 2022

You can refer to workerImportMetaUrl

As far as I can tell, this plugin is for transforming code that uses new Worker(new URL(...)). I could add the same support to that plugin, but it doesn't cover assets.

edit: I've extended support to worker URLs using import.meta.url

@kherock kherock force-pushed the patch-2 branch 5 times, most recently from 4d4d33a to 5c144a6 Compare April 22, 2022 03:35
packages/playground/assets/index.html Outdated Show resolved Hide resolved
packages/playground/assets/__tests__/assets.spec.ts Outdated Show resolved Hide resolved
packages/vite/src/node/plugins/worker.ts Outdated Show resolved Hide resolved
@kherock kherock force-pushed the patch-2 branch 2 times, most recently from 3624717 to cb410a4 Compare April 23, 2022 19:54
@poyoho poyoho mentioned this pull request Apr 24, 2022
9 tasks
@poyoho
Copy link
Member

poyoho commented Apr 24, 2022

fix: #7779

@bluwy bluwy linked an issue Apr 25, 2022 that may be closed by this pull request
7 tasks
poyoho
poyoho previously approved these changes Apr 25, 2022
Copy link
Member

@bluwy bluwy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for bringing this to a great state so far. I have some suggestions and questions below. Feel free to let me know if you have any concerns!

packages/vite/src/node/plugins/assetImportMetaUrl.ts Outdated Show resolved Hide resolved
packages/vite/src/node/plugins/assetImportMetaUrl.ts Outdated Show resolved Hide resolved
packages/vite/src/node/plugins/assetImportMetaUrl.ts Outdated Show resolved Hide resolved
packages/vite/src/node/plugins/workerImportMetaUrl.ts Outdated Show resolved Hide resolved
@kherock
Copy link
Contributor Author

kherock commented May 3, 2022

I'm a bit stuck on this until I can set up my Windows environment to debug the issue with calculating a relative path from the public root. I should have some time soon but would definitely appreciate some help!

All done, this is ready!

@kherock kherock force-pushed the patch-2 branch 2 times, most recently from a301ec3 to 50c19ca Compare May 3, 2022 20:30
@kherock
Copy link
Contributor Author

kherock commented Jun 20, 2022

Following #7837 (comment), I think we should still resolve absolute path like new URL('/path/to/something', import.meta.url) to be from the root instead of the publicDir, so it reflects the resolve logic for glob imports. Not sure if this is resolved in a conversation somewhere, but I don't think the code currently handles this.

The rest looks great though!

@bluwy I do believe this is the case already. The resolver I created uses the project root, and then has a special fallback ??= to allow /... routes to resolve to files in the public dir.

assetResolver ??= config.createResolver({
extensions: [],
mainFields: [],
tryIndex: false,
preferRelative: true
})
file = await assetResolver(url, id)
file ??= url.startsWith('/')
? slash(path.join(config.publicDir, url))
: slash(path.resolve(path.dirname(id), url))

In this way, both new URL('/static/icon.png', import.meta.url) and new URL('/icon.png', import.meta.url) work when /static is the public base dir. The former should ideally generate a warning, but I don't want to copy-paste this large chunk of code into two plugins - I'd appreciate if someone else could do that refactoring 😅

// check if public dir is inside root dir
const publicDir = normalizePath(server.config.publicDir)
const rootDir = normalizePath(server.config.root)
if (publicDir.startsWith(rootDir)) {
const publicPath = `${publicDir.slice(rootDir.length)}/`
// warn explicit public paths
if (url.startsWith(publicPath)) {
let warning: string
if (isImportRequest(url)) {
const rawUrl = removeImportQuery(url)
warning =
'Assets in public cannot be imported from JavaScript.\n' +
`Instead of ${colors.cyan(
rawUrl
)}, put the file in the src directory, and use ${colors.cyan(
rawUrl.replace(publicPath, '/src/')
)} instead.`
} else {
warning =
`files in the public directory are served at the root path.\n` +
`Instead of ${colors.cyan(url)}, use ${colors.cyan(
url.replace(publicPath, '/')
)}.`
}
logger.warn(colors.yellow(warning))
}
}

@kherock
Copy link
Contributor Author

kherock commented Aug 10, 2022

@bluwy anything I can do here? I should be able to find time to rebase this soon.

This tests existing behavior for obtaining an asset's URL from the public base path.
This test fails because the worker plugin's renderChunk hook runs its
import.meta.url transformation after Rollup already has transformed it
with importMeta.renderFinalMechanism.
@kherock
Copy link
Contributor Author

kherock commented Aug 26, 2022

This is ready again, would really like to see this released in the near future!

Copy link
Member

@bluwy bluwy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the lack of response @kherock. My brain wasn't up for recalling all the context of this PR until now 😦 Thanks for the reply previously, that make sense to me!

This LGTM. I think we can bring this in 3.1

@bluwy bluwy added this to the 3.1 milestone Aug 26, 2022
@kherock
Copy link
Contributor Author

kherock commented Aug 26, 2022

Are the macOS tests flaky in CI? Neither of the last two runs seem to be related to these changes

@bluwy
Copy link
Member

bluwy commented Aug 26, 2022

Looks like forth times a charm. I hope this isn't caused by this PR, plus the test failure logs seem unrelated.

@kherock
Copy link
Contributor Author

kherock commented Aug 29, 2022

@poyoho @bluwy ETA on having this merged? I'd like to avoid spending more time rebasing this one if it can be helped 😅

@patak-dev patak-dev modified the milestones: 3.1, 3.2 Sep 2, 2022
@bluwy
Copy link
Member

bluwy commented Sep 4, 2022

@kherock I think this is a great feature, but we'd need a team meeting to confirm it. It's planned for 3.2 now, but if there's any merge conflicts in the future I can help with resolving it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
p2-nice-to-have Not breaking anything but nice to have (priority)
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

”document“ should not appear in the Worker. Support node_modules when resolving worker urls
6 participants