Развертывание Angular Universal в IIS

У меня проблема с развертыванием моего Node.js в IIS в моем web.config:

> <handlers>
>         <add name="iisnode-ng-universal" path="dist/server.js" verb="*" modules="iisnode" />
>     </handlers>

 <rule name="ng-universal" stopProcessing="true">
        <match url=".*" />
        <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
            <add input="{HTTP_HOST}" pattern="test" />
        </conditions>
        <action type="Rewrite" url="dist/server.js" />
    </rule>

Я получаю эту ошибку:

изображение

Вот как выглядит мое дерево веб-файлов:

веб-файлы

Я попытался предоставить полное разрешение IIS_IUSRS и IUSR, но это не сработало. Как предлагается в этом сообщении: iisnode обнаружил ошибку при обработке запроса


person John doe    schedule 28.02.2018    source источник


Ответы (4)


Можете ли вы попробовать приведенный ниже код .. он работает для меня

<?xml version="1.0" encoding="utf-8"?>


<configuration>
    <system.webServer>        
      <handlers>
        <add name="iisnode" path="server.js" verb="*" modules="iisnode"/>
      </handlers>
      <rewrite>
        <rules>
            <rule name="DynamicContent">
                 <match url="/*" />
                 <action type="Rewrite" url="server.js"/>
            </rule>
       </rules>
      </rewrite>
    </system.webServer>
  </configuration>

Ваш server.js может находиться за пределами папки dist.

person Darsan S Kumar    schedule 28.02.2018
comment
это приводит к тому, что iisnode обнаружил ошибку при обработке запроса. HRESULT: 0x2 Статус HTTP: 500 Подстатус HTTP: 1002 Причина HTTP: Внутренняя ошибка сервера Вы получаете этот ответ HTTP 200, потому что для параметра конфигурации system.webServer/iisnode/@devErrorsEnabled установлено значение «true». Помимо журнала stdout и stderr процесса node.exe, рассмотрите возможность использования отладки и трассировки трассировки событий Windows для дальнейшей диагностики проблемы. error.pls помогите мне исправить это - person kamalav; 14.05.2018
comment
Здравствуйте, я столкнулся с этой ошибкой: Ошибка HTTP 500.21 - Внутренний обработчик ошибок сервера iisnode имеет плохой модуль iisnode в своем списке модулей. Есть идеи, как исправить то же самое? - person Kunal Kakkad; 11.06.2019

После обновления моего проекта Angular 8 до 9, я имею в виду, что я обновил практически все до последней версии, произошло несколько вещей.

1.- webpack.config.js файл был переименован в .bak, поэтому кажется, что использование webpack больше не подходит, и действительно, если я пытаюсь повторно активировать сборку webpack, ничего не происходит, он создает сборку, но скрипт не запускается. Бег с node server.js входит и исчезает, вообще ничего не говоря.

2.- Теперь в папке dist нет файла .js в корне, а папки браузеров и сборок сервера там, как и раньше, но даже редактирование файла web.config, чтобы указать iisnode запускать server/main.js вместо server.js, все время выдает 500 нет имеет значение, что я делаю.

3.- Единственное, что работает сначала, это запускать локально

npm run dev:ssr

Это означает, что ссылка на представление в сборке браузера есть, но она работает так, как будто должна запускаться из корня с запросом dist / browser.

Я изменил путь сборки и путь сборки сервера в angular.json, чтобы создать файл main.js в корне папки ./dist.

angular.json (outputPath изменен)

architect: {
  "build": {
    "builder": "@angular-devkit/build-angular:browser",
    "options": {
      "outputPath": "dist/browser",
      "index": "src/index.html",
      "main": "src/main.ts",
      "tsConfig": "tsconfig.app.json",
      ...
    },
    ...
  },
  "server": {
    "builder": "@angular-devkit/build-angular:server",
    "options": {
      "outputPath": "dist",
      "main": "server.ts",
      "tsConfig": "tsconfig.server.json"
    },
    ...
  },
  ...
}

Что ж, вот и проблема. Сборка браузера без проблем генерирует ./dist/browser, и сборка сервера действительно помещает файл main.js непосредственно в ./dist, но каким-то образом решила удалить папку ./dist/browser и при запуске узла main.js (web.config указывает to main.js) он не может найти ./browser/index.html и, конечно, не потому, что процессу сборки сервера удалось удалить папку браузера.

Хакерское решение, запустите третью сборку (снова сборку браузера)

Я надеюсь, что это можно решить, но, честно говоря, это меня совсем не беспокоит, компьютер запускает сборку, а не я, но вы знаете, могло бы быть лучше и быстрее, если бы процесс сборки сервера не удалял сборку браузера папка.

Теперь он прекрасно развертывается в службе приложений Azure прямо из AppVey или каждый раз, когда я развертываю выбранную сборку, никаких проблем.

package.json (обратите внимание на дополнительную производственную сборку после сборки сервера)

{
  ...
  "scripts": {
    ...
    "dev:ssr": "ng run Angular-Universal:serve-ssr",
    "serve:ssr": "node dist/main.js",
    "build:ssr": "npm run build:universal && ng run Angular-Universal:build:production",
    "start:ssr": "npm run build:ssr && npm run serve:ssr",
    "build:universal": "ng run Angular-Universal:build:production && ng run Angular-Universal:server:production",
    "prerender": "ng run Angular-Universal:prerender"
  },
  ...
}

Обратите внимание, что сценарий build:ssr выполняет обе сборки, а затем снова сборку браузера. Также обратите внимание, что сценарий serve:ssr был изменен для запуска dist/main.js

Наконец, необходимо было изменить файл server.ts, чтобы запросить представление из ./browser/index.html или ./dist/browser/index.html в зависимости от структуры папок целевой системы. При развертывании в службе приложений Azure main.js запрашивает browser / index.html, но если проект обслуживается с npm run dev:ssr или node main.js в моей локальной среде с запуском в macOS, он запрашивает dist / browser / index.html. В любом случае простой человек может преодолеть это препятствие.

server.ts (Изменения в функции приложения)

// The Express app is exported so that it can be used by serverless Functions.
export function app() {
  const server = express();

  let distFolder: string;
  const path1 = join(process.cwd(), 'browser');         // Running from the deployed version (production)
  const path2 = join(process.cwd(), 'dist/browser');    // Running from the source (macOS local development)

  if (fs.existsSync(path1)) {
    distFolder = path1;
  } else if (fs.existsSync(path2)) {
    distFolder = path2;
  } else {
    return null;
  }
  console.log('distFolder:', distFolder);
  const indexHtml = fs.existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';

  // Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
  server.engine('html', ngExpressEngine({
    bootstrap: AppServerModule,
  }));

  server.set('view engine', 'html');
  server.set('views', distFolder);

  // Example Express Rest API endpoints
  // server.get('/api/**', (req, res) => { });
  // Serve static files from /browser
  server.get('*.*', express.static(distFolder, {
    maxAge: '1y'
  }));

  // All regular routes use the Universal engine
  server.get('*', (req, res) => {
    res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
  });

  return server;
}

На всякий случай, если вам интересно, как насчет копирования файла web.config в корень папки dist, ну, поскольку я использую AppVeyor для CI / CD, я изменил команду создания артефакта, чтобы включить web.config (из исходных файлов репо непосредственно в .7z файл)

А почему бы не включить мой web.config?

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.web>
    <httpRuntime enableVersionHeader="false" />
  </system.web>
  <system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Strict-Transport-Security" value="max-age=31536000"/>
        <add name="X-Content-Type-Options" value="nosniff" />
        <add name="X-Frame-Options" value="DENY" />
        <add name="X-XSS-Protection" value="1; mode=block" />
        <remove name="X-Powered-By" />
      </customHeaders>
    </httpProtocol>
    <webSocket enabled="false" />
    <handlers>
      <!-- Indicates that the main.js file is a node.js site to be handled by the iisnode module -->
      <add name="iisnode" path="main.js" verb="*" modules="iisnode"/>
    </handlers>
    <rewrite>
      <rules>
        <rule name="HTTP to HTTPS redirect" stopProcessing="true">
          <match url="(.*)" />
          <conditions>
            <add input="{HTTPS}" pattern="off" ignoreCase="true" />
          </conditions>
          <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
        </rule>
        <!-- Do not interfere with requests for node-inspector debugging -->
        <rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
          <match url="^main.js\/debug[\/]?" />
        </rule>
        <!-- All other URLs are mapped to the node.js site entry point -->
        <rule name="DynamicContent">
          <match url="^(?!.*login).*$"></match>
          <conditions>
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
          </conditions>
          <action type="Rewrite" url="main.js"/>
        </rule>
      </rules>
      <outboundRules>
        <rule name="Add Strict-Transport-Security when HTTPS" enabled="true">
          <match serverVariable="RESPONSE_Strict_Transport_Security" pattern=".*" />
          <conditions>
            <add input="{HTTPS}" pattern="on" ignoreCase="true" />
          </conditions>
          <action type="Rewrite" value="max-age=31536000" />
        </rule>
      </outboundRules>
    </rewrite>
    <!-- 'bin' directory has no special meaning in node.js and apps can be placed in it -->
    <security>
      <requestFiltering>
        <hiddenSegments>
          <remove segment="bin"/>
        </hiddenSegments>
      </requestFiltering>
    </security>
    <!-- Make sure error responses are left untouched -->
    <httpErrors existingResponse="PassThrough" />

    <!-- Restart the server if any of these files change -->
    <iisnode watchedFiles="web.config;*.js;browser/*.*" />
  </system.webServer>
</configuration>

Я надеюсь, что это может помочь другим в моей ситуации или, по крайней мере, полезно для обсуждения. Никто не любит ломать голову, пытаясь выполнить успешное развертывание в службе приложений Azure после обновления до версии 9. Пожалуйста, дайте мне знать, можно ли что-то улучшить, возможно, параметр сборки, чтобы избежать удаления папки сборки браузера или чего-то еще. Ваше здоровье.

person Sparker73    schedule 28.05.2020

Если вы хотите запустить приложение angular с рендерингом на стороне сервера:

1-Создайте новый проект:

ng new anguniversal

2-Включить рендеринг на стороне сервера (SSR)

ng add @nguniversal/express-engine

ШАГ 1

Firstly execute the command given below to build an Angular app with the express server.
npm run build:ssr

Теперь вы можете увидеть папку dist в папке вашего проекта.

ШАГ 2

Create a new folder in your windows server (for example name it as angular-universal) and copy the dist folder from the project folder here

ШАГ 3

Copy main.js file from dist/anguniversal/server folder and paste it direct in angular-universal folder.

ШАГ 4.

Создайте и откройте файл Web.config (в папке angular-universal) и добавьте в него код.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <add name="iisnode" path="main.js" verb="*" modules="iisnode" />
    </handlers>
    <rewrite>
      <rules>
        <rule name="DynamicContent">
          <match url="/*" />
          <action type="Rewrite" url="main.js"/>
        </rule>
        <rule name="StaticContent" stopProcessing="true">
          <match url="([\S]+[.](jpg|jpeg|gif|css|png|js|ts|cscc|less|ico|html|map|svg))" />
          <action type="None" />
        </rule>
      </rules>
    </rewrite>
    <staticContent>
      <clientCache cacheControlMode="UseMaxAge" />
      <remove fileExtension=".svg" />
      <remove fileExtension=".eot" />
      <remove fileExtension=".ttf" />
      <remove fileExtension=".woff" />
      <remove fileExtension=".woff2" />
      <remove fileExtension=".otf" />
      <mimeMap fileExtension=".ttf" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".svg" mimeType="image/svg+xml"  />
      <mimeMap fileExtension=".eot" mimeType="application/vnd.ms-fontobject" />
      <mimeMap fileExtension=".woff" mimeType="application/x-woff" />
      <mimeMap fileExtension=".woff2" mimeType="application/x-woff" />
      <mimeMap fileExtension=".otf" mimeType="application/otf" />
    </staticContent>
  </system.webServer>
</configuration>

ШАГ 5.

Установите узел IIS & Перезапись URL на сервере.

ШАГ 6.

Добавить веб-сайт… в IIS. введите описание изображения здесь

ШАГ 7.

В IIS перейдите в Пулы приложений. для созданного вами сайта (angular-universal). Затем измените версию .NET CLR на Без управляемого кода.

введите описание изображения здесь

Готово, можете проверить результат.

person AbolfazlR    schedule 06.03.2021

Следующий процесс сработал для меня после 2 дней проб и ошибок (Angular 8)

  • Assuming you followed https://angular.io/guide/universal
    • Assuming you changed the src\tsconfig.server.json as -- use this comment if tsconfig.server.json is generated inside src folder already

{
  "extends": "./tsconfig.app.json",
  "compilerOptions": {
    "outDir": "../out-tsc/app-server",
    "module": "commonjs"
  },
  "files": [
    "src/main.server.ts" -- old
    "main.server.ts" -- use this
  ],
  "angularCompilerOptions": {
    "entryModule": "./app/app.server.module#AppServerModule"
  }
}

  • И скомпилирован с использованием npm run build: ssr && npm run serve: ssr

  • Следуйте ответу 1 этого сообщения и установите iisnode со страницы https://github.com/tjanczuk/iisnode (при необходимости обратитесь к руководству этого парня. https://www.youtube.com/watch?v=JUYCDnqR8p0)

  • установить url-rewrite из ссылки
  • скопируйте папку dist в папку веб-сайта iis
  • Перемещайте контент, пока он не будет выглядеть следующим образом

website_root:.
│   server.js
│   web.config
│
├───dist
│   └───browser
│           3rdpartylicenses.txt
│           favicon.ico
│           index.html
│           main-es2015.da6c4688eda738c0ae37.js
│           main-es5.da6c4688eda738c0ae37.js
│           polyfills-es2015.0ef207fb7b4761464817.js
│           polyfills-es5.2b9ce34c123ac007a8ba.js
│           runtime-es2015.e8a2810b3b08d6a1b6aa.js
│           runtime-es5.e8a2810b3b08d6a1b6aa.js
│           styles.09e2c710755c8867a460.css
│
└───server
        main.js

Развернуть в Azure (на основе этого ответа по ссылке ** r3plica ) **

Единственное отличие - дополнительная задача копирования файлов, перемещающая папку сервера в корневой каталог.

Примечание

Если что-то не работает, всегда используйте node, чтобы указать на server.js this

node <path to server.js>

Это расскажет вам о самых простых вещах, которые вы ошиблись.

person Supun De Silva    schedule 13.10.2019
comment
Эй, как вы скопировали файлы server.js и web.config из корневой папки проекта в корневую папку dist во время или после сборки? Я бы хотел поступить так же, но у меня не получилось. Я пробовал angular.json, но он не позволяет настраивать ресурсы для сборки сервера, также после обновления до Angular 9 использование webpack не рекомендуется, и это было то, что я использовал для копирования файлов, установив плагин copy-webpack-plugin. Любое предложение? - person Sparker73; 20.05.2020
comment
Я сделал это после сборки. Использование конвейеров сборки Azure. Если вам нужен SS потока сборки, я могу куда-нибудь загрузить - person Supun De Silva; 22.05.2020
comment
О, боже, большое спасибо, мы не используем Azure Build Pipes, мы используем AppVeyor для CI / CD, но я все эти выходные сильно ломал голову над этим бизнесом, и, наконец, я кое-что от него получил.Это хак, который команда Angula CLI можно было избежать. Я все равно опубликую свое решение. - person Sparker73; 26.05.2020