我用Webpack创建了一个简单的聊天应用,使用了TypeScript、Express、Mongoose和Bootstrap

我是JavaScript和MongoDB的初学者。在不清楚的地方,我一边搜索一边进行了编写。如果有任何错误,请告诉我,我将非常感激。

    How to build a real time chat application in Node.js using Express, Mongoose and Socket.io

在这个链接中,我找到了关于express和mongodb的教程,并尝试用Typescript自己重写了它。请多关照。m(_ _)m

我成功地创建了类似这样的聊天。

Screen Shot 2019-08-12 at 12.07.51.png

环境

    • macOS Mojave 10.14.5

 

    • node 12.7.0

 

    MongoDB 4.0.3

下面是我实际创建的代码,您可以参考:

安装MongoDB

    HomebrewでMacにMongoDBをインストールした時のメモ – Qiita

根据这个链接,我已经安装了MongoDB。m(_ _)m

#参考リンクにあるように、こちらでmongodbを起動している状態にしておきます。
sudo mongod --dbpath /var/lib/mongodb --logpath /var/log/mongodb.log

安装

yarn add express mongoose socket.io bootstrap
yarn add -D webpack webpack-cli webpack-merge webpack-node-externals nodemon-webpack-plugin typescript ts-loader @types/express @types/mongoose @types/node @types/socket.io @types/socket.io-client @types/webpack css-loader style-loader
    • express

 

    • mongoose

 

    • socket.io

 

    • bootstrap

 

    • webpack

 

    • webpack-cli

 

    • webpack-merge

webpackの共通設定をマージしてくれて、見やすくなる。

webpack-node-externals

サーバー側をバンドルする時に使う、node_modulesを無視して外部関数として扱うようにバンドルしてくれる

nodemon-webpack-plugin

開発時に便利なnodemonのwebpack用プラグイン

typescript
ts-loader
@types/express
@types/mongoose
@types/node

nodeのhttpモジュールも一部使うときに使用する型定義

@types/socket.io

socket.ioのサーバーで動く機能の型定義

@types/socket.io-client

socket.ioのブラウザで動く機能の型定義

@types/webpack

webpack.config.jsで補完が効くようにするためだけなので、なくてもOK

css-loader

bootstrapのcssをjsから読み取るので必要

style-loader

bootstrapのcssをjsから読み取るので必要

webpack配置文件

const merge = require("webpack-merge");
const nodeExternals = require("webpack-node-externals");
const NodemonPlugin = require("nodemon-webpack-plugin");

/** @type import("webpack").Configuration */
const baseConfig = {
    mode: process.env.NODE_ENV || "development",
    module: {
        rules: [
            {
                test: /\.ts$/,
                use: "ts-loader",
            },
        ],
    },
    resolve: {
        extensions: [".js", ".ts"],
    },
};
module.exports = [
    // ブラウザで動く機能をバンドル
    merge(baseConfig, {
        entry: "./src/client",
        output: {
            filename: "client.js",
            path: `${__dirname}/dist`,
        },
        module: {
            rules: [
                {
                    // bootstrapのcssを読み込む際に必要
                    test: /\.css$/,
                    use: ["style-loader", "css-loader"]
                }
            ]
        }
    }),
    // Nodeサーバーで動く機能をバンドル
    merge(baseConfig, {
        entry: "./src/server",
        output: {
            filename: "server.js",
            path: `${__dirname}/dist`,
        },
        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: [
            // webpackで生成したファイルを、`node bundle.js` と実行する場合に
            // node_modulesのファイルを一緒にバンドルしている必要はないので、
            // node_modulesを無視して外部関数として扱うようにバンドルしてくれる
            nodeExternals()
        ],
        plugins: [
            // nodeのサーバ用のjsファイルを編集した時に自動でサーバを再起動してくれる
            // nodemonのwebpack用のプラグイン
            new NodemonPlugin(),
        ],
    }),
];

tsconfig.json的同义词:配置文件.json

こちらを参考にして設定しました。間違っていたら教えていただきたいです。m(_ _)m

    • https://webpack.js.org/guides/typescript/

 

    https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
{
  "compilerOptions": {
    "target": "es5",
    "module": "esnext",
    "strict": true,
    "allowJs": true,
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ]
}

サーバー側を作成

import * as express from "express";
import * as http from "http";
import * as net from "net";
import * as socketio from "socket.io";
import * as mongoose from "mongoose";

import { ISendMsg } from "./global";

interface ISendMsgModel extends mongoose.Document, ISendMsg {}

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

let Message: mongoose.Model<ISendMsgModel>;

(async () => {
    try {
        await mongoose.connect("mongodb://localhost/simple-chat");
        Message = mongoose.model<ISendMsgModel>("Message", new mongoose.Schema({ name: String, message: String }))
    } catch (err) {
        console.log(err)
    }
})();

app.use(express.static(`${__dirname}/../`));

app.get("/messages", async (req: express.Request, res: express.Response) => {
    try {
        const messages = await Message.find({});
        res.send(messages);
    } catch (err) {
        console.log(err)
    }
})

io.on("connection", (socket: socketio.Socket) => {
    socket.on("message", async (msg: ISendMsg) => {
        try {
            const message = new Message(msg);
            await message.save();
            io.emit("message", msg);
        } catch (err) {
            console.log(err)
        }
    });
})

server.listen(3000, () => {
    console.log(`server is running on port ${(server.address() as net.AddressInfo).port}`);
});

メッセージの内容は共通の設定なのでglobal.d.tsに定義してみました。

export interface ISendMsg {
    name: string;
    message: string;
}

创建浏览器端

import * as io from "socket.io-client";
import "bootstrap/dist/css/bootstrap.min.css";

import { ISendMsg } from "./global";

const input: HTMLInputElement = <HTMLInputElement>document.getElementById("name");
const message: HTMLTextAreaElement = <HTMLTextAreaElement>document.getElementById("message");
const send: HTMLButtonElement = <HTMLButtonElement>document.getElementById("send");
const messages: HTMLDivElement = <HTMLDivElement>document.getElementById("messages");

const socket: SocketIOClient.Socket = io();

(async () => {
    const res = await fetch("http://localhost:3000/messages");
    const data: ISendMsg[] = await res.json();
    data.forEach(addMessages);
})();

send.addEventListener("click", () => {
    socket.emit("message", { name: input.value, message: message.value });
});

socket.on("message", addMessages)

function addMessages({ name, message }: ISendMsg) {
    messages.insertAdjacentHTML("beforeend", `
        <h4> ${name} </h4>
        <p>  ${message} </p>
    `);
}
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Hello, world!</title>
<script src="dist/client.js" defer></script>
</head>
<body>
    <div class="container p-5">
        <div class="jumbotron">
            <h1 class="display-4">Send Message</h1>
            <br>
            <input id="name" class="form-control" placeholder="Name">
            <br>
            <textarea id="message" class="form-control" placeholder="Your Message Here"></textarea>
            <br>
            <button id="send" class="btn btn-success">Send</button>
        </div>
        <div id="messages"></div>
    </div>
</body>
</html>

实行

yarn webpack -w #http://localhost:3000/ をブラウザで開く
EDyJFoqPv5.gif

我成功地运行了简易聊天。


感谢使用Studio 3T作为MongoDB的图形用户界面客户端进行创建。m(_ _)m


感谢您阅读至最后。m(_ _)m

广告
将在 10 秒后关闭
bannerAds