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

参照関係
  • Created at 2018/09/22 03:45

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

<!--truncate-->

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
  }
}