Next.js (with TypeScript)のサーバーをKoaで起動する
基本的にKoaやExpressなどを使う必要はないのですが、Shopify Appなどでお世話になりそうなので勉強がてら車輪の再開発してました。 進め方 Next.jsのKoa Exampleを目指して、自力で実装します […]
目次
基本的にKoaやExpressなどを使う必要はないのですが、Shopify Appなどでお世話になりそうなので勉強がてら車輪の再開発してました。
進め方
Next.jsのKoa Exampleを目指して、自力で実装します。
なのでこのExampleをcloneする方が手取り早いです。
https://github.com/vercel/next.js/tree/canary/examples/custom-server-koa
セットアップ
TypeScript化はcreate-next-app
でできるのでサッと立ち上げてしまいます。
$ yarn create next-app --typescript
ライブラリインストール
Koaライブラリと型定義、そしてサーバーを動かすためにts-nodeをインストールします。
$ yarn add koa koa-router ts-node
$ yarn add -D @types/koa @types/koa-router
サーバー向けtsconfigの作成
Next.jsでTypeScriptを使う場合、isolatedModules
をtrue
にする必要があります。しかしこれを有効にしていると、サーバー側のJSをts-nodeで動かせないので、別途サーバー用のtsconfigを作成します。
tsconfig.server.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"isolatedModules": false
},
"include": ["server/**/*.ts"]
}
簡単なKoaサーバーのコードを実装
兎にも角にもまずはKoaでサーバーを動かしてみないと始まりません。Next.jsのコードと分けるために、server/index.ts
としてファイルを作成します。
server/index.ts
import Koa from 'koa'
import Router from 'koa-router'
const server = new Koa()
const router = new Router()
router.get('/', (ctx) => {
ctx.body = 'hello'
})
server.use(router.routes())
server.listen(3100, () => {
console.log('> Ready on http://localhost:3100')
})
Package.jsonにサーバー起動コマンドを設定
あとはts-nodeでサーバーを動かすだけです。オプションが長いので、npm-scriptとして定義してしまいましょう。
"scripts": {
"start:server": "yarn ts-node --project tsconfig.server.json server/index.ts",
これでyarn start:server
を実行するとサーバーが起動します。
% yarn start:server
yarn run v1.22.10
$ yarn ts-node --project tsconfig.server.json server/index.ts
$ /Users/development/koa-typescript/node_modules/.bin/ts-node --project tsconfig.server.json server/index.ts
Ready on http://localhost:3100
cURLでhelloが帰ってくることを確認します。
$ curl http://localhost:3100/
hello
Next.jsを組み込む
あとはNext.jsをKoaに載せるだけです。Exampleの実装をそのままserver/index.ts
に載せましょう。
import Koa from 'koa'
import Router from 'koa-router'
import next from 'next'
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare().then(() => {
const server = new Koa()
const router = new Router()
router.all('(.*)', async (ctx) => {
await handle(ctx.req, ctx.res)
ctx.respond = false
})
server.use(async (ctx, next) => {
ctx.res.statusCode = 200
await next()
})
server.use(router.routes())
server.listen(3100, () => {
console.log('> Ready on http://localhost:3100')
})
})
これでブラウザからアクセスすると、Next.jsのスターター画面が表示されます。
終わりに
これだけだと正直やるメリットはあまりないです。ただ、ShopifyでNext.jsを使う場合にお世話になるので、内容理解の第一歩としてはちょうどよかったかなと思います。