forked from vitejs/vite
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: add test suite to stabilize ssr frameworks
tests vitejs#2390 and vitejs#1875 amongst others
- Loading branch information
Showing
17 changed files
with
374 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// @ts-check | ||
// this is automtically detected by scripts/jestPerTestSetup.ts and will replace | ||
// the default e2e test serve behavior | ||
|
||
const port = (exports.port = 9529) | ||
const root = `${__dirname}/..` | ||
|
||
exports.serve = async function serve(_, isProduction) { | ||
const { startServer, build } = require('vue-framework') | ||
if (isProduction) { | ||
process.env.NODE_ENV = 'production' | ||
await build(root, true) | ||
} | ||
const stopServer = await startServer(root, port, isProduction) | ||
return { | ||
// for test teardown | ||
close() { | ||
return stopServer() | ||
} | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
packages/playground/ssr-framework/__tests__/vue-framework.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { editFile, getColor, isBuild, untilUpdated } from '../../testUtils' | ||
import { port } from './serve' | ||
import fetch from 'node-fetch' | ||
|
||
const url = `http://localhost:${port}` | ||
|
||
test('/', async () => { | ||
await page.goto(url) | ||
expect(await page.textContent('h1')).toBe('Home') | ||
if (isBuild) { | ||
expect(await getColor('h1')).toBe('black') | ||
} else { | ||
// During dev, the CSS is loaded from async chunk and we may have to wait | ||
// when the test runs concurrently. | ||
await untilUpdated(() => getColor('h1'), 'black') | ||
} | ||
|
||
// is rendered to HTML | ||
const homeHtml = await (await fetch(url + '/')).text() | ||
expect(homeHtml).toContain('count is: 0') | ||
}) | ||
|
||
test('hydration', async () => { | ||
expect(await page.textContent('button')).toContain('0') | ||
await page.click('button') | ||
expect(await page.textContent('button')).toContain('1') | ||
|
||
// should not have hydration mismatch | ||
browserLogs.forEach((msg) => { | ||
expect(msg).not.toMatch('mismatch') | ||
}) | ||
}) | ||
|
||
test('/about', async () => { | ||
await page.goto(url + '/about') | ||
expect(await page.textContent('h1')).toBe('About') | ||
if (isBuild) { | ||
expect(await getColor('h1')).toBe('red') | ||
} else { | ||
// During dev, the CSS is loaded from async chunk and we may have to wait | ||
// when the test runs concurrently. | ||
await untilUpdated(() => getColor('h1'), 'red') | ||
} | ||
|
||
// is rendered to HTML | ||
const aboutHtml = await (await fetch(url + '/about')).text() | ||
expect(aboutHtml).toContain('A colored page.') | ||
|
||
// should not have hydration mismatch | ||
browserLogs.forEach((msg) => { | ||
expect(msg).not.toMatch('mismatch') | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"name": "testbla", | ||
"private": true, | ||
"version": "0.0.0", | ||
"scripts": { | ||
"dev": "vue-framework", | ||
"build": "vue-framework build", | ||
"serve": "vue-framework serve" | ||
}, | ||
"dependencies": { | ||
"@vue/server-renderer": "^3.0.6", | ||
"vue": "^3.0.8", | ||
"vue-framework": "file:./vue-framework/", | ||
"vue-router": "^4.0.3" | ||
}, | ||
"devDependencies": { | ||
"@vue/compiler-sfc": "^3.0.8" | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<template> | ||
<div> | ||
<p><a href="/">Home</a> <a href="/about">About</a></p> | ||
<h1>About</h1> | ||
A colored page. | ||
</div> | ||
</template> | ||
|
||
<style scoped> | ||
* { | ||
color: red; | ||
} | ||
div { | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
} | ||
</style> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<template> | ||
<div> | ||
<p><a href="/">Home</a> <a href="/about">About</a></p> | ||
<h1>Home</h1> | ||
<button @click="state.count++">count is: {{ state.count }}</button> | ||
</div> | ||
</template> | ||
|
||
<script setup> | ||
import { reactive } from 'vue' | ||
const state = reactive({ count: 0 }) | ||
</script> | ||
|
||
<style scoped> | ||
div { | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
} | ||
</style> |
3 changes: 3 additions & 0 deletions
3
packages/playground/ssr-framework/vue-framework/bin/vue-framework.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/usr/bin/env node | ||
|
||
require('../cli') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
const { getViteConfig } = require('./getViteConfig') | ||
const hydrateFile = require.resolve('./hydrate') | ||
const getPagesFile = require.resolve('./getPages') | ||
|
||
module.exports.build = build | ||
|
||
async function build(root, silent) { | ||
const { build } = require('vite') | ||
|
||
const configBase = getViteConfig(root, true) | ||
|
||
if (silent) { | ||
configBase.logLevel = 'error' | ||
} | ||
|
||
// client build | ||
await build({ | ||
...configBase, | ||
build: { | ||
outDir: 'dist/client', | ||
manifest: true, | ||
polyfillDynamicImport: false, | ||
rollupOptions: { input: hydrateFile } | ||
} | ||
}) | ||
|
||
// server build | ||
await build({ | ||
...configBase, | ||
build: { | ||
outDir: 'dist/server', | ||
manifest: true, | ||
polyfillDynamicImport: false, | ||
rollupOptions: { input: getPagesFile }, | ||
ssr: true | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
const { startServer } = require('./server') | ||
const { build } = require('./build') | ||
|
||
cli() | ||
|
||
async function cli() { | ||
const root = process.cwd() | ||
const port = 3000 | ||
const cliCommand = process.argv[2] | ||
if (cliCommand === undefined) { | ||
await startServer(root, port, false) | ||
console.log(`http://localhost:${port}`) | ||
return | ||
} | ||
if (cliCommand === 'build') { | ||
build(root) | ||
return | ||
} | ||
if (cliCommand === 'serve') { | ||
process.env.NODE_ENV = 'production' | ||
await startServer(root, port, true) | ||
console.log(`http://localhost:${port}`) | ||
return | ||
} | ||
throw new Error(`Unknown command ${cliCommand}`) | ||
} |
77 changes: 77 additions & 0 deletions
77
packages/playground/ssr-framework/vue-framework/createPageRender.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
const { renderToString } = require('@vue/server-renderer') | ||
const { relative } = require('path') | ||
const { createSSRApp } = require('vue') | ||
const hydrateFile = require.resolve('./hydrate') | ||
const getPagesFile = require.resolve('./getPages') | ||
|
||
module.exports.createPageRender = createPageRender | ||
|
||
const env = {} | ||
|
||
function createPageRender(viteServer, root, isProduction) { | ||
Object.assign(env, { viteServer, root, isProduction }) | ||
return render | ||
} | ||
|
||
async function render(url) { | ||
const routeMatch = await route(url) | ||
if (routeMatch === null) return null | ||
const { Page, pagePath } = routeMatch | ||
const app = createApp(Page) | ||
const html = await renderToString(app) | ||
return `<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<script>window.pagePath = '${pagePath}'</script> | ||
<script async type="module" src="${getBrowserEntry()}"></script> | ||
<link rel="icon" href="data:;base64,="> | ||
</head> | ||
<body> | ||
<div id="app">${html}</div> | ||
</body> | ||
</html> | ||
` | ||
} | ||
|
||
function getBrowserEntry() { | ||
if (!env.isProduction) { | ||
return hydrateFile | ||
} else { | ||
return findBuildEntry(hydrateFile) | ||
} | ||
} | ||
|
||
function findBuildEntry(filePathAbsolute) { | ||
const clientManifestPath = `${env.root}/dist/client/manifest.json` | ||
const clientManifest = require(clientManifestPath) | ||
const filePathRelative = relative(env.root, filePathAbsolute) | ||
const { file } = clientManifest[filePathRelative] | ||
return '/' + file | ||
} | ||
|
||
async function route(url) { | ||
const pages = await getPages() | ||
const fileName = | ||
url === '/' ? 'Home' : url.split('')[1].toUpperCase() + url.slice(2) | ||
const pagePath = `/src/pages/${fileName}.vue` | ||
const pageLoader = pages[pagePath] | ||
if (!pageLoader) return null | ||
const exports = await pageLoader() | ||
const Page = exports.default | ||
return { Page, pagePath } | ||
} | ||
|
||
async function getPages() { | ||
let exports | ||
if (!env.isProduction) { | ||
exports = await env.viteServer.ssrLoadModule(getPagesFile) | ||
} else { | ||
exports = require(`${env.root}/dist/server/getPages.js`) | ||
} | ||
return await exports.getPages() | ||
} | ||
|
||
function createApp(Page) { | ||
const app = createSSRApp(Page) | ||
return app | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export { getPages } | ||
|
||
async function getPages() { | ||
const pages = import.meta.glob('/src/pages/*.vue') | ||
return pages | ||
} |
13 changes: 13 additions & 0 deletions
13
packages/playground/ssr-framework/vue-framework/getViteConfig.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
const vuePlugin = require('@vitejs/plugin-vue') | ||
const vueJsx = require('@vitejs/plugin-vue-jsx') | ||
|
||
module.exports.getViteConfig = getViteConfig | ||
|
||
function getViteConfig(root, isProduction) { | ||
return { | ||
root, | ||
configFile: false, | ||
ssr: { external: ['vite-plugin-ssr'] }, | ||
plugins: [vuePlugin(), vueJsx()] | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
packages/playground/ssr-framework/vue-framework/hydrate.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { getPages } from './getPages' | ||
import { createSSRApp } from 'vue' | ||
|
||
hydrate() | ||
|
||
async function hydrate() { | ||
const pages = await getPages() | ||
const { pagePath } = window | ||
const exports = await pages[pagePath]() | ||
const Page = exports.default | ||
const app = createSSRApp(Page) | ||
app.mount('#app') | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
const { startServer } = require('./server') | ||
const { build } = require('./build') | ||
module.exports.startServer = startServer | ||
module.exports.build = build |
19 changes: 19 additions & 0 deletions
19
packages/playground/ssr-framework/vue-framework/package.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"name": "vue-framework", | ||
"version": "1.0.0", | ||
"main": "index.js", | ||
"bin": { | ||
"vue-framework": "bin/vue-framework.js" | ||
}, | ||
"peerDependencies": { | ||
"@vue/compiler-sfc": "^3.0.8", | ||
"@vue/server-renderer": "^3.0.6", | ||
"vue": "^3.0.8", | ||
"vue-router": "^4.0.3" | ||
}, | ||
"devDependencies": { | ||
"@vitejs/plugin-vue": "^1.0.0", | ||
"@vitejs/plugin-vue-jsx": "^1.1.2", | ||
"express": "^4.17.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
const express = require('express') | ||
const { createPageRender } = require('./createPageRender.js') | ||
const { getViteConfig } = require('./getViteConfig.js') | ||
const vite = require('vite') | ||
|
||
module.exports.startServer = startServer | ||
|
||
async function startServer(root, port, isProduction) { | ||
const app = express() | ||
|
||
let viteServer | ||
if (isProduction) { | ||
app.use(express.static(`${root}/dist/client`, { index: false })) | ||
} else { | ||
viteServer = await vite.createServer({ | ||
...getViteConfig(root, isProduction), | ||
optimizeDeps: { entries: ['/src/pages/*.vue'] }, | ||
server: { middlewareMode: true } | ||
}) | ||
app.use(viteServer.middlewares) | ||
} | ||
|
||
const renderPage = createPageRender(viteServer, root, isProduction) | ||
app.get('*', async (req, res, next) => { | ||
const url = req.originalUrl | ||
const html = await renderPage(url) | ||
if (html === null) return next() | ||
res.send(html) | ||
}) | ||
|
||
return new Promise((resolve) => { | ||
const server = app.listen(port, () => { | ||
const stopServer = async () => { | ||
server.close() | ||
if (viteServer) await viteServer.close() | ||
} | ||
resolve(stopServer) | ||
}) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters