Nguon: Microsoft Learn · .NET 8.0
Hướng dẫn: Bắt đầu với ASP.NET Core SignalR sử dụng TypeScript và Webpack
Hướng dẫn này mô tả cách xây dựng ứng dụng web ASP.NET Core SignalR sử dụng TypeScript (ngôn ngữ lập trình có kiểu tĩnh mở rộng JavaScript) và Webpack (công cụ đóng gói module) để đóng gói và biên dịch tài nguyên phía client.
Tổng quan
Hướng dẫn này minh họa cách:
- Tạo ứng dụng ASP.NET Core SignalR (thư viện giao tiếp thời gian thực)
- Cấu hình server SignalR
- Cấu hình pipeline (quy trình) biên dịch sử dụng Webpack
- Cấu hình client TypeScript cho SignalR
- Thiết lập giao tiếp giữa client và server
Điều kiện tiên quyết
- Node.js cùng với npm
- Visual Studio 2022 trở lên với workload (gói công việc) ASP.NET và web development, HOẶC
- Visual Studio Code với C# Dev Kit và .NET SDK
Các bước cấu hình chính
1. Tạo ứng dụng web ASP.NET Core
Tạo một dự án ASP.NET Core rỗng và thêm gói NuGet Microsoft.TypeScript.MSBuild để bật tính năng biên dịch TypeScript.
2. Cấu hình Server
Trong file Program.cs:
csharp
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSignalR();
var app = builder.Build();
app.UseDefaultFiles();
app.UseStaticFiles();
app.MapHub<ChatHub>("/hub");3. Tạo SignalR Hub (trung tâm SignalR)
Tạo file Hubs/ChatHub.cs:
csharp
using Microsoft.AspNetCore.SignalR;
namespace SignalRWebpack.Hubs;
public class ChatHub : Hub
{
public async Task NewMessage(long username, string message) =>
await Clients.All.SendAsync("messageReceived", username, message);
}4. Cấu hình pipeline biên dịch phía client
Tạo file package.json với các npm scripts (lệnh chạy npm):
json
{
"name": "signalrwebpack",
"version": "1.0.0",
"private": true,
"scripts": {
"build": "webpack --mode=development --watch",
"release": "webpack --mode=production",
"publish": "npm run release && dotnet publish -c Release"
},
"devDependencies": {
"clean-webpack-plugin": "4.0.0",
"css-loader": "7.1.3",
"html-webpack-plugin": "5.6.6",
"mini-css-extract-plugin": "2.10.0",
"ts-loader": "9.5.4",
"typescript": "5.9.3",
"webpack": "5.104.1",
"webpack-cli": "6.0.1"
},
"dependencies": {
"@microsoft/signalr": "^10.0.0",
"@types/node": "^25.0.10"
}
}5. Cấu hình Webpack
Tạo file webpack.config.js:
javascript
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: "./src/index.ts",
output: {
path: path.resolve(__dirname, "wwwroot"),
filename: "[name].[chunkhash].js",
publicPath: "/",
},
resolve: {
extensions: [".js", ".ts"],
},
module: {
rules: [
{
test: /\.ts$/,
use: "ts-loader",
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: "./src/index.html",
}),
new MiniCssExtractPlugin({
filename: "css/[name].[chunkhash].css",
}),
],
};6. Các file nguồn phía client
Tạo thư mục src với các file sau:
src/index.html:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>ASP.NET Core SignalR with TypeScript and Webpack</title>
</head>
<body>
<div id="divMessages" class="messages"></div>
<div class="input-zone">
<label id="lblMessage" for="tbMessage">Message:</label>
<input id="tbMessage" class="input-zone-input" type="text" />
<button id="btnSend">Send</button>
</div>
</body>
</html>src/css/main.css:
css
*,
*::before,
*::after {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
}
.input-zone {
align-items: center;
display: flex;
flex-direction: row;
margin: 10px;
}
.input-zone-input {
flex: 1;
margin-right: 10px;
}
.message-author {
font-weight: bold;
}
.messages {
border: 1px solid #000;
margin: 10px;
max-height: 300px;
min-height: 300px;
overflow-y: auto;
padding: 5px;
}src/tsconfig.json:
json
{
"compilerOptions": {
"target": "es5"
}
}src/index.ts:
typescript
import * as signalR from "@microsoft/signalr";
import "./css/main.css";
const divMessages: HTMLDivElement = document.querySelector("#divMessages");
const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
const username = new Date().getTime();
const connection = new signalR.HubConnectionBuilder()
.withUrl("/hub")
.build();
connection.on("messageReceived", (username: string, message: string) => {
const m = document.createElement("div");
m.innerHTML = `<div class="message-author">${username}</div><div>${message}</div>`;
divMessages.appendChild(m);
divMessages.scrollTop = divMessages.scrollHeight;
});
connection.start().catch((err) => document.write(err));
tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {
if (e.key === "Enter") {
send();
}
});
btnSend.addEventListener("click", send);
function send() {
connection.send("newMessage", username, tbMessage.value)
.then(() => (tbMessage.value = ""));
}Kiểm tra ứng dụng
- Chạy
npm run releaseđể biên dịch các tài nguyên phía client ở chế độ production - Chạy ứng dụng bằng
dotnet runhoặc thông qua Visual Studio - Mở ứng dụng trong trình duyệt tại
https://localhost:<port> - Mở thêm một tab/trình duyệt khác và kiểm tra việc gửi tin nhắn thời gian thực giữa các client
Hướng dẫn bao gồm các chỉ dẫn chi tiết cho cả Visual Studio và Visual Studio Code.