Учебник. Начало работы с ASP.NET Core SignalR с использованием TypeScript и Webpack.

Примечание.

Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 8 этой статьи.

Внимание

Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

В текущем выпуске см . версию .NET 8 этой статьи.

Себастиен Сугнес

В этом учебнике демонстрируется использование средства Webpack для создания пакета и сборки веб-приложения ASP.NET Core SignalR, а также объединения и создания клиента, который написан на языке TypeScript. С помощью средства Webpack разработчики могут создавать пакеты и выполнять сборку ресурсов на стороне клиента для веб-приложения.

В этом руководстве описано следующее:

  • Создание приложения ASP.NET Core SignalR
  • настроить сервер SignalR.
  • Настроить конвейер сборки с использованием Webpack
  • настроить клиент TypeScript SignalR;
  • Включение обмена данными между клиентом и сервером.

Просмотреть или скачать образец кода (описание загрузки)

Необходимые компоненты

  • Visual Studio 2022 с рабочей нагрузкой ASP.NET и веб-разработка.

    Рабочие нагрузки установщика VS22

Создание веб-приложения ASP.NET Core

По умолчанию Visual Studio использует версию npm, которая находится в его каталоге установки. Настройка Visual Studio на поиск npm в переменной среды PATH:

Запустите Visual Studio. В начальном окне выберите Продолжить без кода.

  1. Выберите Сервис>Параметры>Проекты и решения>Управление веб-пакетами>Внешние веб-инструменты.

  2. $(PATH) Выберите запись из списка. Щелкните стрелку вверх, чтобы переместить этот элемент на вторую позицию в списке, и нажмите OK.

    Конфигурация Visual Studio.

Создание веб-приложения ASP.NET Core:

  1. Перейдите в меню Файл>Создать>Проект и выберите шаблон Пустой шаблон ASP.NET Core. Выберите Далее.
  2. Задайте для проекта имя SignalRWebpack и нажмите кнопку Создать.
  3. Выберите .NET 8.0 (долгосрочная поддержка) в раскрывающемся списке Платформы . Нажмите кнопку создания.

Добавьте в проект пакет NuGet Microsoft.TypeScript.MSBuild.

  1. В обозревателе решений щелкните правой кнопкой мыши узел проекта и выберите Управление пакетами NuGet. На вкладке Обзор найдите Microsoft.TypeScript.MSBuild, а затем нажмите кнопку Установить справа, чтобы установить пакет.

Visual Studio добавляет пакет NuGet в узел Зависимости в обозревателе решений, разрешая компиляцию TypeScript в проекте.

настроить сервер .

В этом разделе вы настроите веб-приложение ASP.NET Core для отправки и получения сообщений SignalR.

  1. В Program.cs вызовите AddSignalR.

    var builder = WebApplication.CreateBuilder(args);
    
    builder.Services.AddSignalR();
    
  2. В Program.cs снова вызовите UseDefaultFiles и UseStaticFiles:

    var app = builder.Build();
    
    app.UseDefaultFiles();
    app.UseStaticFiles();
    

    Приведенный выше код позволяет серверу находить и обслуживать index.html файл. Файл обрабатывается независимо от того, вводит ли пользователь полный или корневой URL-адрес веб-приложения.

  3. Создайте новый каталог с именем Hubs в корневом каталоге проекта SignalRWebpack/ для хранения класса концентратора SignalR.

  4. Создайте файл Hubs/ChatHub.cs со следующим кодом:

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

    Приведенный выше код осуществляет широковещательную рассылку полученных сервером сообщений всем подключенным пользователям. Универсальный метод on для получения всех сообщений не требуется. Имя метода указывается после суффиксов имени сообщения.

    В этом примере:

    • Клиент TypeScript отправляет сообщение, определенное как newMessage.
    • Метод C# NewMessage ожидает данные, отправленные клиентом.
    • Выполняется вызов метода SendAsync для Clients.All.
    • Полученные сообщения отправляются всем клиентам, подключенным к концентратору.
  5. Добавьте следующий оператор using в самое начало Program.cs, чтобы разрешить ссылку ChatHub:

    using SignalRWebpack.Hubs;
    
  6. В Program.cs сопоставьте маршрут /hub с концентратором ChatHub. Замените код, отображающий сообщение Hello World!, следующим кодом:

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

Настройка клиента

В этом разделе вы создадите проект Node.js для преобразования TypeScript в JavaScript и объединения ресурсов на стороне клиента, включая HTML и CSS, с помощью Webpack.

  1. Выполните следующую команду в корневом package.json каталоге проекта, чтобы создать файл:

    npm init -y
    
  2. Добавьте выделенное свойство в package.json файл и сохраните изменения файла:

    {
      "name": "SignalRWebpack",
      "version": "1.0.0",
      "private": true,
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }
    

    Если свойству private присвоено значение true, на следующем шаге не будут отображаться предупреждения об установке пакета.

  3. Установите необходимые пакеты npm. Выполните следующую команду из корневого каталога проекта:

    npm i -D -E clean-webpack-plugin css-loader html-webpack-plugin mini-css-extract-plugin ts-loader typescript webpack webpack-cli
    

    Использование параметра -E позволяет отключить установленное по умолчанию поведение npm, предусматривающее запись операторов диапазона семантического управления версиями в файл package.json. Например, "webpack": "5.76.1" используется вместо "webpack": "^5.76.1". Этот параметр позволяет исключить непреднамеренное обновление до более новых версий пакета.

    Дополнительные сведения см. в npm-install.

  4. Замените свойство scripts в файле package.json следующим кодом:

    "scripts": {
      "build": "webpack --mode=development --watch",
      "release": "webpack --mode=production",
      "publish": "npm run release && dotnet publish -c Release"
    },
    

    Определены следующие скрипты:

    • build: объединяет клиентские ресурсы в режиме разработки и проверяет изменения файлов. Наблюдатель за файлами выполняет повторное создание пакета при каждом изменении файла проекта. Параметр mode позволяет отключить оптимизации в рабочей среде, такие как встряхивание дерева и минификация. build используется только в среде разработки.
    • release: объединяет клиентские ресурсы в рабочем режиме.
    • publish. Запускает скрипт release для создания пакета ресурсов на стороне клиента в рабочем режиме. Этот скрипт вызывает команду publish интерфейса командной строки .NET для публикации приложения.
  5. Создайте файл с именем webpack.config.js в корневом каталоге проекта с помощью следующего кода:

    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",
            }),
        ],
    };
    

    Приведенный выше файл определяет конфигурацию процесса компиляции Webpack.

    • Свойство output переопределяет значение distпо умолчанию. Пакет вместо этого создается в каталоге wwwroot .
    • Массив resolve.extensions включает в себя .js импорт клиентского SignalR JavaScript.
  6. Создайте каталог с именем src в корневом каталоге SignalRWebpack/проекта для клиентского кода.

  7. src Скопируйте каталог и его содержимое из примера проекта в корневой каталог проекта. Каталог src содержит следующие файлы:

    • index.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>
      
    • 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;
      }
      
    • tsconfig.json, который определяет конфигурацию компилятора TypeScript для получения совместимого с ECMAScript 5 кода JavaScript.

      {
        "compilerOptions": {
          "target": "es5"
        }
      }
      
    • index.ts:

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

      Приведенный выше код извлекает ссылки на элементы модели DOM и присоединяет два обработчика событий:

      • keyup: срабатывает, когда пользователь вводит данные в текстовое поле tbMessage, и вызывает функцию send при нажатии пользователем клавиши Enter.
      • click: срабатывает, когда пользователь нажимает кнопку Отправить и вызывается функцию send.

      Класс HubConnectionBuilder создает новый построитель для настройки подключения к серверу. Функция withUrl настраивает URL-адрес концентратора.

      SignalR обеспечивает обмен сообщениями между клиентом и сервером. Каждому сообщению присваивается определенное имя. Например, сообщения с именем messageReceived могут выполнять логику отображения новых сообщений в соответствующей зоне. Прослушивание определенных сообщений реализуется с помощью функции on. Возможно прослушивание любого числа имен сообщений. Кроме того, можно передавать параметры сообщения, например имя его автора или содержимое полученного сообщения. После того как клиент получает сообщение, создается новый элемент div, в атрибуте innerHTML которого содержатся имя автора и содержимое сообщения. Этот элемент добавляется в основной элемент div, который используется для отображения сообщений.

      Для отправки сообщения через соединение WebSockets необходимо вызвать метод send. Первый параметр этого метода содержит имя сообщения. Другие параметры заполняются данными сообщения. В этом примере на сервер отправляется сообщение, идентифицированное как newMessage. Это сообщение содержит имя пользователя, а также данные, введенные этим пользователем в текстовое поле. Если отправка выполняется успешно, значение текстового поля очищается.

  8. Выполните следующую команду в корневом элементе проекта:

    npm i @microsoft/signalr @types/node
    

    Предыдущая команда устанавливает:

    • Клиент TypeScript SignalR, который позволяет клиенту отправлять сообщения на сервер.
    • Определения типа TypeScript для Node.js, обеспечивающие проверку типов Node.js во время компиляции.

Тестирование приложения

Чтобы проверить работоспособность приложения, выполните следующие шаги.

  1. Запустите Webpack в release режиме. Выполните следующие команды в окне Консоль диспетчера пакетов в корневом элементе проекта.

    npm run release
    

    Эта команда создает ресурсы на стороне клиента, которые будут обслуживаться при выполнении приложения. Ресурсы помещаются в папку wwwroot .

    Веб-пакет выполнил следующие задачи:

    • Очистка содержимого wwwroot каталога.
    • Преобразование TypeScript в JavaScript (этот процесс называется транспилированием).
    • Корректировка созданного кода JavaScript в целях уменьшения размера файла (этот процесс называется минификацией).
    • Скопированы обработанные файлы JavaScript, CSS и HTML из srcwwwroot каталога.
    • В файл ввели следующие элементы wwwroot/index.html :
      • Тег <link>, ссылающийся на файл wwwroot/main.<hash>.css. Этот тег размещается непосредственно после закрывающего тега </head>.
      • Тег <script>, ссылающийся на минифицированный файл wwwroot/main.<hash>.js. Этот тег помещается сразу после закрывающего </title> тега.
  2. Выберите Отладка>Запуск без отладки, чтобы запустить приложение в браузере, не присоединяя отладчик. Файл wwwroot/index.html обрабатывается по адресу https://localhost:<port>.

    Если возникают ошибки компиляции, попробуйте закрыть и повторно открыть решение.

  3. Откройте другой экземпляр браузера (любого) и вставьте URL-адрес в адресную строку.

  4. Выберите любой браузер, введите произвольный текст в поле Сообщение и нажмите кнопку Отправить. На обеих страницах мгновенно отображаются имя пользователя и сообщение.

Сообщение, отображаемое в обоих окнах браузера

Следующие шаги

Дополнительные ресурсы

В этом учебнике демонстрируется использование средства Webpack для создания пакета и сборки веб-приложения ASP.NET Core SignalR, а также объединения и создания клиента, который написан на языке TypeScript. С помощью средства Webpack разработчики могут создавать пакеты и выполнять сборку ресурсов на стороне клиента для веб-приложения.

В этом руководстве описано следующее:

  • Создание приложения ASP.NET Core SignalR
  • настроить сервер SignalR.
  • Настроить конвейер сборки с использованием Webpack
  • настроить клиент TypeScript SignalR;
  • Включение обмена данными между клиентом и сервером.

Просмотреть или скачать образец кода (описание загрузки)

Необходимые компоненты

  • Visual Studio 2022 с рабочей нагрузкой ASP.NET и веб-разработка.

    Рабочие нагрузки установщика VS22

Создание веб-приложения ASP.NET Core

По умолчанию Visual Studio использует версию npm, которая находится в его каталоге установки. Настройка Visual Studio на поиск npm в переменной среды PATH:

Запустите Visual Studio. В начальном окне выберите Продолжить без кода.

  1. Выберите Сервис>Параметры>Проекты и решения>Управление веб-пакетами>Внешние веб-инструменты.

  2. $(PATH) Выберите запись из списка. Щелкните стрелку вверх, чтобы переместить этот элемент на вторую позицию в списке, и нажмите OK.

    Конфигурация Visual Studio.

Создание веб-приложения ASP.NET Core:

  1. Перейдите в меню Файл>Создать>Проект и выберите шаблон Пустой шаблон ASP.NET Core. Выберите Далее.
  2. Задайте для проекта имя SignalRWebpack и нажмите кнопку Создать.
  3. Выберите .NET 7.0 (Standard Term Support) в раскрывающемся меню Платформа. Нажмите кнопку создания.

Добавьте в проект пакет NuGet Microsoft.TypeScript.MSBuild.

  1. В обозревателе решений щелкните правой кнопкой мыши узел проекта и выберите Управление пакетами NuGet. На вкладке Обзор найдите Microsoft.TypeScript.MSBuild, а затем нажмите кнопку Установить справа, чтобы установить пакет.

Visual Studio добавляет пакет NuGet в узел Зависимости в обозревателе решений, разрешая компиляцию TypeScript в проекте.

настроить сервер .

В этом разделе вы настроите веб-приложение ASP.NET Core для отправки и получения сообщений SignalR.

  1. В Program.cs вызовите AddSignalR.

    var builder = WebApplication.CreateBuilder(args);
    
    builder.Services.AddSignalR();
    
  2. В Program.cs снова вызовите UseDefaultFiles и UseStaticFiles:

    var app = builder.Build();
    
    app.UseDefaultFiles();
    app.UseStaticFiles();
    

    Приведенный выше код позволяет серверу находить и обслуживать index.html файл. Файл обрабатывается независимо от того, вводит ли пользователь полный или корневой URL-адрес веб-приложения.

  3. Создайте новый каталог с именем Hubs в корневом каталоге проекта SignalRWebpack/ для хранения класса концентратора SignalR.

  4. Создайте файл Hubs/ChatHub.cs со следующим кодом:

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

    Приведенный выше код осуществляет широковещательную рассылку полученных сервером сообщений всем подключенным пользователям. Универсальный метод on для получения всех сообщений не требуется. Имя метода указывается после суффиксов имени сообщения.

    В этом примере:

    • Клиент TypeScript отправляет сообщение, определенное как newMessage.
    • Метод C# NewMessage ожидает данные, отправленные клиентом.
    • Выполняется вызов метода SendAsync для Clients.All.
    • Полученные сообщения отправляются всем клиентам, подключенным к концентратору.
  5. Добавьте следующий оператор using в самое начало Program.cs, чтобы разрешить ссылку ChatHub:

    using SignalRWebpack.Hubs;
    
  6. В Program.cs сопоставьте маршрут /hub с концентратором ChatHub. Замените код, отображающий сообщение Hello World!, следующим кодом:

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

Настройка клиента

В этом разделе вы создадите проект Node.js для преобразования TypeScript в JavaScript и объединения ресурсов на стороне клиента, включая HTML и CSS, с помощью Webpack.

  1. Выполните следующую команду в корневом package.json каталоге проекта, чтобы создать файл:

    npm init -y
    
  2. Добавьте выделенное свойство в package.json файл и сохраните изменения файла:

    {
      "name": "SignalRWebpack",
      "version": "1.0.0",
      "private": true,
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }
    

    Если свойству private присвоено значение true, на следующем шаге не будут отображаться предупреждения об установке пакета.

  3. Установите необходимые пакеты npm. Выполните следующую команду из корневого каталога проекта:

    npm i -D -E clean-webpack-plugin css-loader html-webpack-plugin mini-css-extract-plugin ts-loader typescript webpack webpack-cli
    

    Использование параметра -E позволяет отключить установленное по умолчанию поведение npm, предусматривающее запись операторов диапазона семантического управления версиями в файл package.json. Например, "webpack": "5.76.1" используется вместо "webpack": "^5.76.1". Этот параметр позволяет исключить непреднамеренное обновление до более новых версий пакета.

    Дополнительные сведения см. в npm-install.

  4. Замените свойство scripts в файле package.json следующим кодом:

    "scripts": {
      "build": "webpack --mode=development --watch",
      "release": "webpack --mode=production",
      "publish": "npm run release && dotnet publish -c Release"
    },
    

    Определены следующие скрипты:

    • build: объединяет клиентские ресурсы в режиме разработки и проверяет изменения файлов. Наблюдатель за файлами выполняет повторное создание пакета при каждом изменении файла проекта. Параметр mode позволяет отключить оптимизации в рабочей среде, такие как встряхивание дерева и минификация. build используется только в среде разработки.
    • release: объединяет клиентские ресурсы в рабочем режиме.
    • publish. Запускает скрипт release для создания пакета ресурсов на стороне клиента в рабочем режиме. Этот скрипт вызывает команду publish интерфейса командной строки .NET для публикации приложения.
  5. Создайте файл с именем webpack.config.js в корневом каталоге проекта с помощью следующего кода:

    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",
            }),
        ],
    };
    

    Приведенный выше файл определяет конфигурацию процесса компиляции Webpack.

    • Свойство output переопределяет значение distпо умолчанию. Пакет вместо этого создается в каталоге wwwroot .
    • Массив resolve.extensions включает в себя .js импорт клиентского SignalR JavaScript.
  6. src Скопируйте каталог и его содержимое из примера проекта в корневой каталог проекта. Каталог src содержит следующие файлы:

    • index.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>
      
    • 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;
      }
      
    • tsconfig.json, который определяет конфигурацию компилятора TypeScript для получения совместимого с ECMAScript 5 кода JavaScript.

      {
        "compilerOptions": {
          "target": "es5"
        }
      }
      
    • index.ts:

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

      Приведенный выше код извлекает ссылки на элементы модели DOM и присоединяет два обработчика событий:

      • keyup: срабатывает, когда пользователь вводит данные в текстовое поле tbMessage, и вызывает функцию send при нажатии пользователем клавиши Enter.
      • click: срабатывает, когда пользователь нажимает кнопку Отправить и вызывается функцию send.

      Класс HubConnectionBuilder создает новый построитель для настройки подключения к серверу. Функция withUrl настраивает URL-адрес концентратора.

      SignalR обеспечивает обмен сообщениями между клиентом и сервером. Каждому сообщению присваивается определенное имя. Например, сообщения с именем messageReceived могут выполнять логику отображения новых сообщений в соответствующей зоне. Прослушивание определенных сообщений реализуется с помощью функции on. Возможно прослушивание любого числа имен сообщений. Кроме того, можно передавать параметры сообщения, например имя его автора или содержимое полученного сообщения. После того как клиент получает сообщение, создается новый элемент div, в атрибуте innerHTML которого содержатся имя автора и содержимое сообщения. Этот элемент добавляется в основной элемент div, который используется для отображения сообщений.

      Для отправки сообщения через соединение WebSockets необходимо вызвать метод send. Первый параметр этого метода содержит имя сообщения. Другие параметры заполняются данными сообщения. В этом примере на сервер отправляется сообщение, идентифицированное как newMessage. Это сообщение содержит имя пользователя, а также данные, введенные этим пользователем в текстовое поле. Если отправка выполняется успешно, значение текстового поля очищается.

  7. Выполните следующую команду в корневом элементе проекта:

    npm i @microsoft/signalr @types/node
    

    Предыдущая команда устанавливает:

    • Клиент TypeScript SignalR, который позволяет клиенту отправлять сообщения на сервер.
    • Определения типа TypeScript для Node.js, обеспечивающие проверку типов Node.js во время компиляции.

Тестирование приложения

Чтобы проверить работоспособность приложения, выполните следующие шаги.

  1. Запустите Webpack в release режиме. Выполните следующие команды в окне Консоль диспетчера пакетов в корневом элементе проекта.

    npm run release
    

    Эта команда создает ресурсы на стороне клиента, которые будут обслуживаться при выполнении приложения. Ресурсы помещаются в папку wwwroot .

    Веб-пакет выполнил следующие задачи:

    • Очистка содержимого wwwroot каталога.
    • Преобразование TypeScript в JavaScript (этот процесс называется транспилированием).
    • Корректировка созданного кода JavaScript в целях уменьшения размера файла (этот процесс называется минификацией).
    • Скопированы обработанные файлы JavaScript, CSS и HTML из srcwwwroot каталога.
    • В файл ввели следующие элементы wwwroot/index.html :
      • Тег <link>, ссылающийся на файл wwwroot/main.<hash>.css. Этот тег размещается непосредственно после закрывающего тега </head>.
      • Тег <script>, ссылающийся на минифицированный файл wwwroot/main.<hash>.js. Этот тег помещается сразу после закрывающего </title> тега.
  2. Выберите Отладка>Запуск без отладки, чтобы запустить приложение в браузере, не присоединяя отладчик. Файл wwwroot/index.html обрабатывается по адресу https://localhost:<port>.

    Если возникают ошибки компиляции, попробуйте закрыть и повторно открыть решение.

  3. Откройте другой экземпляр браузера (любого) и вставьте URL-адрес в адресную строку.

  4. Выберите любой браузер, введите произвольный текст в поле Сообщение и нажмите кнопку Отправить. На обеих страницах мгновенно отображаются имя пользователя и сообщение.

Сообщение, отображаемое в обоих окнах браузера

Следующие шаги

Дополнительные ресурсы

В этом учебнике демонстрируется использование средства Webpack для создания пакета и сборки веб-приложения ASP.NET Core SignalR, а также объединения и создания клиента, который написан на языке TypeScript. С помощью средства Webpack разработчики могут создавать пакеты и выполнять сборку ресурсов на стороне клиента для веб-приложения.

В этом руководстве описано следующее:

  • Создание приложения ASP.NET Core SignalR
  • настроить сервер SignalR.
  • Настроить конвейер сборки с использованием Webpack
  • настроить клиент TypeScript SignalR;
  • Включение обмена данными между клиентом и сервером.

Просмотреть или скачать образец кода (описание загрузки)

Необходимые компоненты

Создание веб-приложения ASP.NET Core

По умолчанию Visual Studio использует версию npm, которая находится в его каталоге установки. Настройка Visual Studio на поиск npm в переменной среды PATH:

  1. Запустите Visual Studio. В начальном окне выберите Продолжить без кода.

  2. Выберите Сервис>Параметры>Проекты и решения>Управление веб-пакетами>Внешние веб-инструменты.

  3. $(PATH) Выберите запись из списка. Щелкните стрелку вверх, чтобы переместить этот элемент на вторую позицию в списке, и нажмите OK.

    Конфигурация Visual Studio.

Создание веб-приложения ASP.NET Core:

  1. Перейдите в меню Файл>Создать>Проект и выберите шаблон Пустой шаблон ASP.NET Core. Выберите Далее.
  2. Задайте для проекта имя SignalRWebpack и нажмите кнопку Создать.
  3. Выберите .NET 6.0 (Long Term Support) в раскрывающемся меню Платформа. Нажмите кнопку создания.

Добавьте в проект пакет NuGet Microsoft.TypeScript.MSBuild.

  1. В обозревателе решений щелкните правой кнопкой мыши узел проекта и выберите Управление пакетами NuGet. На вкладке Обзор найдите Microsoft.TypeScript.MSBuild, а затем нажмите кнопку Установить справа, чтобы установить пакет.

Visual Studio добавляет пакет NuGet в узел Зависимости в обозревателе решений, разрешая компиляцию TypeScript в проекте.

настроить сервер .

В этом разделе вы настроите веб-приложение ASP.NET Core для отправки и получения сообщений SignalR.

  1. В Program.cs вызовите AddSignalR.

    var builder = WebApplication.CreateBuilder(args);
    
    builder.Services.AddSignalR();
    
  2. В Program.cs снова вызовите UseDefaultFiles и UseStaticFiles:

    var app = builder.Build();
    
    app.UseDefaultFiles();
    app.UseStaticFiles();
    

    Приведенный выше код позволяет серверу находить и обслуживать index.html файл. Файл обрабатывается независимо от того, вводит ли пользователь полный или корневой URL-адрес веб-приложения.

  3. Создайте новый каталог с именем Hubs в корневом каталоге проекта SignalRWebpack/ для хранения класса концентратора SignalR.

  4. Создайте файл Hubs/ChatHub.cs со следующим кодом:

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

    Приведенный выше код осуществляет широковещательную рассылку полученных сервером сообщений всем подключенным пользователям. Универсальный метод on для получения всех сообщений не требуется. Имя метода указывается после суффиксов имени сообщения.

    В этом примере клиент TypeScript отправляет сообщение, идентифицированное как newMessage. Метод C# NewMessage ожидает данные, отправленные клиентом. Выполняется вызов метода SendAsync для Clients.All. Полученные сообщения отправляются всем клиентам, подключенным к концентратору.

  5. Добавьте следующий оператор using в самое начало Program.cs, чтобы разрешить ссылку ChatHub:

    using SignalRWebpack.Hubs;
    
  6. В Program.cs сопоставьте маршрут /hub с концентратором ChatHub. Замените код, отображающий сообщение Hello World!, следующим кодом:

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

Настройка клиента

В этом разделе вы создадите проект Node.js для преобразования TypeScript в JavaScript и объединения ресурсов на стороне клиента, включая HTML и CSS, с помощью Webpack.

  1. Выполните следующую команду в корневом package.json каталоге проекта, чтобы создать файл:

    npm init -y
    
  2. Добавьте выделенное свойство в package.json файл и сохраните изменения файла:

    {
      "name": "SignalRWebpack",
      "version": "1.0.0",
      "private": true,
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }
    

    Если свойству private присвоено значение true, на следующем шаге не будут отображаться предупреждения об установке пакета.

  3. Установите необходимые пакеты npm. Выполните следующую команду из корневого каталога проекта:

    npm i -D -E clean-webpack-plugin css-loader html-webpack-plugin mini-css-extract-plugin ts-loader typescript webpack webpack-cli
    

    Использование параметра -E позволяет отключить установленное по умолчанию поведение npm, предусматривающее запись операторов диапазона семантического управления версиями в файл package.json. Например, "webpack": "5.70.0" используется вместо "webpack": "^5.70.0". Этот параметр позволяет исключить непреднамеренное обновление до более новых версий пакета.

    Дополнительные сведения см. в npm-install.

  4. Замените свойство scripts в файле package.json следующим кодом:

    "scripts": {
      "build": "webpack --mode=development --watch",
      "release": "webpack --mode=production",
      "publish": "npm run release && dotnet publish -c Release"
    },
    

    Определены следующие скрипты:

    • build: объединяет клиентские ресурсы в режиме разработки и проверяет изменения файлов. Наблюдатель за файлами выполняет повторное создание пакета при каждом изменении файла проекта. Параметр mode позволяет отключить оптимизации в рабочей среде, такие как встряхивание дерева и минификация. build используется только в среде разработки.
    • release: объединяет клиентские ресурсы в рабочем режиме.
    • publish. Запускает скрипт release для создания пакета ресурсов на стороне клиента в рабочем режиме. Этот скрипт вызывает команду publish интерфейса командной строки .NET для публикации приложения.
  5. Создайте файл с именем webpack.config.js в корневом каталоге проекта с помощью следующего кода:

    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",
        }),
      ],
    };
    

    Приведенный выше файл определяет конфигурацию процесса компиляции Webpack.

    • Свойство output переопределяет значение distпо умолчанию. Пакет вместо этого создается в каталоге wwwroot .
    • Массив resolve.extensions включает в себя .js импорт клиентского SignalR JavaScript.
  6. src Скопируйте каталог и его содержимое из примера проекта в корневой каталог проекта. Каталог src содержит следующие файлы:

    • index.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>
      
    • 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;
      }
      
    • tsconfig.json, который определяет конфигурацию компилятора TypeScript для получения совместимого с ECMAScript 5 кода JavaScript.

      {
        "compilerOptions": {
          "target": "es5"
        }
      }
      
    • index.ts:

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

    Приведенный выше код извлекает ссылки на элементы модели DOM и присоединяет два обработчика событий:

    • keyup: срабатывает, когда пользователь вводит данные в текстовое поле tbMessage, и вызывает функцию send при нажатии пользователем клавиши Enter.
    • click: срабатывает, когда пользователь нажимает кнопку Отправить и вызывается функцию send.

    Класс HubConnectionBuilder создает новый построитель для настройки подключения к серверу. Функция withUrl настраивает URL-адрес концентратора.

    SignalR обеспечивает обмен сообщениями между клиентом и сервером. Каждому сообщению присваивается определенное имя. Например, сообщения с именем messageReceived могут выполнять логику отображения новых сообщений в соответствующей зоне. Прослушивание определенных сообщений реализуется с помощью функции on. Возможно прослушивание любого числа имен сообщений. Кроме того, можно передавать параметры сообщения, например имя его автора или содержимое полученного сообщения. После того как клиент получает сообщение, создается новый элемент div, в атрибуте innerHTML которого содержатся имя автора и содержимое сообщения. Этот элемент добавляется в основной элемент div, который используется для отображения сообщений.

    Для отправки сообщения через соединение WebSockets необходимо вызвать метод send. Первый параметр этого метода содержит имя сообщения. Другие параметры заполняются данными сообщения. В этом примере на сервер отправляется сообщение, идентифицированное как newMessage. Это сообщение содержит имя пользователя, а также данные, введенные этим пользователем в текстовое поле. Если отправка выполняется успешно, значение текстового поля очищается.

  7. Выполните следующую команду в корневом элементе проекта:

    npm i @microsoft/signalr @types/node
    

    Предыдущая команда устанавливает:

    • Клиент TypeScript SignalR, который позволяет клиенту отправлять сообщения на сервер.
    • Определения типа TypeScript для Node.js, обеспечивающие проверку типов Node.js во время компиляции.

Тестирование приложения

Чтобы проверить работоспособность приложения, выполните следующие шаги.

  1. Запустите Webpack в release режиме. Выполните следующие команды в окне Консоль диспетчера пакетов в корневом элементе проекта. Если вы не в корневом каталоге проекта, введите перед этой командой cd SignalRWebpack.

    npm run release
    

    Эта команда создает ресурсы на стороне клиента, которые будут обслуживаться при выполнении приложения. Ресурсы помещаются в папку wwwroot .

    Веб-пакет выполнил следующие задачи:

    • Очистка содержимого wwwroot каталога.
    • Преобразование TypeScript в JavaScript (этот процесс называется транспилированием).
    • Корректировка созданного кода JavaScript в целях уменьшения размера файла (этот процесс называется минификацией).
    • Скопированы обработанные файлы JavaScript, CSS и HTML из srcwwwroot каталога.
    • В файл ввели следующие элементы wwwroot/index.html :
      • Тег <link>, ссылающийся на файл wwwroot/main.<hash>.css. Этот тег размещается непосредственно после закрывающего тега </head>.
      • Тег <script>, ссылающийся на минифицированный файл wwwroot/main.<hash>.js. Этот тег помещается сразу после закрывающего </title> тега.
  2. Выберите Отладка>Запуск без отладки, чтобы запустить приложение в браузере, не присоединяя отладчик. Файл wwwroot/index.html обрабатывается по адресу https://localhost:<port>.

    Если во время компиляции возникают ошибки, попробуйте закрыть и снова открыть решение.

  3. Откройте другой экземпляр браузера (любого) и вставьте URL-адрес в адресную строку.

  4. Выберите любой браузер, введите произвольный текст в поле Сообщение и нажмите кнопку Отправить. На обеих страницах мгновенно отображаются имя пользователя и сообщение.

Сообщение, отображаемое в обоих окнах браузера

Следующие шаги

Дополнительные ресурсы

В этом учебнике демонстрируется использование средства Webpack для создания пакета и сборки веб-приложения ASP.NET Core SignalR, а также объединения и создания клиента, который написан на языке TypeScript. С помощью средства Webpack разработчики могут создавать пакеты и выполнять сборку ресурсов на стороне клиента для веб-приложения.

В этом руководстве описано следующее:

  • сформировать шаблон для начального приложения ASP.NET Core SignalR;
  • настроить клиент TypeScript SignalR;
  • Настроить конвейер сборки с использованием Webpack
  • настроить сервер SignalR.
  • Обеспечить взаимодействие между клиентом и сервером

Просмотреть или скачать образец кода (описание загрузки)

Необходимые компоненты

Создание веб-приложения ASP.NET Core

Настройте Visual Studio на поиск npm в переменной среды PATH. По умолчанию Visual Studio использует версию npm, которая находится в его каталоге установки. В Visual Studio выполните следующие инструкции:

  1. Запустите Visual Studio. В начальном окне выберите Продолжить без кода.

  2. Выберите Сервис>Параметры>Проекты и решения>Управление веб-пакетами>Внешние веб-инструменты.

  3. Выберите элемент $(PATH) в списке. Щелкните стрелку вверх, чтобы переместить этот элемент на вторую позицию в списке, и нажмите OK.

    Конфигурация Visual Studio.

Настройка Visual Studio завершена.

  1. Перейдите в меню Файл>Создать>Проект и выберите шаблон Веб-приложение ASP.NET Core. Выберите Далее.
  2. Присвойте проекту имя *SignalRWebPack`` и щелкните Создать.
  3. Выберите .NET Core в раскрывающемся списке целевых платформ и ASP.NET Core 3.1 в раскрывающемся списке версий платформ. Выберите шаблон Пустой и щелкните Создать.

Добавить пакет Microsoft.TypeScript.MSBuild в проект:

  1. В обозревателе решений (справа) щелкните правой кнопкой мыши имя проекта и выберите пункт Управление пакетами NuGet. На вкладке Обзор найдите Microsoft.TypeScript.MSBuild, а затем нажмите кнопку Установить справа, чтобы установить пакет.

Visual Studio добавляет пакет NuGet в узел Зависимости в обозревателе решений, разрешая компиляцию TypeScript в проекте.

Настройка Webpack и TypeScript

Далее следует настроить преобразование TypeScript в JavaScript и создание пакета ресурсов на стороне клиента.

  1. Выполните следующую команду в корневом package.json каталоге проекта, чтобы создать файл:

    npm init -y
    
  2. Добавьте выделенное свойство в package.json файл и сохраните изменения файла:

    {
      "name": "SignalRWebPack",
      "version": "1.0.0",
      "private": true,
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }
    

    Если свойству private присвоено значение true, на следующем шаге не будут отображаться предупреждения об установке пакета.

  3. Установите необходимые пакеты npm. Выполните следующую команду из корневого каталога проекта:

    npm i -D -E clean-webpack-plugin@3.0.0 css-loader@3.4.2 html-webpack-plugin@3.2.0 mini-css-extract-plugin@0.9.0 ts-loader@6.2.1 typescript@3.7.5 webpack@4.41.5 webpack-cli@3.3.10
    

    Сведения о команде, на которые следует обратить внимание:

    • Для каждого имени пакета номер версии указывается после знака @. npm устанавливает указанные версии пакета.
    • Использование параметра -E позволяет отключить установленное по умолчанию поведение npm, предусматривающее запись операторов диапазона семантического управления версиями в файл *packagejson. Например, "webpack": "4.41.5" используется вместо "webpack": "^4.41.5". Этот параметр позволяет исключить непреднамеренное обновление до более новых версий пакета.

    Дополнительные сведения см. в документации по npm-install.

  4. Замените scripts свойство package.json файла следующим кодом:

    "scripts": {
      "build": "webpack --mode=development --watch",
      "release": "webpack --mode=production",
      "publish": "npm run release && dotnet publish -c Release"
    },
    

    Некоторые пояснения к скриптам:

    • build: объединяет клиентские ресурсы в режиме разработки и проверяет изменения файлов. Наблюдатель за файлами выполняет повторное создание пакета при каждом изменении файла проекта. Параметр mode позволяет отключить оптимизации в рабочей среде, такие как встряхивание дерева и минификация. В среде разработки следует использовать только build.
    • release: объединяет клиентские ресурсы в рабочем режиме.
    • publish. Запускает скрипт release для создания пакета ресурсов на стороне клиента в рабочем режиме. Этот скрипт вызывает команду publish интерфейса командной строки .NET Core для публикации приложения.
  5. Создайте файл с именем webpack.config.js(в корневом каталоге проекта) со следующим кодом:

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

    Приведенный выше файл определяет конфигурацию компиляции Webpack. Сведения о конфигурации, на которые следует обратить внимание:

    • Свойство output переопределяет значение distпо умолчанию. Пакет вместо этого создается в каталоге wwwroot .
    • Массив resolve.extensions включает в себя .js импорт клиентского SignalR JavaScript.
  6. Создайте новый каталог src в корневом каталоге проекта, чтобы сохранить клиентские ресурсы проекта.

  7. Создайте src/index.html с помощью следующей разметки.

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <title>ASP.NET Core SignalR</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>
    

    Приведенный выше HTML-файл определяет стереотипную разметку главной страницы.

  8. Создайте каталог src/css. Его целью является хранение файлов проекта .css .

  9. Создайте 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;
    }
    

    main.css Предыдущий файл стили приложения.

  10. Создайте src/tsconfig.json со следующим кодом JSON.

    {
      "compilerOptions": {
        "target": "es5"
      }
    }
    

    Приведенный выше код определяет конфигурацию компилятора TypeScript для получения совместимого с ECMAScript 5 кода JavaScript.

  11. Создайте src/index.ts, используя следующий код:

    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();
    
    tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {
        if (e.key === "Enter") {
            send();
        }
    });
    
    btnSend.addEventListener("click", send);
    
    function send() {
    }
    

    Приведенный выше код TypeScript извлекает ссылки на элементы модели DOM и присоединяет два обработчика событий:

    • keyup: это событие возникает, когда пользователь вводит в текстовое tbMessageполе. Функция send вызывается, когда пользователь нажимает клавишу ВВОД.
    • click: это событие возникает, когда пользователь нажимает кнопку Отправить. Вызывается функция send.

Настройка приложения

  1. В Startup.Configure добавьте вызовы к UseDefaultFiles(IApplicationBuilder) и UseStaticFiles(IApplicationBuilder).

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        
        app.UseRouting();
        app.UseDefaultFiles();
        app.UseStaticFiles();
        
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapHub<ChatHub>("/hub");
        });
            
    }
    

    Приведенный выше код позволяет серверу находить и обслуживать index.html файл. Файл обрабатывается независимо от того, вводит ли пользователь полный или корневой URL-адрес веб-приложения.

  2. В конце Startup.Configure сопоставьте маршрут /hub с концентратором ChatHub. Замените код, отображающий Hello World!, следующей строкой:

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHub<ChatHub>("/hub");
    });
    
  3. В Startup.ConfigureServices вызовите AddSignalR.

    services.AddSignalR();
    
  4. Создайте новый каталог с именем Hubs в корневом каталоге проекта SignalRWebPack/ для хранения концентратора SignalR.

  5. Создайте концентратор Hubs/ChatHub.cs со следующим кодом:

    using Microsoft.AspNetCore.SignalR;
    using System.Threading.Tasks;
    
    namespace SignalRWebPack.Hubs
    {
        public class ChatHub : Hub
        {
        }
    }
    
  6. Добавьте следующую using инструкцию в верхней части Startup.cs файла, чтобы устранить ссылку ChatHub :

    using SignalRWebPack.Hubs;
    

Обеспечение взаимодействия между клиентом и сервером

Приложение в настоящее время отображает простую форму для отправки сообщений, но еще не работает. Сервер прослушивает конкретный маршрут, но ничего не делает с отправленными сообщениями.

  1. Выполните следующую команду в корневом элементе проекта:

    npm i @microsoft/signalr @types/node
    

    Предыдущая команда устанавливает:

    • Клиент TypeScript SignalR, который позволяет клиенту отправлять сообщения на сервер.
    • Определения типа TypeScript для Node.js, обеспечивающие проверку типов Node.js во время компиляции.
  2. Добавьте выделенный код в файл src/index.ts:

    import "./css/main.css";
    import * as signalR from "@microsoft/signalr";
    
    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) => {
        let 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() {
    }
    

    Приведенный выше код поддерживает получение сообщений от сервера. Класс HubConnectionBuilder создает новый построитель для настройки подключения к серверу. Функция withUrl настраивает URL-адрес концентратора.

    SignalR обеспечивает обмен сообщениями между клиентом и сервером. Каждому сообщению присваивается определенное имя. Например, сообщения с именем messageReceived могут выполнять логику отображения новых сообщений в соответствующей зоне. Прослушивание определенных сообщений реализуется с помощью функции on. Возможно прослушивание любого числа имен сообщений. Кроме того, можно передавать параметры сообщения, например имя его автора или содержимое полученного сообщения. После того как клиент получает сообщение, создается новый элемент div, в атрибуте innerHTML которого содержатся имя автора и содержимое сообщения. Этот элемент добавляется в основной элемент div, который используется для отображения сообщений.

  3. Теперь клиент может принимать сообщения. Далее следует настроить его для отправки сообщений. Добавьте выделенный код в файл src/index.ts:

    import "./css/main.css";
    import * as signalR from "@microsoft/signalr";
    
    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) => {
        let messages = document.createElement("div");
    
        messages.innerHTML =
            `<div class="message-author">${username}</div><div>${message}</div>`;
    
        divMessages.appendChild(messages);
        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 = "");
    }
    

    Для отправки сообщения через соединение WebSockets необходимо вызвать метод send. Первый параметр этого метода содержит имя сообщения. Другие параметры заполняются данными сообщения. В этом примере на сервер отправляется сообщение, идентифицированное как newMessage. Это сообщение содержит имя пользователя, а также данные, введенные этим пользователем в текстовое поле. Если отправка выполняется успешно, значение текстового поля очищается.

  4. Добавьте метод NewMessage в класс ChatHub:

    using Microsoft.AspNetCore.SignalR;
    using System.Threading.Tasks;
    
    namespace SignalRWebPack.Hubs
    {
        public class ChatHub : Hub
        {
            public async Task NewMessage(long username, string message)
            {
                await Clients.All.SendAsync("messageReceived", username, message);
            }
        }
    }
    

    Приведенный выше код осуществляет широковещательную рассылку полученных сервером сообщений всем подключенным пользователям. Универсальный метод on для получения всех сообщений не требуется. Имя метода указывается после суффиксов имени сообщения.

    В этом примере клиент TypeScript отправляет сообщение, идентифицированное как newMessage. Метод C# NewMessage ожидает данные, отправленные клиентом. Выполняется вызов метода SendAsync для Clients.All. Полученные сообщения отправляются всем клиентам, подключенным к концентратору.

Тестирование приложения

Чтобы проверить работоспособность приложения, выполните следующие шаги.

  1. Запустите средство Webpack в режиме release. Выполните следующие команды в окне Консоль диспетчера пакетов в корневом элементе проекта. Если вы не в корневом каталоге проекта, введите перед этой командой cd SignalRWebPack.

    npm run release
    

    Эта команда создает ресурсы на стороне клиента, которые будут обслуживаться при выполнении приложения. Ресурсы помещаются в папку wwwroot .

    Веб-пакет выполнил следующие задачи:

    • Очистка содержимого wwwroot каталога.
    • Преобразование TypeScript в JavaScript (этот процесс называется транспилированием).
    • Корректировка созданного кода JavaScript в целях уменьшения размера файла (этот процесс называется минификацией).
    • Скопированы обработанные файлы JavaScript, CSS и HTML из srcwwwroot каталога.
    • В файл ввели следующие элементы wwwroot/index.html :
      • Тег <link>, ссылающийся на файл wwwroot/main.<hash>.css. Этот тег размещается непосредственно после закрывающего тега </head>.
      • Тег <script>, ссылающийся на минифицированный файл wwwroot/main.<hash>.js. Этот тег помещается сразу после закрывающего </title> тега.
  2. Выберите Отладка>Запуск без отладки, чтобы запустить приложение в браузере, не присоединяя отладчик. Файл wwwroot/index.html обрабатывается по адресу http://localhost:<port_number>.

    Если во время компиляции возникают ошибки, попробуйте закрыть и снова открыть решение.

  3. Откройте другой экземпляр любого браузера. Вставьте URL-адрес в адресную строку.

  4. Выберите любой браузер, введите произвольный текст в поле Сообщение и нажмите кнопку Отправить. На обеих страницах мгновенно отображаются имя пользователя и сообщение.

Сообщение, отображаемое в обоих окнах браузера

Дополнительные ресурсы

В этом учебнике демонстрируется использование средства Webpack для создания пакета и сборки веб-приложения ASP.NET Core SignalR, а также объединения и создания клиента, который написан на языке TypeScript. С помощью средства Webpack разработчики могут создавать пакеты и выполнять сборку ресурсов на стороне клиента для веб-приложения.

В этом руководстве описано следующее:

  • сформировать шаблон для начального приложения ASP.NET Core SignalR;
  • настроить клиент TypeScript SignalR;
  • Настроить конвейер сборки с использованием Webpack
  • настроить сервер SignalR.
  • Обеспечить взаимодействие между клиентом и сервером

Просмотреть или скачать образец кода (описание загрузки)

Необходимые компоненты

Создание веб-приложения ASP.NET Core

Настройте Visual Studio на поиск npm в переменной среды PATH. По умолчанию Visual Studio использует версию npm, которая находится в его каталоге установки. В Visual Studio выполните следующие инструкции:

  1. Выберите Сервис>Параметры>Проекты и решения>Управление веб-пакетами>Внешние веб-инструменты.

  2. Выберите элемент $(PATH) в списке. Щелкните стрелку вверх, чтобы переместить этот элемент на вторую позицию в списке.

    Конфигурация Visual Studio

Настройка Visual Studio завершена. Теперь следует создать проект.

  1. Перейдите в меню Файл>Создать>Проект и выберите шаблон Веб-приложение ASP.NET Core.
  2. Присвойте проекту имя *SignalRWebPack`` и щелкните Создать.
  3. Выберите .NET Core в раскрывающемся списке целевых платформ и выберите ASP.NET Core 2.2 в раскрывающемся списке средства выбора платформы. Выберите шаблон Пустой и щелкните Создать.

Настройка Webpack и TypeScript

Далее следует настроить преобразование TypeScript в JavaScript и создание пакета ресурсов на стороне клиента.

  1. Выполните следующую команду в корневом package.json каталоге проекта, чтобы создать файл:

    npm init -y
    
  2. Добавьте выделенное свойство в package.json файл:

    {
      "name": "SignalRWebPack",
      "version": "1.0.0",
      "private": true,
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }
    

    Если свойству private присвоено значение true, на следующем шаге не будут отображаться предупреждения об установке пакета.

  3. Установите необходимые пакеты npm. Выполните следующую команду из корневого каталога проекта:

    npm install -D -E clean-webpack-plugin@1.0.1 css-loader@2.1.0 html-webpack-plugin@4.0.0-beta.5 mini-css-extract-plugin@0.5.0 ts-loader@5.3.3 typescript@3.3.3 webpack@4.29.3 webpack-cli@3.2.3
    

    Сведения о команде, на которые следует обратить внимание:

    • Для каждого имени пакета номер версии указывается после знака @. npm устанавливает указанные версии пакета.
    • Использование параметра -E позволяет отключить установленное по умолчанию поведение npm, предусматривающее запись операторов диапазона семантического управления версиями в файл *packagejson. Например, "webpack": "4.29.3" используется вместо "webpack": "^4.29.3". Этот параметр позволяет исключить непреднамеренное обновление до более новых версий пакета.

    Дополнительные сведения см. в документации по npm-install.

  4. Замените scripts свойство package.json файла следующим кодом:

    "scripts": {
      "build": "webpack --mode=development --watch",
      "release": "webpack --mode=production",
      "publish": "npm run release && dotnet publish -c Release"
    },
    

    Некоторые пояснения к скриптам:

    • build: объединяет клиентские ресурсы в режиме разработки и проверяет изменения файлов. Наблюдатель за файлами выполняет повторное создание пакета при каждом изменении файла проекта. Параметр mode позволяет отключить оптимизации в рабочей среде, такие как встряхивание дерева и минификация. В среде разработки следует использовать только build.
    • release: объединяет клиентские ресурсы в рабочем режиме.
    • publish. Запускает скрипт release для создания пакета ресурсов на стороне клиента в рабочем режиме. Этот скрипт вызывает команду publish интерфейса командной строки .NET Core для публикации приложения.
  5. Создайте в корневом элементе проекта файл *webpack.config.js со следующим кодом:

    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(["wwwroot/*"]),
            new HtmlWebpackPlugin({
                template: "./src/index.html"
            }),
            new MiniCssExtractPlugin({
                filename: "css/[name].[chunkhash].css"
            })
        ]
    };
    

    Приведенный выше файл определяет конфигурацию компиляции Webpack. Сведения о конфигурации, на которые следует обратить внимание:

    • Свойство output переопределяет значение distпо умолчанию. Пакет вместо этого создается в каталоге wwwroot .
    • Массив resolve.extensions включает в себя .js импорт клиентского SignalR JavaScript.
  6. Создайте новый каталог src в корневом каталоге проекта, чтобы сохранить клиентские ресурсы проекта.

  7. Создайте src/index.html с помощью следующей разметки.

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <title>ASP.NET Core SignalR</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>
    

    Приведенный выше HTML-файл определяет стереотипную разметку главной страницы.

  8. Создайте каталог src/css. Его целью является хранение файлов проекта .css .

  9. Создайте файл src/css/main.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;
    }
    

    main.css Предыдущий файл стили приложения.

  10. Создайте src/tsconfig.json со следующим кодом JSON.

    {
      "compilerOptions": {
        "target": "es5"
      }
    }
    

    Приведенный выше код определяет конфигурацию компилятора TypeScript для получения совместимого с ECMAScript 5 кода JavaScript.

  11. Создайте src/index.ts, используя следующий код:

    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();
    
    tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {
        if (e.keyCode === 13) {
            send();
        }
    });
    
    btnSend.addEventListener("click", send);
    
    function send() {
    }
    

    Приведенный выше код TypeScript извлекает ссылки на элементы модели DOM и присоединяет два обработчика событий:

    • keyup: это событие возникает, когда пользователь вводит в текстовое tbMessage поле. Функция send вызывается, когда пользователь нажимает клавишу ВВОД.
    • click: это событие возникает, когда пользователь нажимает кнопку Отправить. Вызывается функция send.

Настройка приложения ASP.NET Core

  1. Код в методе Startup.Configure отображает текст Hello World!. Замените вызов метода app.Run вызовами методов UseDefaultFiles(IApplicationBuilder) и UseStaticFiles(IApplicationBuilder).

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

    Приведенный выше код позволяет серверу находить и обслуживать index.html файл, независимо от того, вводит ли пользователь полный URL-адрес или корневой URL-адрес веб-приложения.

  2. Вызовите AddSignalR в Startup.ConfigureServices. Этот метод добавляет в проект службы SignalR.

    services.AddSignalR();
    
  3. Сопоставьте маршрут /hub с концентратором ChatHub. Добавьте в конец метода Startup.Configure следующие строки:

    app.UseSignalR(options =>
    {
        options.MapHub<ChatHub>("/hub");
    });
    
  4. Создайте новый каталог Hubs в корневом элементе проекта. Этот каталог служит для хранения концентратора SignalR, созданного на предыдущем шаге.

  5. Создайте концентратор Hubs/ChatHub.cs со следующим кодом:

    using Microsoft.AspNetCore.SignalR;
    using System.Threading.Tasks;
    
    namespace SignalRWebPack.Hubs
    {
        public class ChatHub : Hub
        {
        }
    }
    
  6. Добавьте следующий код в начало файла Startup.cs, чтобы разрешить ссылку ChatHub:

    using SignalRWebPack.Hubs;
    

Обеспечение взаимодействия между клиентом и сервером

На данный момент приложение отображает простую форму для отправки сообщений. При попытке сделать это ничего не происходит. Сервер прослушивает конкретный маршрут, но ничего не делает с отправленными сообщениями.

  1. Выполните следующую команду в корневом элементе проекта:

    npm install @aspnet/signalr
    

    Команда выше устанавливает клиент TypeScript SignalR, который позволяет клиенту отправлять сообщения на сервер.

  2. Добавьте выделенный код в файл src/index.ts:

    import "./css/main.css";
    import * as signalR from "@aspnet/signalr";
    
    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) => {
        let 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.keyCode === 13) {
            send();
        }
    });
    
    btnSend.addEventListener("click", send);
    
    function send() {
    }
    

    Приведенный выше код поддерживает получение сообщений от сервера. Класс HubConnectionBuilder создает новый построитель для настройки подключения к серверу. Функция withUrl настраивает URL-адрес концентратора.

    SignalR обеспечивает обмен сообщениями между клиентом и сервером. Каждому сообщению присваивается определенное имя. Например, сообщения с именем messageReceived могут выполнять логику отображения новых сообщений в соответствующей зоне. Прослушивание определенных сообщений реализуется с помощью функции on. Возможно прослушивание любого числа имен сообщений. Кроме того, можно передавать параметры сообщения, например имя его автора или содержимое полученного сообщения. После того как клиент получает сообщение, создается новый элемент div, в атрибуте innerHTML которого содержатся имя автора и содержимое сообщения. Новое сообщение добавляется в основной элемент div, который используется для отображения сообщений.

  3. Теперь клиент может принимать сообщения. Далее следует настроить его для отправки сообщений. Добавьте выделенный код в файл src/index.ts:

    import "./css/main.css";
    import * as signalR from "@aspnet/signalr";
    
    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) => {
        let messageContainer = document.createElement("div");
    
        messageContainer.innerHTML =
            `<div class="message-author">${username}</div><div>${message}</div>`;
    
        divMessages.appendChild(messageContainer);
        divMessages.scrollTop = divMessages.scrollHeight;
    });
    
    connection.start().catch(err => document.write(err));
    
    tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {
        if (e.keyCode === 13) {
            send();
        }
    });
    
    btnSend.addEventListener("click", send);
    
    function send() {
        connection.send("newMessage", username, tbMessage.value)
                  .then(() => tbMessage.value = "");
    }
    

    Для отправки сообщения через соединение WebSockets необходимо вызвать метод send. Первый параметр этого метода содержит имя сообщения. Другие параметры заполняются данными сообщения. В этом примере на сервер отправляется сообщение, идентифицированное как newMessage. Это сообщение содержит имя пользователя, а также данные, введенные этим пользователем в текстовое поле. Если отправка выполняется успешно, значение текстового поля очищается.

  4. Добавьте метод NewMessage в класс ChatHub:

    using Microsoft.AspNetCore.SignalR;
    using System.Threading.Tasks;
    
    namespace SignalRWebPack.Hubs
    {
        public class ChatHub : Hub
        {
            public async Task NewMessage(long username, string message)
            {
                await Clients.All.SendAsync("messageReceived", username, message);
            }
        }
    }
    

    Приведенный выше код осуществляет широковещательную рассылку полученных сервером сообщений всем подключенным пользователям. Универсальный метод on для получения всех сообщений не требуется. Имя метода указывается после суффиксов имени сообщения.

    В этом примере клиент TypeScript отправляет сообщение, идентифицированное как newMessage. Метод C# NewMessage ожидает данные, отправленные клиентом. Выполняется вызов метода SendAsync для Clients.All. Полученные сообщения отправляются всем клиентам, подключенным к концентратору.

Тестирование приложения

Чтобы проверить работоспособность приложения, выполните следующие шаги.

  1. Запустите средство Webpack в режиме release. Выполните следующие команды в окне Консоль диспетчера пакетов в корневом элементе проекта. Если вы не в корневом каталоге проекта, введите перед этой командой cd SignalRWebPack.

    npm run release
    

    Эта команда создает ресурсы на стороне клиента, которые будут обслуживаться при выполнении приложения. Ресурсы помещаются в папку wwwroot .

    Веб-пакет выполнил следующие задачи:

    • Очистка содержимого wwwroot каталога.
    • Преобразование TypeScript в JavaScript (этот процесс называется транспилированием).
    • Корректировка созданного кода JavaScript в целях уменьшения размера файла (этот процесс называется минификацией).
    • Скопированы обработанные файлы JavaScript, CSS и HTML из srcwwwroot каталога.
    • В файл ввели следующие элементы wwwroot/index.html :
      • Тег <link>, ссылающийся на файл wwwroot/main.<hash>.css. Этот тег размещается непосредственно после закрывающего тега </head>.
      • Тег <script>, ссылающийся на минифицированный файл wwwroot/main.<hash>.js. Этот тег помещается сразу после закрывающего </title> тега.
  2. Выберите Отладка>Запуск без отладки, чтобы запустить приложение в браузере, не присоединяя отладчик. Файл wwwroot/index.html обрабатывается по адресу http://localhost:<port_number>.

  3. Откройте другой экземпляр любого браузера. Вставьте URL-адрес в адресную строку.

  4. Выберите любой браузер, введите произвольный текст в поле Сообщение и нажмите кнопку Отправить. На обеих страницах мгновенно отображаются имя пользователя и сообщение.

Сообщение, отображаемое в обоих окнах браузера

Дополнительные ресурсы