Skip to content

Commit

Permalink
fix(dev): rewrite importee path at html files at spa fallback (#3239)
Browse files Browse the repository at this point in the history
  • Loading branch information
underfin authored May 10, 2021
1 parent 24178b0 commit 13d41d8
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 52 deletions.
31 changes: 10 additions & 21 deletions packages/vite/src/node/plugins/html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,10 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin {
if (id.endsWith('.html')) {
const publicPath = `/${slash(path.relative(config.root, id))}`
// pre-transform
html = await applyHtmlTransforms(html, publicPath, id, preHooks)
html = await applyHtmlTransforms(html, preHooks, {
path: publicPath,
filename: id
})

let js = ''
const s = new MagicString(html)
Expand Down Expand Up @@ -374,15 +377,12 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin {
}

const shortEmitName = path.posix.relative(config.root, id)
result = await applyHtmlTransforms(
result,
'/' + shortEmitName,
id,
postHooks,
undefined,
result = await applyHtmlTransforms(result, postHooks, {
path: '/' + shortEmitName,
filename: id,
bundle,
chunk
)
})

this.emitFile({
type: 'asset',
Expand Down Expand Up @@ -424,6 +424,7 @@ export interface IndexHtmlTransformContext {
server?: ViteDevServer
bundle?: OutputBundle
chunk?: OutputChunk
originalUrl?: string
}

export type IndexHtmlTransformHook = (
Expand Down Expand Up @@ -462,26 +463,14 @@ export function resolveHtmlTransforms(

export async function applyHtmlTransforms(
html: string,
path: string,
filename: string,
hooks: IndexHtmlTransformHook[],
server?: ViteDevServer,
bundle?: OutputBundle,
chunk?: OutputChunk
ctx: IndexHtmlTransformContext
): Promise<string> {
const headTags: HtmlTagDescriptor[] = []
const headPrependTags: HtmlTagDescriptor[] = []
const bodyTags: HtmlTagDescriptor[] = []
const bodyPrependTags: HtmlTagDescriptor[] = []

const ctx: IndexHtmlTransformContext = {
path,
filename,
server,
bundle,
chunk
}

for (const hook of hooks) {
const res = await hook(html, ctx)
if (!res) {
Expand Down
6 changes: 5 additions & 1 deletion packages/vite/src/node/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,11 @@ export interface ViteDevServer {
/**
* Apply vite built-in HTML transforms and any plugin HTML transforms.
*/
transformIndexHtml(url: string, html: string): Promise<string>
transformIndexHtml(
url: string,
html: string,
originalUrl?: string
): Promise<string>
/**
* Util for transforming a file with esbuild.
* Can be useful for certain plugins.
Expand Down
79 changes: 49 additions & 30 deletions packages/vite/src/node/server/middlewares/indexHtml.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import fs from 'fs'
import path from 'path'
import MagicString from 'magic-string'
import { NodeTypes } from '@vue/compiler-dom'
import { AttributeNode, NodeTypes } from '@vue/compiler-dom'
import { Connect } from 'types/connect'
import {
applyHtmlTransforms,
Expand All @@ -10,25 +10,24 @@ import {
resolveHtmlTransforms,
traverseHtml
} from '../../plugins/html'
import { ViteDevServer } from '../..'
import { ResolvedConfig, ViteDevServer } from '../..'
import { send } from '../send'
import { CLIENT_PUBLIC_PATH, FS_PREFIX } from '../../constants'
import { cleanUrl, fsPathFromId } from '../../utils'
import { assetAttrsConfig } from '../../plugins/html'

export function createDevHtmlTransformFn(
server: ViteDevServer
): (url: string, html: string) => Promise<string> {
): (url: string, html: string, originalUrl: string) => Promise<string> {
const [preHooks, postHooks] = resolveHtmlTransforms(server.config.plugins)

return (url: string, html: string): Promise<string> => {
return applyHtmlTransforms(
html,
url,
getHtmlFilename(url, server),
[...preHooks, devHtmlHook, ...postHooks],
server
)
return (url: string, html: string, originalUrl: string): Promise<string> => {
return applyHtmlTransforms(html, [...preHooks, devHtmlHook, ...postHooks], {
path: url,
filename: getHtmlFilename(url, server),
server,
originalUrl
})
}
}

Expand All @@ -41,9 +40,44 @@ function getHtmlFilename(url: string, server: ViteDevServer) {
}

const startsWithSingleSlashRE = /^\/(?!\/)/
const processNodeUrl = (
node: AttributeNode,
s: MagicString,
config: ResolvedConfig,
htmlPath: string,
originalUrl?: string
) => {
const url = node.value?.content || ''
if (startsWithSingleSlashRE.test(url)) {
// prefix with base
s.overwrite(
node.value!.loc.start.offset,
node.value!.loc.end.offset,
`"${config.base + url.slice(1)}"`
)
} else if (
url.startsWith('.') &&
originalUrl &&
originalUrl !== '/' &&
htmlPath === '/index.html'
) {
// #3230 if some request url (localhost:3000/a/b) return to fallback html, the relative assets
// path will add `/a/` prefix, it will caused 404.
// rewrite before `./index.js` -> `localhost:3000/a/index.js`.
// rewrite after `../index.js` -> `localhost:3000/index.js`.
s.overwrite(
node.value!.loc.start.offset,
node.value!.loc.end.offset,
`"${path.posix.join(
path.posix.relative(originalUrl, '/'),
url.slice(1)
)}"`
)
}
}
const devHtmlHook: IndexHtmlTransformHook = async (
html,
{ path: htmlPath, server }
{ path: htmlPath, server, originalUrl }
) => {
// TODO: solve this design issue
// Optional chain expressions can return undefined by design
Expand All @@ -67,15 +101,7 @@ const devHtmlHook: IndexHtmlTransformHook = async (
}

if (src) {
const url = src.value?.content || ''
if (startsWithSingleSlashRE.test(url)) {
// prefix with base
s.overwrite(
src.value!.loc.start.offset,
src.value!.loc.end.offset,
`"${config.base + url.slice(1)}"`
)
}
processNodeUrl(src, s, config, htmlPath, originalUrl)
} else if (isModule) {
// inline js module. convert to src="proxy"
s.overwrite(
Expand All @@ -97,14 +123,7 @@ const devHtmlHook: IndexHtmlTransformHook = async (
p.value &&
assetAttrs.includes(p.name)
) {
const url = p.value.content || ''
if (startsWithSingleSlashRE.test(url)) {
s.overwrite(
p.value.loc.start.offset,
p.value.loc.end.offset,
`"${config.base + url.slice(1)}"`
)
}
processNodeUrl(p, s, config, htmlPath, originalUrl)
}
}
}
Expand Down Expand Up @@ -139,7 +158,7 @@ export function indexHtmlMiddleware(
if (fs.existsSync(filename)) {
try {
let html = fs.readFileSync(filename, 'utf-8')
html = await server.transformIndexHtml(url, html)
html = await server.transformIndexHtml(url, html, req.originalUrl)
return send(req, res, html, 'html')
} catch (e) {
return next(e)
Expand Down

0 comments on commit 13d41d8

Please sign in to comment.