typescript toyproject: ピンインを出力してみよう

####　目標

> typescript, webpack, loader の環境設定
> webpack環境でjavascript, jqueryを使う

#### 前提条件
* node.js（必）

```
C:\>node -v
v12.18.4
```
* visual studio code (以上vsc)

* Live Server
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070645/1448a852-fba6-c34f-5d7d-ed169988c535.png)



# 1. typescript project 生成
**(1) 基本セッティング**

```
C:\git>mkdir pinyin_show　// 1. project　フォルダーを作って
C:\git>cd pinyin_show　// 2. そこに入って
C:\git\lang_wich_sample>npm init　// 3. package.jsonが生成させる
```
エンター連続してデフォルトで進む。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070645/6aa7b217-6a4e-c904-502f-a8664b6be9c7.png)
vscからpinyin_showを開いてpackage.jsonを確認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070645/e3d4a083-9993-2516-594e-bb42ecb8a508.png)

```
npm install
```
package-lock.json確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070645/89781e9f-69a6-8439-e8c1-d8163124c107.png)

**(2) typescript セッティング**

```
npm i -D typescript ts-node @types/node
```

>_ts-node: typescript → es5へ変換・実行_
>_@types/node: typescript用タイプライブラリ（ex ramda →　@types/ramda)_

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070645/6d55b1ad-4144-3df4-47f2-0d2729e707e0.png)

```
tsc --init
```
tsconfig.json が作られた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070645/4b25725c-eaaf-ffe1-86a1-6a1efd08b99e.png)

まずはコマンドアウトを全部削除。


```tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include" : ["src/index.ts"] // そして始まりのファイルを設定する
}
```
そしてsrc/index.ts　を作る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070645/055e3b08-e1aa-20e5-a7b8-8b41e5a94ca3.png)

# 2. webpackを使ってみよう
**(1) HTML生成**
まずindex.htmlを作って中身を埋める
（! →　tabキーで基本コードが自動で書かれる）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070645/6da1df07-4345-adb6-1620-9559639e2b85.png)

ピンイン出力のためのキーワード入力欄を作って

```
<input type="input" class="keyword" placeholder="keyword"></input>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070645/11e427e2-668e-fdaa-ffb8-c46641eae603.png)

異常なしのこと確認。

**(2) webpackインストール**
>_webpackとは？　一つのhtml実行に必要なjsファイルたちを一つのjsnにまとめてくれること。_

```
npm i -D webpack webpack-cli
```
package.jsonで無事インストールのこと確認して。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070645/434bc788-e920-b362-807a-1c6c156b3b4d.png)

webpackコマンドを追加する（"build"にしなくても大丈夫）

```
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"　// 追加
  },
```
webpackの設定ファイルを生成する。

```webpack.config.js
const path = require('path');

module.exports = {
    mode: 'development',
    entry: {
      main:'./src/index.ts'
    },
    output: {
      path: path.resolve('./dist'),
      filename:'[name].js'　// [name] = entry : { key: value} の key (main.js)
    }
  };
```
今までの設定に問題はないかチェックしてみよう。
(これから修正の確認は以下コマンドを叩いた後にする)

```
npm run build
```
distフォルダーがなくてもnpm run buildでdistフォルダーが作られmain.jsが納めていることが確認できる。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070645/898e9e9a-76f0-1e57-d4e9-4b5f41e07883.png)

ビルドされたjsをhtmlで使うためにはjsのパスをhtmlに入れておく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070645/a17b328a-c8cb-d2f3-28c9-20beade8f0ff.png)

しかしいちいちビルドの結果物を指定するのも面倒なので、これもwebpackを通してまとめるようにしよう。

**(3) html-webpack-plugin インストール**

```
npm i -D html-webpack-plugin
```
```webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');　// 追加
const path = require('path');

module.exports = {
    mode: 'development',
    entry: {
      main:'./src/index.ts'
    },
    output: {
      path: path.resolve('./dist'),
      filename:'[name].js'
    },　　
　　　// 追加
    plugins: [
      new HtmlWebpackPlugin({
        template:'./src/index.html'
      })
    ],
  };
```
それでは ```<script...></script> ```は削除して

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070645/17cefe95-0b27-ba81-addf-e03b986ede97.png)

(実装誤り修正： src/index.htmlになるよう位置修正)

```
npm run build
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070645/5a82d7d7-0655-8d34-5c76-3504ad74033c.png)

これからはビルドされたdist/htmlを使うようにする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070645/6dc59f23-b439-ce9d-87ab-03ba35c1000b.png)

**(4) ts-loader インストール**
typescriptで作成したコードを画面で手軽に理解させるためにはローダーのインストールが必要。

```
npm i -D ts-loader
```

```webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');

module.exports = {
    mode: 'development',
    entry: {
      main:'./src/index.ts'
    },
    output: {
      path: path.resolve('./dist'),
      filename:'[name].js'
    },
    plugins: [
      new HtmlWebpackPlugin({
        template:'./src/index.html'
      })
    ],
     //追加
     module: { 
      rules: [ 
        { test: /\.ts$/, use: 'ts-loader' } 
      ] 
    }      
  };
```

# 3. javascript作成

キーボードが押された際に呼び出される関数を作ってみた。

```index.html
    <input type="input" class="keyword" placeholder="keyword" onkeydown="main"></input>
```

```index.ts
export function main(){
    console.log("hello typescript..?");
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070645/1f304695-9165-f4be-74ea-6dbc3863a7d0.png)

```
Uncaught ReferenceError: main is not defined at HTMLInputElement.onkeydown
```
onKeyDown, onClick系の関数をtsで使うにはWindowへ設定追加が必要だそうで、

```index.ts
interface Window {
    main(event: KeyboardEvent): void;
}

// enterキーのみ反応する
window.main = (event: KeyboardEvent) => {
    if(event.code == "Enter"){
        console.log("success typescript");
    }
};
```
```index.html
    <input type="input" class="keyword" placeholder="keyword" onkeydown="main(event)"></input>
```

成功！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1070645/4f17cb8b-05e1-6191-2f25-f0d2096cb06c.png)

# 4. ピンイン投入

```
npm install pinyin
```
（参考：https://www.npmjs.com/package/pinyin　）

# 5. jqueryで変換結果を画面に表示させる
**(1) jqueryのインストール**

```
npm i --save-dev @types/jquery
```
（参考：https://www.npmjs.com/package/jquery　）

```index.html
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</body>
```

**(2) js → html**
jsからの結果を受け取るタグを追加する。

```index.html
        <div id="pinyinResult"></div>
```
```index.ts
const pinyin = require("./pinyin.ts");

interface Window {
    main(event: KeyboardEvent): void;
}

window.main = (event: KeyboardEvent) => {
    if(event.code == "Enter"){
        pinyin.inputHtml();
    }
};
```
```pinyin.ts
const pinyin = require("pinyin");

function convertPinyin(keyword: string) : string {
    return pinyin(keyword);
}

export function inputHtml(){
    const keyword = $('.keyword').val() + "";
    const convertedKeyword = convertPinyin(keyword);

    let withoutComma = "";

    for(let convert of convertedKeyword){
        withoutComma += convert;
    }

    let html = `<h3>${withoutComma}</h3>`;

    // using jquery
    $("#pinyinResult").append(html);
}
```