Skip to content

Commit

Permalink
feat: add ViteDevServer.transformIndexHtml method for ssr
Browse files Browse the repository at this point in the history
close #1745
  • Loading branch information
yyx990803 committed Jan 29, 2021
1 parent e438802 commit dbe1f4a
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 39 deletions.
16 changes: 15 additions & 1 deletion packages/playground/ssr/__tests__/ssr.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getColor, isBuild, untilUpdated } from '../../testUtils'
import { editFile, getColor, isBuild, untilUpdated } from '../../testUtils'
import { port } from './serve'
import fetch from 'node-fetch'

Expand Down Expand Up @@ -62,6 +62,13 @@ describe('Vue', () => {
await page.click('button')
expect(await page.textContent('button')).toBe('1')
})

test('hmr', async () => {
editFile('src/vue/Async.vue', (code) =>
code.replace('Hello from Vue', 'changed')
)
await untilUpdated(() => page.textContent('h1'), 'changed')
})
})

describe('React', () => {
Expand All @@ -82,4 +89,11 @@ describe('React', () => {
)
).toBe(true)
})

test('hmr', async () => {
editFile('src/react/Child.jsx', (code) =>
code.replace('Hello from React', 'changed')
)
await untilUpdated(() => page.textContent('h1'), 'changed')
})
})
26 changes: 10 additions & 16 deletions packages/playground/ssr/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,12 @@ async function createServer(
require('./dist/client/ssr-manifest.json')
: {}

function getIndexTemplate(url) {
function getIndexTemplate() {
if (isProd) {
return indexProd
}

// TODO handle plugin indexHtmlTransforms?
const reactPreamble = url.startsWith('/react')
? `<script type="module">${
require('@vitejs/plugin-react-refresh').preambleCode
}</script>`
: ''

// during dev, inject vite client + always read fresh index.html
return (
`<script type="module" src="/@vite/client"></script>` +
reactPreamble +
fs.readFileSync(toAbsolute('index.html'), 'utf-8')
)
return fs.readFileSync(toAbsolute('index.html'), 'utf-8')
}

const app = express()
Expand Down Expand Up @@ -67,16 +55,22 @@ async function createServer(

app.use('*', async (req, res, next) => {
try {
const url = req.originalUrl
let template = getIndexTemplate()
if (!isProd) {
template = await vite.transformIndexHtml(url, template)
}

const { render } = isProd
? // @ts-ignore
require('./dist/server/entry-server.js')
: await vite.ssrLoadModule('/src/entry-server.ts')

const [appHtml, preloadLinks] = await render(req.originalUrl, manifest)
const [appHtml, preloadLinks] = await render(url, manifest)

const html = `
${preloadLinks}
${getIndexTemplate(req.originalUrl).replace(`<!--ssr-outlet-->`, appHtml)}
${template.replace(`<!--ssr-outlet-->`, appHtml)}
`

res.status(200).set({ 'Content-Type': 'text/html' }).end(html)
Expand Down
14 changes: 12 additions & 2 deletions packages/vite/src/node/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ import { createWebSocketServer, WebSocketServer } from '../server/ws'
import { baseMiddleware } from './middlewares/base'
import { proxyMiddleware, ProxyOptions } from './middlewares/proxy'
import { transformMiddleware } from './middlewares/transform'
import { indexHtmlMiddleware } from './middlewares/indexHtml'
import {
createDevHtmlTransformFn,
indexHtmlMiddleware
} from './middlewares/indexHtml'
import history from 'connect-history-api-fallback'
import {
serveRawFsMiddleware,
Expand Down Expand Up @@ -189,6 +192,10 @@ export interface ViteDevServer {
url: string,
options?: TransformOptions
): Promise<TransformResult | null>
/**
* Apply vite built-in HTML transforms and any plugin HTML transforms.
*/
transformIndexHtml(url: string, html: string): Promise<string>
/**
* Util for transforming a file with esbuild.
* Can be useful for certain plugins.
Expand Down Expand Up @@ -299,6 +306,7 @@ export async function createServer(
transformRequest(url, options) {
return transformRequest(url, server, options)
},
transformIndexHtml: null as any,
ssrLoadModule(url, options) {
if (!server._ssrExternals) {
server._ssrExternals = resolveSSRExternal(config)
Expand Down Expand Up @@ -329,6 +337,8 @@ export async function createServer(
_pendingReload: null
}

server.transformIndexHtml = createDevHtmlTransformFn(server)

process.once('SIGTERM', async () => {
try {
await server.close()
Expand Down Expand Up @@ -438,7 +448,7 @@ export async function createServer(

if (!middlewareMode) {
// transform index.html
middlewares.use(indexHtmlMiddleware(server, plugins))
middlewares.use(indexHtmlMiddleware(server))
// handle 404s
middlewares.use((_, res) => {
res.statusCode = 404
Expand Down
46 changes: 26 additions & 20 deletions packages/vite/src/node/server/middlewares/indexHtml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import path from 'path'
import MagicString from 'magic-string'
import { NodeTypes } from '@vue/compiler-dom'
import { Connect } from 'types/connect'
import { Plugin } from '../../plugin'
import {
applyHtmlTransforms,
getScriptInfo,
Expand All @@ -14,9 +13,31 @@ import {
import { ViteDevServer } from '../..'
import { send } from '../send'
import { CLIENT_PUBLIC_PATH, FS_PREFIX } from '../../constants'
import { cleanUrl } from '../../utils'
import { cleanUrl, fsPathFromId } from '../../utils'
import { assetAttrsConfig } from '../../plugins/html'

export function createDevHtmlTransformFn(server: ViteDevServer) {
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
)
}
}

function getHtmlFilename(url: string, server: ViteDevServer) {
if (url.startsWith(FS_PREFIX)) {
return fsPathFromId(url)
} else {
return path.join(server.config.root, url.slice(1))
}
}

const devHtmlHook: IndexHtmlTransformHook = async (
html,
{ path: htmlPath, server }
Expand Down Expand Up @@ -101,32 +122,17 @@ const devHtmlHook: IndexHtmlTransformHook = async (
}

export function indexHtmlMiddleware(
server: ViteDevServer,
plugins: readonly Plugin[]
server: ViteDevServer
): Connect.NextHandleFunction {
const [preHooks, postHooks] = resolveHtmlTransforms(plugins)

return async (req, res, next) => {
const url = req.url && cleanUrl(req.url)
// spa-fallback always redirects to /index.html
if (url?.endsWith('.html') && req.headers['sec-fetch-dest'] !== 'script') {
let filename
if (url.startsWith(FS_PREFIX)) {
filename = url.slice(FS_PREFIX.length)
} else {
filename = path.join(server.config.root, url.slice(1))
}
const filename = getHtmlFilename(url, server)
if (fs.existsSync(filename)) {
try {
let html = fs.readFileSync(filename, 'utf-8')
// apply transforms
html = await applyHtmlTransforms(
html,
url,
filename,
[...preHooks, devHtmlHook, ...postHooks],
server
)
html = await server.transformIndexHtml(url, html)
return send(req, res, html, 'html')
} catch (e) {
return next(e)
Expand Down

0 comments on commit dbe1f4a

Please sign in to comment.