Skip to main content

c8r/genのserverのコードを分析してみる

· 3 min read

参照関係

  • Created at 2018/09/22 03:45

引き続きgenを実際に読む。

server.ts

serverの主な役割はこうだ

  • File System Watchの立ち上げ(ファイルの変更監視)
  • WebSocket Serverの立ち上げ
  • HTTPサーバーの立ち上げ
  • HTTPサーバーが返すresponseの作成
const start = async (dirname: string, opts: Options) => {
// 利用可能なポートを探す
const socketPort: number = await portfinder.getPortPromise()
// 定義だけ
let socket: WebSocket
// 初回に表示するページの取得
let gPages = await getPages(dirname, opts)

// ファイルの変更監視
const watcher: chokidar.FSWatcher = chokidar.watch(dirname, {
depth: 1,
ignoreInitial: true,
ignored: '!*.(jsx|md|json)',
})

// WebSocketサーバーの立ち上げ
const socketServer = new WebSocket.Server({ port: socketPort })

// 接続時にsocket渡す
socketServer.on('connection', (res: WebSocket) => {
// 最後に接続したものだけ更新の対象とする
socket = res
})

// 更新時に得られたsocketに対してpayloadを投げる
const update = async () => {
if (!socket) {
return
}
gPages = await getPages(dirname, opts)
socket.send(JSON.stringify({ reload: true }))
}
// 省略
}

export { start as server }

続きは、HTTPサーバー部分

const start = async (dirname: string, opts: Options) => {
// 中略
const app = http.createServer((req: http.IncomingMessage, res: http.ServerResponse) => {
if (!req.url) {
return
}
const { pathname } = url.parse(req.url)
if (!pathname) {
return
}
// URIとディレクトリ名を結合することで、ファイル名を生成する
const filepath = path.join(dirname, pathname)
// ローカルディレクトリに存在しているかどうか確認
if (fs.existsSync(filepath) && fs.statSync(filepath).isFile()) {
fs.createReadStream(filepath).pipe(res)
return
}

// `/`終わりの場合はindexでに変換する
const name = pathname === '/' ? 'index' : pathname.replace(/^\//, '').replace(/\/$/, '')
const page = gPages.find((localPage: any) => localPage.name === name)

if (!page) {
res.write('page not found: ' + pathname)
res.end()
return
}
// レンダリングするページをレスポンスに含める
res.write(page.html)
// hot reloadをかける用のscriptを最後尾に追加する
res.write(makeScript(socketPort))
res.end()
})

try {
const server = await app.listen(socketPort + 2)
return server
} catch (err) {
console.log(err)
throw err
}
}