Перейти к содержимому

Сборка пакета .portalpart

WebPart пишутся на C# и упаковываются в ZIP-архив .portalpart (manifest + DLL + CSS + опционально JS).

Настройка SDK: Extension SDK с korport.ru/developers.

Новая WebPart — из шаблона SDK:

Окно терминала
# После распаковки portal-sdk-X.Y.Z.zip
dotnet new install ./portal-sdk-1.0.0/templates/portal-webpart
dotnet new portal-webpart -n MyWidget -o ./my-widget

Отредактируйте manifest.json (см. manifest.md), C#-класс, при необходимости Templates/ и assets/main.css / assets/main.js, затем соберите пакет:

Linux / macOS / Git Bash:

Окно терминала
./portal-sdk-1.0.0/scripts/pack-portalpart.sh ./my-widget
# → my-widget/dist/my-widget.portalpart

Windows (PowerShell):

Окно терминала
.\portal-sdk-1.0.0\scripts\pack-portalpart.ps1 .\my-widget

Скрипты pack-portalpart.sh / pack-portalpart.ps1 выполняют dotnet publish и упаковку ZIP (без Docker и без исходников Portal). По умолчанию Release; для отладки с PDB: CONFIGURATION=Debug / -Configuration Debug — см. Отладка расширений.

Чтобы только проверить упаковку на готовом демо из SDK: examples/hello-widget + тот же pack-portalpart.

Шаблон dotnet new portal-webpart -n MyWidget уже подставляет согласованные имена. Обычно .csproj трогать не нужно — достаточно править manifest.json, C#-класс и шаблоны HTML.

ПараметрМенять?Зачем
TargetFramework (net10.0)НетДолжен совпадать с Portal
Nullable / ImplicitUsingsПо желаниюСтиль проекта, на установку не влияет
AssemblyNameТолько при переименовании DLLИмя выходной DLL → должно совпадать с entry в manifest (dist/{AssemblyName}.dll)
RootNamespaceТолько при смене namespaceNamespace классов → вместе с именем класса даёт entryType
PackageReference Portal.WebPart.Sdk VersionДа, при обновлении PortalВерсия SDK = версия Portal
EmbeddedResource Templates\*.htmlОставить, если есть HTML-шаблоныВстраивает Templates/*.html в DLL

Связка с манифестом (пример для -n MyWidget):

.csproj / кодmanifest.json
AssemblyName = MyWidget"entry": "dist/MyWidget.dll"
RootNamespace + класс = Contoso.MyWidget.MyWidgetHandler"entryType": "Contoso.MyWidget.MyWidgetHandler"

Если меняете AssemblyName, namespace или имя класса — синхронно обновите entry / entryType в manifest.json. Иначе пакет установится, но WebPart не загрузится.

id в manifest (contoso.my-widget) — отдельный ключ каталога; он не обязан совпадать с AssemblyName.

Исходники:

my-widget/
├── Templates/
│ └── widget.html ← embedded в DLL (см. ui-and-api.md)
├── MyWidgetHandler.cs
├── MyWidget.csproj
├── manifest.json
└── assets/ ← опционально
├── main.css ← → dist/main.css в ZIP
└── main.js ← опционально

Архив .portalpart (ZIP) после pack-portalpart:

my-widget.portalpart (ZIP)
├── manifest.json
└── dist/
├── MyWidget.dll
├── main.v1.0.0.css ← версия из manifest
└── main.v1.0.0.js ← опционально

Установка: Админка → WebPart → загрузить файл.

Изменения в исходниках (*.cs, assets/main.css, assets/main.js) не попадают в портал автоматически. Работающий экземпляр берёт DLL, CSS и JS из установленного пакета в хранилище (S3).

  1. Внесите изменения в C#-код и/или assets/main.css, assets/main.js.
  2. Увеличьте версию в manifest.json (semver, например 1.0.11.0.2). Это важно для сброса кэша CSS/JS (см. ниже).
  3. Соберите пакет скриптом из SDK (рядом с распакованным portal-sdk-…):
    Окно терминала
    ./portal-sdk-1.0.0/scripts/pack-portalpart.sh ./my-widget
    Окно терминала
    .\portal-sdk-1.0.0\scripts\pack-portalpart.ps1 .\my-widget
  4. Переустановите .portalpart:
    • Админка → WebPart — загрузите ZIP с тем же id (старый пакет будет заменён);
    • или POST /api/v1/webparts/packages (multipart, поле package, права администратора).
  5. Обновите страницу в браузере с очисткой кэша (Cmd+Shift+R / Ctrl+Shift+R) или откройте страницу в новой вкладке.

Повторная загрузка с тем же id в manifest.json удаляет предыдущий пакет, выгружает старую DLL из памяти API и регистрирует новую версию. Настройки WebPart на страницах (Property Pane) сохраняются — меняется только код и ассеты.

КомпонентГде хранитсяПоведение при переустановке
C# / HTML (SSR)dist/*.dll в S3Новая DLL подхватывается при следующем render/action
CSSdist/main.v{version}.css в S3Новый путь + ?v=… в URL definition
JSdist/main.v{version}.js в S3То же; bind вызывается заново после render

При сборке pack-portalpart.sh / .ps1 вызывает stage-versioned-assets (версионирование имён CSS/JS):

  1. Переименовывает dist/main.cssdist/main.v{version}.css (и JS аналогично).
  2. Обновляет styles / scripts в manifest.json внутри ZIP.

При установке пакета backend дополнительно добавляет ?v={version} к URL в definition:

/api/v1/webparts/assets/demo.my-widget/dist/main.v1.0.2.css?v=1.0.2

Фронтенд (webPartLoader.js) кэширует ассеты по (manifestKey, pathname, version) и снимает старые <style> / <script> при смене версии. Ответ API для URL с ?v=Cache-Control: public, max-age=31536000, immutable.

В исходниках в manifest.json указывайте обычные имена (dist/main.css); файлы держите в assets/. Версионирование имён — только на этапе pack-portalpart.

«Изменил код, на странице старый вид»

  • Пакет не переустановлен — выполните шаги 3–4 выше.
  • Браузер закэшировал CSS — жёсткое обновление страницы.
  • Версия в manifest.json не изменилась — URL ассетов остаётся прежним; увеличьте version.

«Работает HTML, но не стили / не JS»

  • Проверьте, что styles / scripts указаны в manifest.json и файлы попали в ZIP (unzip -l *.portalpart).
  • CSS/JS должны быть в пакете (assets/dist/ при сборке), не в frontend/public/.

«После обновления JS не срабатывает»

  • Ключ в PortalWebPartClients[…] должен совпадать с id в манифесте.
  • bind вызывается после замены innerHTML — не вешайте обработчики только при первой загрузке страницы.