Skip to content

Commit d49e3fb

Browse files
saurabhdawarepoyohopatak-dev
authored
fix: inline js and css paths for virtual html (#7993)
Co-authored-by: yoho <panyoho@gmail.com> Co-authored-by: patak-dev <matias.capeletto@gmail.com>
1 parent f3d15f1 commit d49e3fb

File tree

2 files changed

+69
-19
lines changed

2 files changed

+69
-19
lines changed

packages/playground/ssr-html/server.js

+27-4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ const DYNAMIC_SCRIPTS = `
1414
<script type="module" src="/src/app.js"></script>
1515
`
1616

17+
const DYNAMIC_STYLES = `
18+
<style>
19+
h1 {
20+
background-color: blue;
21+
}
22+
</style>
23+
`
24+
1725
async function createServer(
1826
root = process.cwd(),
1927
isProd = process.env.NODE_ENV === 'production'
@@ -42,15 +50,30 @@ async function createServer(
4250
// use vite's connect instance as middleware
4351
app.use(vite.middlewares)
4452

45-
app.use('*', async (req, res) => {
53+
app.use('*', async (req, res, next) => {
4654
try {
4755
let [url] = req.originalUrl.split('?')
4856
if (url.endsWith('/')) url += 'index.html'
4957

58+
if (url.startsWith('/favicon.ico')) {
59+
return res.status(404).end('404')
60+
}
61+
if (url.startsWith('/@id/__x00__')) {
62+
return next()
63+
}
64+
5065
const htmlLoc = resolve(`.${url}`)
51-
let html = fs.readFileSync(htmlLoc, 'utf8')
52-
html = html.replace('</body>', `${DYNAMIC_SCRIPTS}</body>`)
53-
html = await vite.transformIndexHtml(url, html)
66+
let template = fs.readFileSync(htmlLoc, 'utf-8')
67+
68+
template = template.replace(
69+
'</body>',
70+
`${DYNAMIC_SCRIPTS}${DYNAMIC_STYLES}</body>`
71+
)
72+
73+
// Force calling transformIndexHtml with url === '/', to simulate
74+
// usage by ecosystem that was recommended in the SSR documentation
75+
// as `const url = req.originalUrl`
76+
const html = await vite.transformIndexHtml('/', template)
5477

5578
res.status(200).set({ 'Content-Type': 'text/html' }).end(html)
5679
} catch (e) {

packages/vite/src/node/server/middlewares/indexHtml.ts

+42-15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import fs from 'fs'
22
import path from 'path'
33
import MagicString from 'magic-string'
4+
import type { SourceMapInput } from 'rollup'
45
import type { AttributeNode, ElementNode, TextNode } from '@vue/compiler-dom'
56
import { NodeTypes } from '@vue/compiler-dom'
67
import type { Connect } from 'types/connect'
@@ -15,7 +16,12 @@ import {
1516
} from '../../plugins/html'
1617
import type { ResolvedConfig, ViteDevServer } from '../..'
1718
import { send } from '../send'
18-
import { CLIENT_PUBLIC_PATH, FS_PREFIX } from '../../constants'
19+
import {
20+
CLIENT_PUBLIC_PATH,
21+
FS_PREFIX,
22+
VALID_ID_PREFIX,
23+
NULL_BYTE_PLACEHOLDER
24+
} from '../../constants'
1925
import {
2026
cleanUrl,
2127
fsPathFromId,
@@ -108,32 +114,53 @@ const devHtmlHook: IndexHtmlTransformHook = async (
108114
const { config, moduleGraph, watcher } = server!
109115
const base = config.base || '/'
110116

117+
let proxyModulePath: string
118+
let proxyModuleUrl: string
119+
120+
const trailingSlash = htmlPath.endsWith('/')
121+
if (!trailingSlash && fs.existsSync(filename)) {
122+
proxyModulePath = htmlPath
123+
proxyModuleUrl = base + htmlPath.slice(1)
124+
} else {
125+
// There are users of vite.transformIndexHtml calling it with url '/'
126+
// for SSR integrations #7993, filename is root for this case
127+
// A user may also use a valid name for a virtual html file
128+
// Mark the path as virtual in both cases so sourcemaps aren't processed
129+
// and ids are properly handled
130+
const validPath = `${htmlPath}${trailingSlash ? 'index.html' : ''}`
131+
proxyModulePath = `\0${validPath}`
132+
proxyModuleUrl = `${VALID_ID_PREFIX}${NULL_BYTE_PLACEHOLDER}${validPath}`
133+
}
134+
111135
const s = new MagicString(html)
112136
let inlineModuleIndex = -1
113-
const filePath = cleanUrl(htmlPath)
137+
const proxyCacheUrl = cleanUrl(proxyModulePath).replace(
138+
normalizePath(config.root),
139+
''
140+
)
114141
const styleUrl: AssetNode[] = []
115142

116143
const addInlineModule = (node: ElementNode, ext: 'js') => {
117144
inlineModuleIndex++
118145

119-
const url = filePath.replace(normalizePath(config.root), '')
120-
121146
const contentNode = node.children[0] as TextNode
122147

123148
const code = contentNode.content
124-
const map = new MagicString(html)
125-
.snip(contentNode.loc.start.offset, contentNode.loc.end.offset)
126-
.generateMap({ hires: true })
127-
map.sources = [filename]
128-
map.file = filename
149+
150+
let map: SourceMapInput | undefined
151+
if (!proxyModulePath.startsWith('\0')) {
152+
map = new MagicString(html)
153+
.snip(contentNode.loc.start.offset, contentNode.loc.end.offset)
154+
.generateMap({ hires: true })
155+
map.sources = [filename]
156+
map.file = filename
157+
}
129158

130159
// add HTML Proxy to Map
131-
addToHTMLProxyCache(config, url, inlineModuleIndex, { code, map })
160+
addToHTMLProxyCache(config, proxyCacheUrl, inlineModuleIndex, { code, map })
132161

133162
// inline js module. convert to src="proxy"
134-
const modulePath = `${
135-
config.base + htmlPath.slice(1)
136-
}?html-proxy&index=${inlineModuleIndex}.${ext}`
163+
const modulePath = `${proxyModuleUrl}?html-proxy&index=${inlineModuleIndex}.${ext}`
137164

138165
// invalidate the module so the newly cached contents will be served
139166
const module = server?.moduleGraph.getModuleById(modulePath)
@@ -190,13 +217,13 @@ const devHtmlHook: IndexHtmlTransformHook = async (
190217

191218
await Promise.all(
192219
styleUrl.map(async ({ start, end, code }, index) => {
193-
const url = filename + `?html-proxy&${index}.css`
220+
const url = `${proxyModulePath}?html-proxy&index=${index}.css`
194221

195222
// ensure module in graph after successful load
196223
const mod = await moduleGraph.ensureEntryFromUrl(url, false)
197224
ensureWatchedFile(watcher, mod.file, config.root)
198225

199-
const result = await server!.pluginContainer.transform(code, url)
226+
const result = await server!.pluginContainer.transform(code, mod.id!)
200227
s.overwrite(start, end, result?.code || '')
201228
})
202229
)

0 commit comments

Comments
 (0)