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

[Blocked] Fix handling of public resources with subpath #2348

Closed
wants to merge 1 commit into from

Conversation

tadeuzagallo
Copy link
Contributor

Changes

  • Change the Vite configuration to account for the subpath, this fixes the handing for resources in the public folder.
  • Change vite-plugin-build-html to prefix URLs in HTML attributes such as img src to match the behavior of Vite. This keeps the behavior consistent between astro dev and astro build.

Testing

I added tests to both the dev routing and preview routing. Notice that there are 5 skipped tests in the preview routing due to an existing bug in the routing, I'll try to tackle that next.

Docs

Bug fix, no changes needed to the docs

@changeset-bot
Copy link

changeset-bot bot commented Jan 8, 2022

🦋 Changeset detected

Latest commit: 4b5a823

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
astro Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions bot added pkg: astro Related to the core `astro` package (scope) test labels Jan 8, 2022
@netlify
Copy link

netlify bot commented Jan 9, 2022

✔️ Deploy Preview for astro-www ready!

🔨 Explore the source changes: 9ed4d72

🔍 Inspect the deploy log: https://app.netlify.com/sites/astro-www/deploys/61dc94c68c6aa000084f6ed9

😎 Browse the preview: https://deploy-preview-2348--astro-www.netlify.app

@netlify
Copy link

netlify bot commented Jan 9, 2022

✔️ Deploy Preview for astro-docs-2 ready!

🔨 Explore the source changes: 9ed4d72

🔍 Inspect the deploy log: https://app.netlify.com/sites/astro-docs-2/deploys/61dc94c607c00f00086fc097

😎 Browse the preview: https://deploy-preview-2348--astro-docs-2.netlify.app

@FredKSchott
Copy link
Member

Nice! cc @jonathantneal to take a look

@jonathantneal jonathantneal self-assigned this Jan 10, 2022
@jonathantneal
Copy link
Contributor

@FredKSchott ✅ Oh yea. Thank you, @tadeuzagallo! I’m hoping to have this one fast follow some Astro Preview fixes. :)

@matthewp
Copy link
Contributor

matthewp commented Jan 10, 2022

Can you clarify what problem this fixes? The problem it appears to me is that you are writing <img src="/images/penguin.png" /> and you want it to be transformed into <img src="/blog/images/penguin.png" />.

I don't think we should be rewriting every link like this because it will not work in SSR. We are actually moving away from rewriting HTML at all.

The way to get your subpath prefixed is to use Astro.site like so:

<img src={new URL('./images/penguin.png', Astro.site).pathname} />

Or just include /blog in your URL:

<img src="/blog/images/penguin.png" />

@tadeuzagallo
Copy link
Contributor Author

tadeuzagallo commented Jan 10, 2022

Sorry, I explained in more depth in the discord channel. Here's the current issue with image loading:

Let's assume we have the subpath set to /blog/ and that there's there's an image in public/penguin.png. In the current state of things you can't load /blog/penguin.png, only /penguin.png.

The way I tried to fix this was by passing the subpath configuration down to Vite through the base configuration option: https://vitejs.dev/config/#base. The automatic prefixing behavior that I implemented was to mimic Vite's behavior as described here: https://vitejs.dev/guide/build.html#public-base-path

return;
}
pathname = pathname.substr(this.devRoot.length) || '';
req.url = pathname.startsWith('/') ? pathname : '/' + pathname;
Copy link
Member

@FredKSchott FredKSchott Jan 10, 2022

Choose a reason for hiding this comment

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

if we go this route, make sure that no one is using originalUrl internally that needs this new req.url instead https://expressjs.com/en/api.html#req.originalUrl

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll do some grepping.

@tadeuzagallo
Copy link
Contributor Author

I removed the unnecessary regexp tests and changes to the .astro pages of the test fixtures.

@jonathantneal
Copy link
Contributor

jonathantneal commented Jan 10, 2022

Does this patch redirect subpath requests to the root? So that /blog/twitter.png is treated like /twitter.png?

That is a very clever patch. It will be more fragile, as it relies on incorrect behavior throughout the rest of the stack.

If this occurs before other plugins, including user plugins, then I could imagine other unintended side-effects, from plugins that intercept URLs like /__VITE__SOMETHING/asset.png.


let pathname = req.url || '/';
if (!pathname.startsWith(this.devRoot)) {
this.renderError(req, res, next);
Copy link
Contributor

@jonathantneal jonathantneal Jan 10, 2022

Choose a reason for hiding this comment

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

Could this next() instead? I understand (multiple) plugins create unique URLs like /__VITE_FILE__/something, and my concern is that this would error them out before they had a chance to intercept the URL.

Ref: https://vitejs.dev/guide/api-plugin.html#conventions

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My concern with that is that /image.png would still work in dev, but break in production, which could lead to bugs.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes. We don’t want either scenario, I think. We can’t predict what other plugins will do, but plugins following the documented conventions would probably get caught by this plugin. 😅

IMHO, this needs to get fixed higher up, wherever the problem originates.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah we shouldn't ban all non-root pathnames, as Vite is going to send some /@fs and /.vite paths. I wouldn't want to special-case them either.

Copy link
Contributor

@matthewp matthewp Jan 11, 2022

Choose a reason for hiding this comment

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

It would be ideal to ban /image.png but shouldn't we get this fix in first (using next() here), as it improves subpath support, and then do the ideal fix afterwards? The ideal fix doesn't seem obvious to me.

Copy link
Contributor

Choose a reason for hiding this comment

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

If that is the case, then the ideal fix may be the necessary fix.

Copy link
Member

Choose a reason for hiding this comment

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

Backing up here: have we confirmed that just setting base in the dev createVite() call doesn't fix this issue, without all of the other changes in this PR? I just tried that and it seems to accomplish our goals here: on the docs site /main.css becomes a 404 and /docs/main.css becomes a 200.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you set the base in vite, when using the astro dev, it will transform all the img src's and the link as part of transformIndexHtml to automatically prefix them, which I believe we agreed is an undesirable behavior (and at the very least doesn't match astro build). I created a very simple test repo which I believe illustrates all the issues with just a couple css files and an image: http://github.com/tadeuzagallo/blog

Copy link
Member

Choose a reason for hiding this comment

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

It could be worth playing around with transformIndexHTML then. It's function signature may have been designed to solve for this: https://github.com/vitejs/vite/blob/647168b2b44b82b1a1cbd8e639f74ddf52a5d5cd/packages/vite/src/node/server/index.ts#L198

  transformIndexHtml(
    url: string,
    html: string,
    originalUrl?: string
  ): Promise<string>

Somewhere else in the codebase, we run it like this:


	// run transformIndexHtml() in dev to run Vite dev transformations
	if (mode === 'development' && !astroConfig.buildOptions.experimentalStaticBuild) {
		const relativeURL = filePath.href.replace(astroConfig.projectRoot.href, '/');
		html = await viteServer.transformIndexHtml(relativeURL, html, pathname);
	}

so maybe the dev call to this function just needs to change the first or third argument to handle this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I could be wrong, I'll dig some more, but from what I read of the code it's purely based on viteConfig.base. Changing the base around the call in the hackiest way did "fix" the behavior:

const base = viteServer.config.base;
viteServer.config.base = '/';
html = await viteServer.transformIndexHtml(relativeURL, html, pathname);
viteServer.config.base = base;

@mateluzm11

This comment has been minimized.

@wbern
Copy link

wbern commented Jan 17, 2022

I'm trying to deploy to a site that requires me to deploy to a sub path, I assume this PR fixes that? I tried doing manual copy commands but the dynamic vendor script still tries to load things without the appended sub path.

@tadeuzagallo
Copy link
Contributor Author

@wbern when you say deploy, are you talking about astro build? This only affects dev.

@wbern
Copy link

wbern commented Jan 17, 2022

@wbern when you say deploy, are you talking about astro build? This only affects dev.

Yes, build. Ok, because the siteOptions don't seem to help my case for the build.

@tadeuzagallo
Copy link
Contributor Author

@wbern in all my tests astro build worked fine with subpaths. If you have a repro or some more info it might be a good idea to file an issue.

@wbern
Copy link

wbern commented Jan 20, 2022

@wbern in all my tests astro build worked fine with subpaths. If you have a repro or some more info it might be a good idea to file an issue.

I have opened it here, thank you for the advice. #2434

@jonathantneal
Copy link
Contributor

This PR has been held up because we know we shouldn’t (and probably can’t) block requests outside of the subpath. However, it looks like there’s a problem in the current solution if it doesn’t and those requests get passed along.

@jonathantneal
Copy link
Contributor

@tadeuzagallo, I think you could either refactor this with an approach that does not block requests, or you could do that in a separate PR, if this one has lingered too long and some of the blocking information is getting lost.

@jonathantneal jonathantneal changed the title Fix handling of public resources with subpath [Blocked] Fix handling of public resources with subpath Jan 25, 2022
@jonathantneal
Copy link
Contributor

jonathantneal commented Feb 7, 2022

This may have been handled in #2494, and we’ll need to revisit this if it comes back up.

This was a tough one. Thank you for all of your hard effort, @tadeuzagallo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg: astro Related to the core `astro` package (scope)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants