LoginSignup
0
0

More than 1 year has passed since last update.

express-generatorで作成したexpressプロジェクトをTypeScript化する その2(フロント側)

Last updated at Posted at 2022-06-08

こんにちは、katです。
前回の続編になります。

前回、express-generatorで作成したプロジェクトのサーバーサイド部分をTypeScript化する方法を紹介したのですが、
その記事ではフロントエンド部分(ブラウザ側JavaScript)のTypeScript化はしておらず、完全なTypeScript化とは呼べない状況でした。

そこで今回、フロント側にもTypeScriptを導入し、なんとか全体をTypeScript化できました。
同時に、フロント側にWebpackも導入し、ブラウザ側では1つのJavaScriptファイルのみを読み込むようにできました。
(フロント側で複数のjsファイルを用いている場合、IEブラウザではESモジュールが使用できない等、ブラウザ間で何かと差異がある。→Webpackを用いて1ファイルにしてしまえば解決)

それらについて、今回学んだ事項を紹介したく、記事を作成しました。
Githubリポジトリ(今回の作業終了時コミット)はこちら

方針

以下のような手順でTypeScript → JavaScriptへの変換をしております。

  1. tscでコンパイル処理(TypeScript複数ファイル → JavaScript複数ファイル)
  2. webpackでバンドル処理(JavaScript複数ファイル → JavaScript単一ファイル & 最適化)
    image.png

ts-loaderという技術を用いて、TypeScript複数ファイル → JavaScript単一ファイル への直接変換を行う手法もあるのですが、
そうするとtscのトランスパイラ(旧バージョンのJavaScript変換等)の恩恵を受けられないことが分かったため、
一度JavaScriptファイルに変換した後にWebpack処理を行うようにしております。

手順

パッケージのインストール

yarn add -D webpack webpack-dev-server webpack-cli clean-webpack-plugin

パッケージの概要

  • webpack-dev-server : 開発用のwebpack(ホットリロード機能付き)
  • webpack-cli : webpack系統をコマンド操作するためのパッケージ
  • clean-webpack-plugin : バンドルの際、格納先フォルダ内の不要ファイル等、ゴミを削除する

ejsの編集

scriptタグを編集し、バンドルされるJavaScriptファイルを読み込む。
今回は、bundle.jsというjsファイルを指定する。

index.ejs
<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <script src="/javascripts/bundle.js" defer></script>
    ~~省略~~
  </head>
  ~~省略~~
</html>

webpack設定ファイル(本番用)

webpack.prod.js
const path = require('path')
const { CleanWebpackPlugin } = require("clean-webpack-plugin")

module.exports = {
  mode: 'production',
  entry: './dist/frontend/index.js',//エントリーポイント
  output: {
    filename: 'bundle.js',//バンドルファイル名
    path: path.resolve(__dirname, 'public', 'javascripts')//バンドル先ディレクトリ
  },
  resolve: {
    extensions: ['.js']
    //typescriptでは、import時に拡張子書かない。しかしそれだけではwebpackエラー出る。そのための拡張子の補完。
  },
  plugins: [
    new CleanWebpackPlugin()//clean-webpack-plugin(バンドル先フォルダ内のゴミを削除)
  ]
}

webpack設定ファイル(開発用)

今回は、バンドル結果を実際にファイルに書き出す(ディスクに出力する)ようにしている。
(webpack-dev-serverでは、デフォルトだとバンドル結果はメモリ上に作成するだけ。バンドル結果を読み込むにはlocalhost:8080/〜〜〜/bundle.jsにアクセスする)。

webpack.dev.js
const path = require('path')

module.exports = {
  mode: 'development',
  entry: './dist/frontend/index.js',//エントリーポイント
  output: {
    filename: 'bundle.js',//バンドルするファイル名
    path: path.resolve(__dirname, 'public', 'javascripts'),//バンドル先ディレクトリ
    publicPath: path.resolve('public', 'javascripts')//webpack-dev-serverで実行時、bundle.jsの格納場所(デフォルトだとaファイルには現れない)
  },
  resolve: {
    extensions: ['.js']
    //typescriptでは、import時に拡張子書かない。しかしそれだけではwebpackエラー出る。そのための拡張子の補完。
  },
  devServer: {
    devMiddleware: {
      writeToDisk: true//バンドルのファイルをファイル出力するための設定
    }
  }
}

今回、実際にファイルをディスク出力する理由として、バンドルされたjsをejs(テンプレートエンジン)で読み込ませたいからである。
ejsを使うのであれば、別ポートのlocalhost:3000を立ち上げる必要があり、その関係で開発用と本番用でscriptタグを書き換えないといけなくなってしまう、という理由があり今回はファイルを実際にディスク出力した。

index.ejs(ファイル出力しない場合の本番用)
~~省略~~
  <head>
    ~~省略~~
    <script src="/javascripts/bundle.js" defer></script>
    ~~省略~~
  </head>
~~省略~~
index.ejs(ファイル出力しない場合の開発用)
~~省略~~
  <head>
    ~~省略~~
    <script src="localhost:8080/javascripts/bundle.js" defer></script>
    ~~省略~~
  </head>
~~省略~~

実行方法

package.jsonを以下のように修正。

package.json
{
~~省略~~
  "scripts": {
    "dev": "tsc -w",
    "dev:back": "ts-node-dev ./src/backend/bin/www",
    "dev:front": "webpack-dev-server --config webpack.dev.js",
    "build": "yarn run build:front && yarn run build:back",
    "build:front": "tsc && webpack --config webpack.prod.js",
    "build:back": "tsc",
    "start": "yarn run build && node ./dist/backend/bin/www"
  },
~~省略~~
}

開発時 実行

ターミナルを3つ立ち上げる(A,B,Cとする)。

  • ターミナルAで yarn run dev
  • ターミナルBで yarn run dev:back
  • ターミナルCで yarn run dev:front
    と実行することで、フロントエンド・バックエンドともにホットリロードで開発できる。
    (ただ、ターミナル3つ立ち上げるやり方はあまりよろしくなさそう。。ここはもう少し勉強の必要あり。)

本番時 実行

ターミナルで yarn run start

おわりに

今回は以上です! ご覧いただきありがとうございました。
まだまだ改善の余地ありですが、ひとまずはexpess-generatorプロジェクトのTypeScript化は完了です。

特に、Webpackの部分は苦手意識を持っており正直腰が重かったのですが、今回0から導入したことで理解が深まりました。
ちなみに、React、Nextは既に勉強済なのですが、「実際にブラウザが読み込むjsファイルはどうなっているのだろう」というところの理解を後回しにしていました。
今回得た知識をもとにReact、Nextを復習し、点と点が繋がればと考えています。

今後とも宜しくお願いいたします。

参考記事

Udemy TypeScript講座

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0