Nguon: Microsoft Learn · .NET 8.0

Hướng dẫn: ASP.NET Core SignalR với TypeScript và Webpack

Nguồn: Tutorial: ASP.NET Core SignalR with TypeScript and Webpack

Hướng dẫn này trình bày cách xây dựng ứng dụng web ASP.NET Core SignalR sử dụng TypeScript và Webpack (công cụ đóng gói) để bundle (đóng gói) các tài nguyên phía client.

Tổng quan

Hướng dẫn này bao gồm:

Điều kiện tiên quyết

Yêu cầu chung

Cho Visual Studio

Cho Visual Studio Code

Thiết lập dự án

Tạo ASP.NET Core Web App

Visual Studio:

  1. File > New > Project/Solution
  2. Chọn template ASP.NET Core Empty
  3. Đặt tên dự án là SignalRWebpack
  4. Chọn .NET 8.0 (Long Term Support)

Visual Studio Code:

dotnetcli
dotnet new web -o SignalRWebpack
code -r SignalRWebpack

Cài đặt hỗ trợ TypeScript

Thêm NuGet package Microsoft.TypeScript.MSBuild:

dotnetcli
dotnet add package Microsoft.TypeScript.MSBuild

Cấu hình Server

1. Cấu hình Program.cs

Thêm SignalR services:

csharp
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSignalR();

Thêm static file serving (phục vụ file tĩnh):

csharp
var app = builder.Build();

app.UseDefaultFiles();
app.UseStaticFiles();

2. Tạo ChatHub

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);
}

3. Map Hub Route

Trong Program.cs:

csharp
using SignalRWebpack.Hubs;

// ... các cấu hình khác ...

app.MapHub<ChatHub>("/hub");

Cấu hình Client

1. Khởi tạo npm

console
npm init -y

2. Cập nhật package.json

json
{
  "name": "signalrwebpack",
  "version": "1.0.0",
  "private": true,
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack --mode=development --watch",
    "release": "webpack --mode=production",
    "publish": "npm run release && dotnet publish -c Release"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "type": "commonjs",
  "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": "^8.0.0",
    "@types/node": "^20.0.0"
  }
}

3. Cài đặt các npm Package

console
npm i -D -E clean-webpack-plugin css-loader html-webpack-plugin mini-css-extract-plugin ts-loader typescript webpack webpack-cli
npm i @microsoft/signalr @types/node

4. Tạo 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",
        }),
    ],
};

5. Tạo các Source File

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");

  const author = document.createElement("div");
  author.className = "message-author";
  author.textContent = username;

  const content = document.createElement("div");
  content.textContent = message;

  m.append(author, content);

  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

Build với Webpack

console
npm run release

Lệnh này:

Chạy ứng dụng

Visual Studio:

Visual Studio Code:

dotnetcli
dotnet run

Kiểm tra chức năng

  1. Mở ứng dụng trong một cửa sổ trình duyệt
  2. Mở một instance trình duyệt khác và điều hướng đến cùng URL
  3. Nhập tin nhắn vào hộp text và nhấn Enter hoặc click Send
  4. Xác minh tin nhắn xuất hiện ở cả hai cửa sổ trình duyệt với username (tên người dùng) duy nhất

Các khái niệm chính

Webpack Scripts

Giao tiếp SignalR

Tính năng TypeScript Client