Skip to content

Commit

Permalink
feat(plugin): add reverse proxy support (#318)
Browse files Browse the repository at this point in the history
Use import paths relative to the domain rather than the filesystem. This
allows reverse proxies to work, including those using a subfolder.
  • Loading branch information
mkilpatrick committed Jun 12, 2023
1 parent c7d9741 commit 68cd81d
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 10 deletions.
51 changes: 46 additions & 5 deletions packages/pages/src/common/src/template/hydration.ts
Expand Up @@ -6,6 +6,41 @@ import { TemplateRenderProps } from "./types.js";
* Imports the custom hydration template and entrypoint template as modules and calls
* the render function.
*
* Dev has a separate function than {@link getHydrationTemplate} due to how Vite messes
* with the import.meta.url.
*
* @param clientRenderTemplatePath the path to the custom client render template
* @param templateModulePath the path to the template module
* @param props the {@link TemplateRenderProps}
* @returns the HTML as a string
*/
export const getHydrationTemplateDev = (
clientRenderTemplatePath: string,
templateModulePath: string,
props: TemplateRenderProps
): string => {
return `
import {default as Component} from "${convertToPosixPath(
templateModulePath
)}";
import {render} from "${convertToPosixPath(clientRenderTemplatePath)}";
render(
{
Page: Component,
pageProps: ${JSON.stringify(props)},
}
);
`;
};

/**
* Imports the custom hydration template and entrypoint template as modules and calls
* the render function.
*
* The component paths need to be resolved to the current domain's relative path in order
* to support reverse proxies.
*
* @param clientRenderTemplatePath the path to the custom client render template
* @param templateModulePath the path to the template module
* @param props the {@link TemplateRenderProps}
Expand All @@ -17,13 +52,19 @@ export const getHydrationTemplate = (
props: TemplateRenderProps
): string => {
return `
import {default as Component} from "${convertToPosixPath(
const componentUrl = import.meta.resolve("./${convertToPosixPath(
templateModulePath
)}";
import {render} from "${convertToPosixPath(clientRenderTemplatePath)}";
render(
)}");
const renderUrl = import.meta.resolve("./${convertToPosixPath(
clientRenderTemplatePath
)}");
const component = await import(componentUrl);
const render = await import(renderUrl);
render.render(
{
Page: Component,
Page: component.default,
pageProps: ${JSON.stringify(props)},
}
);
Expand Down
4 changes: 2 additions & 2 deletions packages/pages/src/dev/server/middleware/sendAppHTML.ts
Expand Up @@ -10,7 +10,7 @@ import { getContentType } from "./getContentType.js";
import { getGlobalClientServerRenderTemplates } from "../../../common/src/template/internal/getTemplateFilepaths.js";
import { ProjectStructure } from "../../../common/src/project/structure.js";
import {
getHydrationTemplate,
getHydrationTemplateDev,
getServerTemplateDev,
} from "../../../common/src/template/hydration.js";

Expand Down Expand Up @@ -52,7 +52,7 @@ export default async function sendAppHTML(
? templateModuleInternal.getHeadConfig(props)
: undefined;

const clientHydrationString = getHydrationTemplate(
const clientHydrationString = getHydrationTemplateDev(
clientServerRenderTemplates.clientRenderTemplatePath,
templateModuleInternal.path,
props
Expand Down
13 changes: 13 additions & 0 deletions packages/pages/src/vite-plugin/build/build.ts
Expand Up @@ -46,6 +46,19 @@ export const build = (projectStructure: ProjectStructure): Plugin => {
},
},
define: processEnvVariables(projectStructure.envVarPrefix),
experimental: {
renderBuiltUrl(filename, { hostType }) {
// Assets are returned with a leading slash for some reason. This adjusts the
// paths to be relative for reverse proxy support.
if (hostType === "js") {
if (filename.at(0) === "/") {
return filename.substring(1);
}
return filename;
}
return { relative: true };
},
},
};
},
buildStart: buildStart(projectStructure),
Expand Down
Expand Up @@ -59,7 +59,6 @@ export interface PluginRenderTemplates {
export const getPluginRenderTemplates = async (
manifest: Manifest
): Promise<PluginRenderTemplates> => {
const clientRenderPath = pathLib.join("..", manifest.renderPaths._client);
const serverRenderPath = manifest.renderPaths._server.replace("assets", "..");

const serverRenderTemplateModule = (await import(
Expand All @@ -68,7 +67,7 @@ export const getPluginRenderTemplates = async (

return {
server: serverRenderTemplateModule,
client: clientRenderPath,
client: manifest.renderPaths._client,
};
};

Expand Down
Expand Up @@ -41,7 +41,7 @@ export const reactWrapper = async <T extends TemplateRenderProps>(
if (hydrate) {
clientHydrationString = getHydrationTemplate(
pluginRenderTemplates.client,
path.join("..", "assets", templateModuleInternal.path.replace("..", "")),
path.join("assets", templateModuleInternal.path.replace("..", "")),
props
);
}
Expand Down

0 comments on commit 68cd81d

Please sign in to comment.