8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

webpack4でTypeScript、Socket.IOの環境を作成してみた

Posted at

javascriptを趣味で勉強しているものです。間違いありましたら指摘お願いします

自分が作成したコード

1 インストール

yarn add socket.io express
yarn add -D typescript @types/socket.io @types/socket.io-client @types/express @types/node webpack webpack-cli ts-loader webpack-node-externals
  • socket.io
    • socket.io本体、Nodeサーバーで動く機能とブラウザで動く機能の両方がインストールされる
  • express
  • typescript
  • @types/socket.io
    • socket.io のNodeサーバーで動く機能の型定義
  • @types/socket.io-client
    • socket.io のブラウザで動く機能の型定義
  • @types/express
    • expressの型定義
  • @types/node
    • nodeのhttpモジュールを使用しているところ用の型定義
  • webpack
  • webpack-cli
  • ts-loader
  • webpack-node-externals
    • webpackで生成したファイルを、node bundle.jsと実行する場合にnode_modulesのファイルを一緒にバンドルしている必要はないので、node_modulesを無視して外部関数として扱うようにバンドルしてくれる

2 フォルダ構成

このようなフォルダ構成で作成してみました。

.
├ dist/ # webpackでバンドルしたファイルを出力(nodeサーバー用)
├ node_modules/
├ package.json
├ public/  # 静的ファイルを置く
│ ├ index.html
│ └ js/ # webpackでバンドルしたファイルを出力(ブラウザ用)
├ src/ # 実際に作業するファイル
│ ├ client/
│ │ └ index.ts
│ └ server/
│   └ index.ts
├ tsconfig.json
├ webpack.config.js
└ yarn.lock

Screen Shot 2019-06-09 at 11.png

3 webpack.config.js

webpack.config.js
const nodeExternals = require("webpack-node-externals");

module.exports = [{
    // ブラウザで動く機能をバンドル
    mode: "development",
    entry: {
        client: "./src/client/index.ts",
    },
    output: {
        filename: "[name].js",
        // expressでpublicフォルダ配下を静的に読む込むように設定するので、そこに出力する
        path: `${__dirname}/public/js`,
    },
    module: {
        rules: [{
            test: /\.ts$/,
            use: "ts-loader",
            exclude: /node_modules/,
        }]
    },
    resolve: {
        extensions: [".ts", ".js"]
    },
}, {
    // Nodeサーバーで動く機能をバンドル
    mode: "development",
    entry: {
        server: "./src/server/index.ts",
    },
    target: "node",
    node: {
        // expressを使うときにはこの設定をしないと失敗します
        // 参考:https://medium.com/@binyamin/creating-a-node-express-webpack-app-with-dev-and-prod-builds-a4962ce51334
        __dirname: false,
        __filename: false,
    },
    externals: [nodeExternals()],
    module: {
        rules: [{
            test: /\.ts$/,
            use: "ts-loader",
            exclude: /node_modules/,
        }]
    },
    resolve: {
        extensions: [".ts", ".js"]
    },
}];

socket.ioはnodeサーバーで動く機能とブラウザで動く機能があるため、設定を分ける必要があります。
設定ファイルを2つにするとかでもいいのですが、今回は↑のようなやり方で2つの設定を書きました。

複数の設定をエクスポートする
参考:https://webpack.js.org/configuration/configuration-types/#exporting-multiple-configurations

4 tsconfig.json

tsconfig.json
{
    "compilerOptions": {
      "outDir": "./dist/",
      "noImplicitAny": true,
      "module": "es6",
      "target": "es5",
      "allowJs": true
    }
}

あまり詳しくないので、こちらを参考にして、ほぼそのままです(^_^;)

5 簡易チャット作成

5-1 サーバ作成

src/server/index.ts
import * as express from "express";
import * as http from "http";
import * as socketio from "socket.io";

const app: express.Express = express();
const server: http.Server = http.createServer(app);
const io: socketio.Server = socketio(server);

app.use(express.static("public"));

io.on("connection", (socket: socketio.Socket) => {
    socket.on("hoge_message", (msg: string) => {
        io.emit("hoge_message", msg);
    });
});

server.listen(3000, () => console.log("listening on *:3000"));

expressでサーバを作成し、publicフォルダ配下を静的ファイルとしてアクセスできるようにします。

5-2 ブラウザ側を作成

public/index.html
<!DOCTYPE html>
<meta charset="UTF-8">
<title>Document</title>
<script src="js/client.js" defer></script>
<form><input><button>Send</button></form>
<ul></ul>
src/client/index.ts
import * as io from "socket.io-client";
const socket: SocketIOClient.Socket = io();

const form: HTMLFormElement = document.querySelector("form");
const input: HTMLInputElement = document.querySelector("input");
const ul: HTMLUListElement = document.querySelector("ul");

form.addEventListener("submit", (e: Event) => {
    e.preventDefault();
    socket.emit("hoge_message", input.value);
    input.value = "";
});

socket.on("hoge_message", (msg: string) => {
    ul.insertAdjacentHTML("beforebegin", `<li>${msg}</li>`);
});

5-3 実行

bash
yarn webpack #dist/server.jsとpublic/js/client.jsが出力
node dist/server.js #サーバ起動

http://localhost:3000/ を開いてsocket.ioがうまく動いていることを確認できました。

vdWDonVtHX.gif

6 ファイル監視

6-1 webpack -w

yarn webpack -wとウォッチモードで実行すれば、ファイルを監視してくれて、ファイルに変更を加えるたびにバンドルし直してくれますね。
しかしそれだけだと、サーバーの方のファイルは変更するたびに、Ctrl+Cでサーバーを切り、もう一度server.jsを実行しないと変更が反映されません。なのでnodemonを使ってみます。

6-2 nodemonを使う

nodemonを使えば、サーバー側のファイルを変更するたびに自動でサーバーを再起動してくれます。

yarn add -D nodemon-webpack-plugin

webpack.config.jsに設定を追加します

const NodemonPlugin = require("nodemon-webpack-plugin");

// ..

    plugins: [
        new NodemonPlugin(),
    ],

// ..

全体ではこうなりました

webpack.config.js
const nodeExternals = require("webpack-node-externals");
const NodemonPlugin = require("nodemon-webpack-plugin");

module.exports = [{
    // ブラウザで動く機能をバンドル
    mode: "development",
    entry: {
        client: "./src/client/index.ts",
    },
    output: {
        filename: "[name].js",
        // expressでpublicフォルダ配下を静的に読む込むように設定するので、そこに出力する
        path: `${__dirname}/public/js`,
    },
    module: {
        rules: [{
            test: /\.ts$/,
            use: "ts-loader",
            exclude: /node_modules/,
        }]
    },
    resolve: {
        extensions: [".ts", ".js"]
    },
}, {
    // Nodeサーバーで動く機能をバンドル
    mode: "development",
    entry: {
        server: "./src/server/index.ts",
    },
    target: "node",
    node: {
        // expressを使うときにはこの設定をしないと失敗します
        // 参考:https://medium.com/@binyamin/creating-a-node-express-webpack-app-with-dev-and-prod-builds-a4962ce51334
        __dirname: false,
        __filename: false,
    },
    externals: [nodeExternals()],
    module: {
        rules: [{
            test: /\.ts$/,
            use: "ts-loader",
            exclude: /node_modules/,
        }]
    },
    plugins: [
        new NodemonPlugin(),
    ],
    resolve: {
        extensions: [".ts", ".js"]
    },
}];

この状態でyarn webpack -wとします。(※nodemon-webpack-pluginはウォッチモードの時のみ動作してくれます)

91w2XiusLF.gif

yarn webpack -wを実行すると自動でサーバーが起動し、その後ファイルを変更するとサーバーが再起動され、変更が反映されていることを確認できました。


最後まで読んでいただいてありがとうございました。m(_ _)m

8
9
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
8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?