我用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
我成功地创建了类似这样的聊天。
环境
-
- 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/ をブラウザで開く
我成功地运行了简易聊天。
感谢使用Studio 3T作为MongoDB的图形用户界面客户端进行创建。m(_ _)m
感谢您阅读至最后。m(_ _)m