From b5739508239c709a9ac9ec5496c60cff12d54e13 Mon Sep 17 00:00:00 2001 From: Yusuke Wada Date: Fri, 12 Apr 2024 08:08:40 +0900 Subject: [PATCH 1/4] feat(dev-server): supports Bun --- .github/workflows/ci-dev-server.yml | 10 +++ packages/dev-server/e2e-bun/e2e.test.ts | 70 +++++++++++++++++++ packages/dev-server/e2e-bun/mock/app.ts | 62 ++++++++++++++++ .../dev-server/e2e-bun/playwright.config.ts | 24 +++++++ .../e2e-bun/public/static/hello.json | 3 + packages/dev-server/e2e-bun/vite.config.ts | 13 ++++ packages/dev-server/package.json | 3 +- packages/dev-server/src/dev-server.ts | 1 + yarn.lock | 10 +-- 9 files changed, 190 insertions(+), 6 deletions(-) create mode 100644 packages/dev-server/e2e-bun/e2e.test.ts create mode 100644 packages/dev-server/e2e-bun/mock/app.ts create mode 100644 packages/dev-server/e2e-bun/playwright.config.ts create mode 100644 packages/dev-server/e2e-bun/public/static/hello.json create mode 100644 packages/dev-server/e2e-bun/vite.config.ts diff --git a/.github/workflows/ci-dev-server.yml b/.github/workflows/ci-dev-server.yml index ca55945..52f429c 100644 --- a/.github/workflows/ci-dev-server.yml +++ b/.github/workflows/ci-dev-server.yml @@ -24,3 +24,13 @@ jobs: - run: yarn build - run: npx playwright install --with-deps - run: yarn test + ci-bun: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: oven-sh/setup-bun@v1 + with: + bun-version: '1.0.25' + - run: bun install + - run: npx playwright install --with-deps + - run: bun run test:e2e:bun diff --git a/packages/dev-server/e2e-bun/e2e.test.ts b/packages/dev-server/e2e-bun/e2e.test.ts new file mode 100644 index 0000000..9cc1c1a --- /dev/null +++ b/packages/dev-server/e2e-bun/e2e.test.ts @@ -0,0 +1,70 @@ +import { test, expect } from '@playwright/test' + +test('Should return 200 response', async ({ page }) => { + const response = await page.goto('/') + expect(response?.status()).toBe(200) + + const headers = response?.headers() ?? {} + expect(headers['x-via']).toBe('vite') + + const content = await page.textContent('h1') + expect(content).toBe('Hello Vite!') +}) + +test('Should contain an injected script tag', async ({ page }) => { + await page.goto('/') + + const lastScriptTag = await page.$('script:last-of-type') + expect(lastScriptTag).not.toBeNull() + + const content = await lastScriptTag?.textContent() + expect(content).toBe('import("/@vite/client")') +}) + +test('Should exclude the file specified in the config file', async ({ page }) => { + let response = await page.goto('/file.ts') + expect(response?.status()).toBe(404) + + response = await page.goto('/ends-in-ts') + expect(response?.status()).toBe(200) + + response = await page.goto('/app/foo') + expect(response?.status()).toBe(404) + + response = await page.goto('/favicon.ico') + expect(response?.status()).toBe(404) + + response = await page.goto('/static/foo.png') + expect(response?.status()).toBe(404) +}) + +test('Should return 200 response - /stream', async ({ page }) => { + const response = await page.goto('/stream') + expect(response?.status()).toBe(200) + + const headers = response?.headers() ?? {} + expect(headers['x-via']).toBe('vite') + + const content = await page.textContent('h1') + expect(content).toBe('Hello Vite!') +}) + +test('Should serve static files in `public/static`', async ({ page }) => { + const response = await page.goto('/static/hello.json') + expect(response?.status()).toBe(200) + + const data = await response?.json() + expect(data['message']).toBe('Hello') +}) + +test('Should return a vite error page - /invalid-response', async ({ page }) => { + const response = await page.goto('/invalid-response') + expect(response?.status()).toBe(500) + expect(await response?.text()).toContain('ErrorOverlay') +}) + +test('Should set `workerd` as a runtime key', async ({ page }) => { + const res = await page.goto('/runtime') + expect(res?.ok()).toBe(true) + expect(await res?.text()).toBe('bun') +}) diff --git a/packages/dev-server/e2e-bun/mock/app.ts b/packages/dev-server/e2e-bun/mock/app.ts new file mode 100644 index 0000000..4c0c421 --- /dev/null +++ b/packages/dev-server/e2e-bun/mock/app.ts @@ -0,0 +1,62 @@ +import { Hono } from 'hono' +import { getRuntimeKey } from 'hono/adapter' + +const app = new Hono() + +app.get('/', (c) => { + c.header('x-via', 'vite') + return c.html('

Hello Vite!

') +}) + +app.get('/file.ts', (c) => { + return c.text('console.log("exclude me!")') +}) + +app.get('/app/foo', (c) => { + return c.html('

exclude me!

') +}) + +app.get('/ends-in-ts', (c) => { + return c.text('this should not be excluded') +}) + +app.get('/favicon.ico', (c) => { + return c.text('a good favicon') +}) + +app.get('/static/foo.png', (c) => { + return c.text('a good image') +}) + +app.get('/stream', () => { + const html = new TextEncoder().encode('

Hello Vite!

') + const stream = new ReadableStream({ + start(controller) { + controller.enqueue(html) + controller.close() + }, + }) + return new Response(stream, { + headers: { 'Content-Type': 'text/html', 'x-via': 'vite' }, + }) +}) + +// @ts-expect-error the response is string +app.get('/invalid-response', () => { + return '

Hello!

' +}) + +app.get('/invalid-error-response', (c) => { + try { + // @ts-expect-error the variable does not exist, intentionally + doesNotExist = true + + return c.html('

Hello Vite!

') + } catch (err) { + return err + } +}) + +app.get('/runtime', (c) => c.text(getRuntimeKey())) + +export default app diff --git a/packages/dev-server/e2e-bun/playwright.config.ts b/packages/dev-server/e2e-bun/playwright.config.ts new file mode 100644 index 0000000..8c50c7a --- /dev/null +++ b/packages/dev-server/e2e-bun/playwright.config.ts @@ -0,0 +1,24 @@ +import { defineConfig, devices } from '@playwright/test' + +export default defineConfig({ + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + workers: process.env.CI ? 1 : undefined, + use: { + baseURL: 'http://localhost:6173', + }, + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + timeout: 5000, + retries: 2, + }, + ], + webServer: { + command: 'bun --bun vite --port 6173 -c ./vite.config.ts', + port: 6173, + reuseExistingServer: !process.env.CI, + }, +}) diff --git a/packages/dev-server/e2e-bun/public/static/hello.json b/packages/dev-server/e2e-bun/public/static/hello.json new file mode 100644 index 0000000..92aaf63 --- /dev/null +++ b/packages/dev-server/e2e-bun/public/static/hello.json @@ -0,0 +1,3 @@ +{ + "message": "Hello" +} \ No newline at end of file diff --git a/packages/dev-server/e2e-bun/vite.config.ts b/packages/dev-server/e2e-bun/vite.config.ts new file mode 100644 index 0000000..3dfe571 --- /dev/null +++ b/packages/dev-server/e2e-bun/vite.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from 'vite' +import devServer, { defaultOptions } from '../src' + +export default defineConfig(async () => { + return { + plugins: [ + devServer({ + entry: './mock/app.ts', + exclude: [...defaultOptions.exclude, '/app/**'], + }), + ], + } +}) diff --git a/packages/dev-server/package.json b/packages/dev-server/package.json index 4e98a52..ea57a6a 100644 --- a/packages/dev-server/package.json +++ b/packages/dev-server/package.json @@ -8,6 +8,7 @@ "scripts": { "test:unit": "vitest --run", "test:e2e": "playwright test -c e2e/playwright.config.ts e2e/e2e.test.ts", + "test:e2e:bun": "playwright test -c e2e-bun/playwright.config.ts e2e-bun/e2e.test.ts", "test": "yarn test:unit && yarn test:e2e", "build": "rimraf dist && tsup --format esm,cjs --dts && publint", "watch": "tsup --watch", @@ -82,7 +83,7 @@ "node": ">=18.14.1" }, "dependencies": { - "@hono/node-server": "^1.8.2", + "@hono/node-server": "^1.10.0", "miniflare": "^3.20231218.2", "minimatch": "^9.0.3" } diff --git a/packages/dev-server/src/dev-server.ts b/packages/dev-server/src/dev-server.ts index fc525f4..31e54bf 100644 --- a/packages/dev-server/src/dev-server.ts +++ b/packages/dev-server/src/dev-server.ts @@ -169,6 +169,7 @@ export function devServer(options?: DevServerOptions): VitePlugin { return response }, { + overrideGlobalObjects: false, errorHandler: (e) => { let err: Error if (e instanceof Error) { diff --git a/yarn.lock b/yarn.lock index 061766a..f500753 100644 --- a/yarn.lock +++ b/yarn.lock @@ -950,10 +950,10 @@ __metadata: languageName: node linkType: hard -"@hono/node-server@npm:^1.8.2": - version: 1.8.2 - resolution: "@hono/node-server@npm:1.8.2" - checksum: dda9a37a9f73ebae64edd653d348dd63c5bd8205e368a8767c8f21bee5e0cbe555c8b279e98a4805ad27ae00517bbeae4fccf27119c6c06af8a268e126d82d0d +"@hono/node-server@npm:^1.10.0": + version: 1.10.0 + resolution: "@hono/node-server@npm:1.10.0" + checksum: d6ed27c41cf3fd10873cd3c927c3459ed9d596d28e4870ad145660e6783f0de9109ec0fe97b45ba55844c6fb41acb748005cff76cdbd78a944a98179489d3cba languageName: node linkType: hard @@ -977,7 +977,7 @@ __metadata: version: 0.0.0-use.local resolution: "@hono/vite-dev-server@workspace:packages/dev-server" dependencies: - "@hono/node-server": ^1.8.2 + "@hono/node-server": ^1.10.0 "@playwright/test": ^1.37.1 glob: ^10.3.10 hono: ^4.0.1 From 031a5716bcfb36de6ea470cda9197b4356781c99 Mon Sep 17 00:00:00 2001 From: Yusuke Wada Date: Fri, 12 Apr 2024 08:19:59 +0900 Subject: [PATCH 2/4] fix the test commanda --- packages/dev-server/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dev-server/package.json b/packages/dev-server/package.json index ea57a6a..7e9493a 100644 --- a/packages/dev-server/package.json +++ b/packages/dev-server/package.json @@ -6,7 +6,7 @@ "module": "dist/index.js", "type": "module", "scripts": { - "test:unit": "vitest --run", + "test:unit": "vitest --run ./src", "test:e2e": "playwright test -c e2e/playwright.config.ts e2e/e2e.test.ts", "test:e2e:bun": "playwright test -c e2e-bun/playwright.config.ts e2e-bun/e2e.test.ts", "test": "yarn test:unit && yarn test:e2e", From bef09a1a5ca830d6bb15b0290da62d4ea3cfbc16 Mon Sep 17 00:00:00 2001 From: Yusuke Wada Date: Fri, 12 Apr 2024 08:22:35 +0900 Subject: [PATCH 3/4] fixed ci config --- .github/workflows/ci-dev-server.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci-dev-server.yml b/.github/workflows/ci-dev-server.yml index 52f429c..5e3eed5 100644 --- a/.github/workflows/ci-dev-server.yml +++ b/.github/workflows/ci-dev-server.yml @@ -26,6 +26,9 @@ jobs: - run: yarn test ci-bun: runs-on: ubuntu-latest + defaults: + run: + working-directory: ./packages/dev-server steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v1 From 09aa48f3ce850401146973cfb2d5aa5fd9aeb9cc Mon Sep 17 00:00:00 2001 From: Yusuke Wada Date: Fri, 12 Apr 2024 08:26:18 +0900 Subject: [PATCH 4/4] add changeset --- .changeset/tame-rabbits-cross.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/tame-rabbits-cross.md diff --git a/.changeset/tame-rabbits-cross.md b/.changeset/tame-rabbits-cross.md new file mode 100644 index 0000000..cdb6f6a --- /dev/null +++ b/.changeset/tame-rabbits-cross.md @@ -0,0 +1,5 @@ +--- +'@hono/vite-dev-server': minor +--- + +feat: supports Bun