Edge Runtimeで遊んでみる
Edge Runtime が出た
Vercelからいつの間にかEdge Runtimeなるものが出てたので、遊んでみた。
Web標準のAPIを使ったエッジ環境で動くアプリケーションの開発やテストを助けるツールキット。Edge環境はNode.jsじゃないし、eval
が使えなかったりするので、それをシミュレートできる。
The Edge Runtime is a toolkit for developing, testing, and defining the runtime Web APIs for Edge infrastructure.
第一行目に「Vercel」とか「Next.js」の文字がないのがよい。とはいえ、一番の想定はVercelのEdge Functionsでしょう。
Edge Functionsってのは今のところ2つあるみたい。どちらもVercelもしくはNext.jsの機能。Edge Middlewareが今朝のNext.js 12.2と共にリリースされた。Edge API Routesってのはベータ。/api/*
で動くやつのエッジ版。
- Edge Middleware
- Edge API Routes
これらがEdge RuntimeのおかげでローカルのNext.jsでエミュレートできる。どちらもnext@canary
で動いた。
今回のリリースに「Edge Server-Rendering(Experimental)」が含まれているようにNext.jsもエッジ寄りになるはず。それを考慮するとEdge Runtimeは必然的に生まれたと言えよう。
Edge RuntimeのCLIでHello World
Edge Runtimeのパッケージの中のedge-runtime
にはCLIがあるので、まずはそれで遊んでみる(REPLもある)。
edge-runtime hello.js --listen
これで、サーバーが立たる。
動いた!
Cloudflare Workersのコードを動かす
Web標準の環境ということはCloudflare WorkersやFastly Compute@Edgeのコードも動くはず(VercelはCloudflare Workersで動いているらしい?)。
import { Hono } from 'hono'
import { poweredBy } from 'hono/powered-by'
const app = new Hono()
app.use('*', poweredBy())
app.get('/', (c) => c.text('Hello Edge Runtime! This is Hono!'))
export default app
import app from './app'
app.fire()
Cloudflare Workers向けを第一に謳っているHonoを使ったコードを、ビルドしてjsにして、edge-runtime
に渡したら動いた!
esbuild --bundle src/server.ts --outfile=dist/server.js
edge-runtime dist/server.js --listen
いいね!
Jest Environment
Jestの環境、@edge-runtime/jest-environment
もついているので先ほどのコードをテストしてみよう。jest.config.js
のtestEnvironment
に明示する。
module.exports = {
testEnvironment: '@edge-runtime/jest-environment',
testMatch: ['**/test/**/*.+(ts|tsx|js)', '**/src/**/(*.)+(spec|test).+(ts|tsx|js)'],
transform: {
'^.+\\.(ts|tsx)$': 'esbuild-jest',
},
}
テストはこんな感じ。
import app from './app'
describe('Test the application', () => {
it('Should return 200 response', async () => {
const res = await app.request('http://localhost/')
expect(res.status).toBe(200)
expect(res.headers.get('x-powered-by')).toBe('Hono')
})
})
いざ、実行!動いた!
エンドポイントにリクエストを送ってレスポンスをe2eっぽく試験するのがこれだけでできるのは、非常にDXが高いです。実はこの書き方は、Cloudflare Workersのアプリケーションを作る時にMiniflareのJest Environmentを使ったテストと全く同じです。
Honoのミドルウェア
あっさりとHonoのBasic認証ミドルウェアも動いた。
Next.jsの中でもCloudflare Workersのコードは動く
まぁようはWeb標準のEdge Functionsなので、Cloudflare Workersが動いて、それがNext.jsでも動くのです。Edge API Routesを試してみます。
pages/api/[...slug].ts
を用意して、いつもどおりNext.jsの開発サーバーを立ち上げると…
import { NextRequest } from 'next/server'
import { Hono } from 'hono'
const app = new Hono()
app.get('/api/hello', (c) => {
return c.json({ message: 'Hellooooo from Hooooono' })
})
// eslint-disable-next-line import/no-anonymous-default-export
export default (req: NextRequest) => app.request(req)
export const config = {
runtime: 'experimental-edge',
}
/api/hello
が動いた!
これも当然ながら、Vercelにデプロイして動きます。
いい感じ!
まとめ
以上、Edge Runtimeで遊んでみました。Cloudflare Workersで動くコードがそのまま動くのは当然なのですが、楽しかったです。Cloudflareには開発環境にWranglerがあるけど、どちらかというとローカルをエミュレートしているMiniflareに近いです。
以前、Honoの開発をする時にテストをどうするか?みたいな話があって、結局、今も使っているminiflare Jest Environment
になったのですが、今回のEdge Runtimeで選択肢が増えるのは嬉しいです。
Cloudflare Workersの話になっちゃた感もありますが、Edge RuntimeがNext.jsでどのように活かされていくかを探求したいですね。Next.jsもどんどんエッジに寄っていく。ってことでもっとEdge Functionsで諸々動かしたいのですが、それはまた今度。
PS. Stream response??
Next.jsのページにEdge API Routesを使うとStreams APIを使って、「Stream response」ができるって書いてあるけど、どうするんだ??ってなってるのであとで調べる。
Edge API Routes can stream responses from the server and run after cached files (e.g. HTML, CSS, JavaScript) have been accessed. Server-side streaming can help improve performance with faster Time To First Byte (TTFB).
今回使ったコード
参考になる記事
Discussion