3

I have created an Asp.NET Core Web Application with Angular 9. I have added Angular Universal to my application. Now I need to publish my application into the Azure app service.

I have used the following command to build an application,

npm run build:ssr

After building angular universal application it will give two folder structures under the dist folder.

dist/{app-name}/browser
dist/{app-name}/server

For run the angular app separately using the following command,

npm run serve:ssr

It's working fine locally. Now I need to publish the application in the Azure app service. So far I have searched a lot of things and integrated them. But unfortunately, I did not find any solution to work for the last four days.

I need some more details about how to configure on .Net core side.

Can anyone help me to solve this issue? Any help is highly appreciated.

Edit:- I have followed the below answer the same thing

Angular 9 universal deployment woes

Here is my web.config file,

<?xml version="1.0" encoding="utf-8"?>
 <configuration>
<system.webServer>
    <webSocket enabled="false" />
    <handlers>
        <add name="iisnode" path="main.js" verb="*" modules="iisnode"/>
    </handlers>
    <rewrite>
        <rules>
            <rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
                <match url="^main.js\/debug[\/]?" />
            </rule>
            <rule name="StaticContent">
                <action type="Rewrite" url="public{REQUEST_URI}"/>
            </rule>
            <rule name="DynamicContent">
                <conditions>
                    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
                </conditions>
                <action type="Rewrite" url="main.js"/>
            </rule>
            <rule name="Angular Routes" stopProcessing="true">
                <match url=".*" />
                <conditions logicalGrouping="MatchAll">
                    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                    <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                </conditions>
                <action type="Rewrite" url="/index.html" />
            </rule>
        </rules>
    </rewrite>
    <security>
        <requestFiltering>
            <hiddenSegments>
                <remove segment="bin"/>
            </hiddenSegments>
        </requestFiltering>
    </security>
    <httpErrors existingResponse="PassThrough" />
</system.webServer>

Yaml file,

pool:
name: Azure Pipelines
steps:   
- task: NodeTool@0
 displayName: 'Use Node 12.x'
 inputs:
  versionSpec: 12.x

 - task: Npm@1
 displayName: 'npm install angular cli'
 inputs:
  command: custom
  verbose: false
  customCommand: 'install @angular/cli -g'

- task: Npm@1
   displayName: 'npm install'
   inputs:
    verbose: false

- task: Npm@1
    displayName: 'npm build'
    inputs:
     command: custom
    verbose: false
    customCommand: 'run build:ssr'

- task: CopyFiles@2
    displayName: 'Copy dist files to staging'
    inputs:
    SourceFolder: dist
    TargetFolder: '$(Build.ArtifactStagingDirectory)/dist'

- task: CopyFiles@2
    displayName: 'Copy web.config'
    inputs:
    Contents: web.config
    TargetFolder: '$(Build.ArtifactStagingDirectory)'

- task: CopyFiles@2
    displayName: 'Copy main.js'
    inputs:
    SourceFolder: 'dist/angular-ssr/server'
    Contents: main.js
    TargetFolder: '$(Build.ArtifactStagingDirectory)'

 - task: AzureRmWebAppDeployment@4
    displayName: 'Azure App Service Deploy: sample-dev'
    inputs:
    azureSubscription: 'subscription'
   WebAppName: 'sample-dev'
   packageForLinux: '$(Build.ArtifactStagingDirectory)'
   ConfigurationSettings: '-Handler iisnode -NodeStartFile server.js -appType node'
   enableCustomDeployment: true

server.ts file,

import 'zone.js/dist/zone-node';
import { ngExpressEngine } from '@nguniversal/express-engine';
import * as express from 'express';
import { join } from 'path';
import { AppServerModule } from './src/main.server';
import { APP_BASE_HREF } from '@angular/common';
import { existsSync } from 'fs';
// The Express app is exported so that it can be used by serverless 
 Functions.
 export function app() {
  const server = express();
  const distFolder = join(process.cwd(), 'dist/angular-ssr/browser');
  const indexHtml = 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;
  }

  function run() {
   const port = process.env.PORT || 4000;

  // Start up the Node server
   const server = app();
    server.listen(port, () => {
     console.log(`Node Express server listening on 
 http://localhost:${port}`);
 });
}

 // Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
  // The below code is to ensure that the server is run only when not 
 requiring the bundle.
  declare const __non_webpack_require__: NodeRequire;
  const mainModule = __non_webpack_require__.main;
   const moduleFilename = mainModule && mainModule.filename || '';
    if (moduleFilename === __filename || moduleFilename.includes('iisnode')) 
   {
      run();
    }

    export * from './src/main.server';

Facing no error in Pipeline,

enter image description here

But facing an error while hit the URL

enter image description here

I have missed any steps?. Can you help me, anyone?

MrBoJangles
  • 12,127
  • 17
  • 61
  • 79
Karnan Muthukumar
  • 1,843
  • 1
  • 8
  • 15
  • Are you just running this as a standalone, ie your spa is self contained, or does the spa make calls to the api in asp.net core? If it's self contained then you deploy everything in the dist folder in your appservice. If it's the latter, then in addition to the dist, you need to publish the binaries from your api and include those in your appservice. You will need to configure a web.config file to serve up both the spa and api. Alternatively, you can have a second app service for your api seperate from the spa. – allan Sep 17 '20 at 06:51
  • Can you share me some details about web.config file @allan – Karnan Muthukumar Sep 17 '20 at 06:54
  • No. It's not standalone application. It makes a call to API. – Karnan Muthukumar Sep 17 '20 at 06:54
  • I think the problem here might be how your application is configured. Can you check the configurations in azure and make sure you have a **WEBSITE_NODE_DEFAULT_VERSION** set? Mine is set to 8.9.4 – r3plica Sep 17 '20 at 18:14

0 Answers0