Replies: 4 comments
|
Now I am using this code as a workaround, manually transform it to an absolute path ctx.body = htmlStr.replace(
/<script ([^>]* |)src="([^"]+)"/g,
(...args) => `<script ${args[1]}src="${path.resolve(path.parse(htmlFilePath).dir, args[2])}"`,
); |
|
I'm surprised that there doesn't seem to be a proper way to do this. @dislido did you find any other solution besides manually replacing the links? I also need this for my processed HTML import plugin. |
|
@ThinkingPlanely Now I am using vite@8.2.2, I still have no way to deal with this. The only progress is that I have discovered that I can use an absolute path based on packages/server/index.ts const vite = await createServer({
root: path.resolve(projectRoot, './packages/client'),
// ...packages/client/pages/test/index.html <script type="module" src="/pages/test/index.ts"></script>I still can't avoid manual replacement while using relative paths |
|
I think the key issue is that Since your HTML is generated by A cleaner workaround than regex-replacing the script tag is to pass Vite the HTML file path (or a URL that correctly maps to that file) when calling For example, if you already know the HTML file selected by const html = await fs.promises.readFile(htmlFilePath, 'utf8');
const transformed = await vite.transformIndexHtml(
fileURLToPath(pathToFileURL(htmlFilePath)),
html
);
ctx.type = 'text/html';
ctx.body = transformed;However, if your rendered HTML contains application-specific placeholders and is not actually read from disk at that point, I'd recommend keeping the mapping between the request URL and the source HTML file in your render middleware: const htmlFilePath = getHtmlFileForRequest(ctx.path);
let html = await fs.promises.readFile(htmlFilePath, 'utf8');
// Replace your renderSlot placeholders here
html = renderHtml(html, data);
// Give Vite the URL corresponding to the actual source HTML file
html = await vite.transformIndexHtml(
ctx.path,
html,
htmlFilePath
);
ctx.type = 'text/html';
ctx.body = html;The important part is that the transformation needs to be associated with the real HTML entry, not just the generated request URL. Another approach, which I think is simpler for this project structure, is to make the paths absolute from Vite's root: <script type="module" src="/pages/test/index.ts"></script>and configure: const vite = await createServer({
root: path.resolve(projectRoot, './packages/client'),
server: {
middlewareMode: true,
},
appType: 'custom',
});Then Vite can resolve the module directly from its configured root without having to infer which physical HTML file So the underlying issue isn't really HMR itself — it's that your server is doing custom HTML rendering while Vite is being asked to perform an HTML transformation without knowing the source HTML entry. If you keep relative paths, you'll need to preserve/pass that HTML-file context somewhere in your rendering pipeline. |
Uh oh!
There was an error while loading. Please reload this page.
I'm using koa to build my node server, and using
ViteDevServerin development mode. The main codes are as follows:My
vite.config.ts:My html files:
renderSlot:${name}will be replaced inrenderMiddlewareWhen I run 'vite build', the
<script type="module" src="./index.tsx"></script>will be transformed to<script type="module" crossorigin src="/build/index-{hash}.js"></script>, but it will keepsrc="./index.tsx"inViteDevServerbecause vite can't get the html file path by the request url. Is there a way to tellViteDevServerhow to transform it?All reactions