diff --git a/__tests__/plugin.spec.ts b/__tests__/plugin.spec.ts
index be055c4..4931251 100644
--- a/__tests__/plugin.spec.ts
+++ b/__tests__/plugin.spec.ts
@@ -34,7 +34,8 @@ async function mockBuild(taskName: string, opts: BuildOptions = {}) {
...viteOptions?.build,
write: false
},
- plugins: [stylexPlugin(stylex)]
+ plugins: [stylexPlugin(stylex)],
+ logLevel: 'silent'
}, viteOptions))
let css = ''
let js = ''
diff --git a/e2e/e2e.spec.ts b/e2e/e2e.spec.ts
index cfcd8f2..e730740 100644
--- a/e2e/e2e.spec.ts
+++ b/e2e/e2e.spec.ts
@@ -1,5 +1,25 @@
+import path from 'path'
import test from 'ava'
import { createE2EServer } from './helper'
+import { createSSRServer } from './fixtures/vue-ssr/server'
+
+// FIXME
+// test('fixture remix', async (t) => {
+// const { page } = await createE2EServer('remix')
+// await page.waitForSelector('div[role="button"]')
+// const elementHandle = await page.$('div[role="button"]')
+// const windowHandle = await page.evaluateHandle(() => Promise.resolve(window))
+// const red = await page.evaluate(([window, el]) => {
+// return (window as Window).getComputedStyle(el as Element).color
+// }, [windowHandle, elementHandle])
+// t.is(red, 'rgb(255, 0, 0)', 'first load spa button text color should be red')
+// await elementHandle.click()
+// await new Promise((resolve) => setTimeout(resolve, 2000))
+// const blue = await page.evaluate(([window, el]) => {
+// return (window as Window).getComputedStyle(el as Element).color
+// }, [windowHandle, elementHandle])
+// t.is(blue, 'rgb(0, 0, 255)', 'tap button and text color should be blue')
+// })
test('fixture spa', async (t) => {
const { page } = await createE2EServer('spa')
@@ -35,20 +55,19 @@ test('fixture qwik', async (t) => {
t.is(blue, 'rgb(0, 0, 255)', 'tap button and text color should be blue')
})
-// FIXME
-// test('fixture remix', async (t) => {
-// const { page } = await createE2EServer('remix')
-// await page.waitForSelector('div[role="button"]')
-// const elementHandle = await page.$('div[role="button"]')
-// const windowHandle = await page.evaluateHandle(() => Promise.resolve(window))
-// const red = await page.evaluate(([window, el]) => {
-// return (window as Window).getComputedStyle(el as Element).color
-// }, [windowHandle, elementHandle])
-// t.is(red, 'rgb(255, 0, 0)', 'first load spa button text color should be red')
-// await elementHandle.click()
-// await new Promise((resolve) => setTimeout(resolve, 2000))
-// const blue = await page.evaluate(([window, el]) => {
-// return (window as Window).getComputedStyle(el as Element).color
-// }, [windowHandle, elementHandle])
-// t.is(blue, 'rgb(0, 0, 255)', 'tap button and text color should be blue')
-// })
+test('fixture vue ssr', async (t) => {
+ const { page } = await createSSRServer(path.join(__dirname, 'fixtures', 'vue-ssr', 'vite.config.mts'))
+ await page.waitForSelector('div[role="button"]')
+ const elementHandle = await page.$('div[role="button"]')
+ const windowHandle = await page.evaluateHandle(() => Promise.resolve(window))
+ const red = await page.evaluate(([window, el]) => {
+ return (window as Window).getComputedStyle(el as Element).color
+ }, [windowHandle, elementHandle])
+ t.is(red, 'rgb(255, 0, 0)', 'first load spa button text color should be red')
+ await elementHandle.click()
+ await new Promise((resolve) => setTimeout(resolve, 2000))
+ const blue = await page.evaluate(([window, el]) => {
+ return (window as Window).getComputedStyle(el as Element).color
+ }, [windowHandle, elementHandle])
+ t.is(blue, 'rgb(0, 0, 255)', 'tap button and text color should be blue')
+})
diff --git a/e2e/fixtures/vue-ssr/index.html b/e2e/fixtures/vue-ssr/index.html
new file mode 100644
index 0000000..516b913
--- /dev/null
+++ b/e2e/fixtures/vue-ssr/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ Vite + Vue
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/e2e/fixtures/vue-ssr/package.json b/e2e/fixtures/vue-ssr/package.json
new file mode 100644
index 0000000..9a07e47
--- /dev/null
+++ b/e2e/fixtures/vue-ssr/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "vite-plugin-stylex-e2e-vue-ssr",
+ "scripts": {
+ "dev": "tsx ./server.ts"
+ },
+ "dependencies": {
+ "@vitejs/plugin-vue": "4.5.1",
+ "express": "^4.18.2",
+ "vite": "^5.0.6",
+ "vite-plugin-stylex": "workspace:*",
+ "vue": "^3.3.10"
+ },
+ "devDependencies": {
+ "@types/express": "^4.17.21",
+ "tsx": "^4.6.2"
+ }
+}
diff --git a/e2e/fixtures/vue-ssr/server.ts b/e2e/fixtures/vue-ssr/server.ts
new file mode 100644
index 0000000..dbe2051
--- /dev/null
+++ b/e2e/fixtures/vue-ssr/server.ts
@@ -0,0 +1,36 @@
+import fs from 'fs/promises'
+import path from 'path'
+import express from 'express'
+import { createChromeBrowser, genRandomPort } from '../../helper'
+
+export async function createSSRServer(configFile = path.join(__dirname, 'vite.config.mts')) {
+ const app = express()
+ const { createServer } = await import('vite')
+
+ const viteServer = await createServer({ configFile, server: { middlewareMode: true }, appType: 'custom', base: '/', root: __dirname })
+ app.use(viteServer.middlewares)
+ app.use('*', async (req, res) => {
+ try {
+ const url = req.originalUrl.replace('/', '')
+ let template = await fs.readFile(path.join(__dirname, 'index.html'), 'utf8')
+ template = await viteServer.transformIndexHtml(url, template)
+ const { render } = await viteServer.ssrLoadModule('/src/entry-server.ts')
+ const rendered = await render(url)
+ const html = template
+ .replace('', rendered.head ?? '')
+ .replace('', rendered.html ?? '')
+ res.status(200).set({ 'Content-Type': 'text/html' }).end(html)
+ } catch (error) {
+ viteServer.ssrFixStacktrace(error)
+ res.status(500).end(error.stack)
+ }
+ })
+ const port = genRandomPort()
+ app.listen(port)
+ const { page } = await createChromeBrowser(port)
+ return { app, page }
+}
+
+if (require.main === module) {
+ createSSRServer()
+}
diff --git a/e2e/fixtures/vue-ssr/src/app.vue b/e2e/fixtures/vue-ssr/src/app.vue
new file mode 100644
index 0000000..089228a
--- /dev/null
+++ b/e2e/fixtures/vue-ssr/src/app.vue
@@ -0,0 +1,33 @@
+
+
+
+
+
diff --git a/e2e/fixtures/vue-ssr/src/entry-client.ts b/e2e/fixtures/vue-ssr/src/entry-client.ts
new file mode 100644
index 0000000..cb1e4a8
--- /dev/null
+++ b/e2e/fixtures/vue-ssr/src/entry-client.ts
@@ -0,0 +1,5 @@
+import { createApp } from './main'
+
+const { app } = createApp()
+
+app.mount('#app')
diff --git a/e2e/fixtures/vue-ssr/src/entry-server.ts b/e2e/fixtures/vue-ssr/src/entry-server.ts
new file mode 100644
index 0000000..3ef128a
--- /dev/null
+++ b/e2e/fixtures/vue-ssr/src/entry-server.ts
@@ -0,0 +1,15 @@
+import { renderToString } from 'vue/server-renderer'
+import { createApp } from './main'
+
+export async function render() {
+ const { app } = createApp()
+
+ // passing SSR context object which will be available via useSSRContext()
+ // @vitejs/plugin-vue injects code into a component's setup() that registers
+ // itself on ctx.modules. After the render, ctx.modules would contain all the
+ // components that have been instantiated during this render call.
+ const ctx = {}
+ const html = await renderToString(app, ctx)
+
+ return { html }
+}
diff --git a/e2e/fixtures/vue-ssr/src/main.ts b/e2e/fixtures/vue-ssr/src/main.ts
new file mode 100644
index 0000000..41a2643
--- /dev/null
+++ b/e2e/fixtures/vue-ssr/src/main.ts
@@ -0,0 +1,10 @@
+import { createSSRApp } from 'vue'
+import App from './app.vue'
+
+// SSR requires a fresh app instance per request, therefore we export a function
+// that creates a fresh app instance. If using Vuex, we'd also be creating a
+// fresh store here.
+export function createApp() {
+ const app = createSSRApp(App)
+ return { app }
+}
diff --git a/e2e/fixtures/vue-ssr/vite.config.mts b/e2e/fixtures/vue-ssr/vite.config.mts
new file mode 100644
index 0000000..4da8378
--- /dev/null
+++ b/e2e/fixtures/vue-ssr/vite.config.mts
@@ -0,0 +1,7 @@
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+import { stylexPlugin } from 'vite-plugin-stylex'
+
+export default defineConfig({
+ plugins: [vue(), stylexPlugin()]
+})
diff --git a/e2e/helper.ts b/e2e/helper.ts
index a7bc6f9..7b6b678 100644
--- a/e2e/helper.ts
+++ b/e2e/helper.ts
@@ -1,17 +1,16 @@
import path from 'path'
import { chromium } from 'playwright'
-import type { ViteDevServer } from 'vite'
-export async function createChromeBrowser(server: ViteDevServer) {
+export async function createChromeBrowser(port: number) {
const browser = await chromium.launch()
const page = await browser.newPage()
- const localURL = `http://localhost:${server.config.server.port}`
+ const localURL = `http://localhost:${port}`
page.goto(localURL)
return { page }
}
-// I don't know thy vite don't accept port 0
-function genRandomPort() {
+// I don't know why vite don't accept port 0
+export function genRandomPort() {
const minPort = 5173
const maxPort = 49151
return Math.floor(Math.random() * (maxPort - minPort + 1)) + minPort
@@ -28,6 +27,6 @@ export async function createE2EServer(taskName: string) {
root: path.join(__dirname, 'fixtures', taskName)
})
await server.listen()
- const { page } = await createChromeBrowser(server)
+ const { page } = await createChromeBrowser(server.config.server.port)
return { page, server }
}
diff --git a/yarn.lock b/yarn.lock
index 7655d4d..b19afb9 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1812,7 +1812,17 @@ __metadata:
languageName: node
linkType: hard
-"@types/connect@npm:^3.4.38":
+"@types/body-parser@npm:*":
+ version: 1.19.5
+ resolution: "@types/body-parser@npm:1.19.5"
+ dependencies:
+ "@types/connect": "*"
+ "@types/node": "*"
+ checksum: 1e251118c4b2f61029cc43b0dc028495f2d1957fe8ee49a707fb940f86a9bd2f9754230805598278fe99958b49e9b7e66eec8ef6a50ab5c1f6b93e1ba2aaba82
+ languageName: node
+ linkType: hard
+
+"@types/connect@npm:*, @types/connect@npm:^3.4.38":
version: 3.4.38
resolution: "@types/connect@npm:3.4.38"
dependencies:
@@ -1862,6 +1872,30 @@ __metadata:
languageName: node
linkType: hard
+"@types/express-serve-static-core@npm:^4.17.33":
+ version: 4.17.41
+ resolution: "@types/express-serve-static-core@npm:4.17.41"
+ dependencies:
+ "@types/node": "*"
+ "@types/qs": "*"
+ "@types/range-parser": "*"
+ "@types/send": "*"
+ checksum: 12750f6511dd870bbaccfb8208ad1e79361cf197b147f62a3bedc19ec642f3a0f9926ace96705f4bc88ec2ae56f61f7ca8c2438e6b22f5540842b5569c28a121
+ languageName: node
+ linkType: hard
+
+"@types/express@npm:^4.17.21":
+ version: 4.17.21
+ resolution: "@types/express@npm:4.17.21"
+ dependencies:
+ "@types/body-parser": "*"
+ "@types/express-serve-static-core": ^4.17.33
+ "@types/qs": "*"
+ "@types/serve-static": "*"
+ checksum: fb238298630370a7392c7abdc80f495ae6c716723e114705d7e3fb67e3850b3859bbfd29391463a3fb8c0b32051847935933d99e719c0478710f8098ee7091c5
+ languageName: node
+ linkType: hard
+
"@types/hast@npm:^2.0.0":
version: 2.3.8
resolution: "@types/hast@npm:2.3.8"
@@ -1871,6 +1905,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/http-errors@npm:*":
+ version: 2.0.4
+ resolution: "@types/http-errors@npm:2.0.4"
+ checksum: 1f3d7c3b32c7524811a45690881736b3ef741bf9849ae03d32ad1ab7062608454b150a4e7f1351f83d26a418b2d65af9bdc06198f1c079d75578282884c4e8e3
+ languageName: node
+ linkType: hard
+
"@types/istanbul-lib-coverage@npm:^2.0.1":
version: 2.0.6
resolution: "@types/istanbul-lib-coverage@npm:2.0.6"
@@ -1901,6 +1942,20 @@ __metadata:
languageName: node
linkType: hard
+"@types/mime@npm:*":
+ version: 3.0.4
+ resolution: "@types/mime@npm:3.0.4"
+ checksum: a6139c8e1f705ef2b064d072f6edc01f3c099023ad7c4fce2afc6c2bf0231888202adadbdb48643e8e20da0ce409481a49922e737eca52871b3dc08017455843
+ languageName: node
+ linkType: hard
+
+"@types/mime@npm:^1":
+ version: 1.3.5
+ resolution: "@types/mime@npm:1.3.5"
+ checksum: e29a5f9c4776f5229d84e525b7cd7dd960b51c30a0fb9a028c0821790b82fca9f672dab56561e2acd9e8eed51d431bde52eafdfef30f643586c4162f1aecfc78
+ languageName: node
+ linkType: hard
+
"@types/ms@npm:*":
version: 0.7.34
resolution: "@types/ms@npm:0.7.34"
@@ -1924,6 +1979,20 @@ __metadata:
languageName: node
linkType: hard
+"@types/qs@npm:*":
+ version: 6.9.10
+ resolution: "@types/qs@npm:6.9.10"
+ checksum: 3e479ee056bd2b60894baa119d12ecd33f20a25231b836af04654e784c886f28a356477630430152a86fba253da65d7ecd18acffbc2a8877a336e75aa0272c67
+ languageName: node
+ linkType: hard
+
+"@types/range-parser@npm:*":
+ version: 1.2.7
+ resolution: "@types/range-parser@npm:1.2.7"
+ checksum: 95640233b689dfbd85b8c6ee268812a732cf36d5affead89e806fe30da9a430767af8ef2cd661024fd97e19d61f3dec75af2df5e80ec3bea000019ab7028629a
+ languageName: node
+ linkType: hard
+
"@types/react-dom@npm:^18.2.7":
version: 18.2.17
resolution: "@types/react-dom@npm:18.2.17"
@@ -1958,6 +2027,27 @@ __metadata:
languageName: node
linkType: hard
+"@types/send@npm:*":
+ version: 0.17.4
+ resolution: "@types/send@npm:0.17.4"
+ dependencies:
+ "@types/mime": ^1
+ "@types/node": "*"
+ checksum: cf4db48251bbb03cd6452b4de6e8e09e2d75390a92fd798eca4a803df06444adc94ed050246c94c7ed46fb97be1f63607f0e1f13c3ce83d71788b3e08640e5e0
+ languageName: node
+ linkType: hard
+
+"@types/serve-static@npm:*":
+ version: 1.15.5
+ resolution: "@types/serve-static@npm:1.15.5"
+ dependencies:
+ "@types/http-errors": "*"
+ "@types/mime": "*"
+ "@types/node": "*"
+ checksum: 0ff4b3703cf20ba89c9f9e345bc38417860a88e85863c8d6fe274a543220ab7f5f647d307c60a71bb57dc9559f0890a661e8dc771a6ec5ef195d91c8afc4a893
+ languageName: node
+ linkType: hard
+
"@types/unist@npm:^2, @types/unist@npm:^2.0.0":
version: 2.0.10
resolution: "@types/unist@npm:2.0.10"
@@ -4698,7 +4788,7 @@ __metadata:
languageName: node
linkType: hard
-"express@npm:^4.17.1":
+"express@npm:^4.17.1, express@npm:^4.18.2":
version: 4.18.2
resolution: "express@npm:4.18.2"
dependencies:
@@ -10143,6 +10233,20 @@ __metadata:
languageName: unknown
linkType: soft
+"vite-plugin-stylex-e2e-vue-ssr@workspace:e2e/fixtures/vue-ssr":
+ version: 0.0.0-use.local
+ resolution: "vite-plugin-stylex-e2e-vue-ssr@workspace:e2e/fixtures/vue-ssr"
+ dependencies:
+ "@types/express": ^4.17.21
+ "@vitejs/plugin-vue": 4.5.1
+ express: ^4.18.2
+ tsx: ^4.6.2
+ vite: ^5.0.6
+ vite-plugin-stylex: "workspace:*"
+ vue: ^3.3.10
+ languageName: unknown
+ linkType: soft
+
"vite-plugin-stylex@workspace:*, vite-plugin-stylex@workspace:.":
version: 0.0.0-use.local
resolution: "vite-plugin-stylex@workspace:."