Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

azure - Angular 9 universal deployment woes

Honestly, I find it so annoying that this keeps changing. I solved this very issue in an easlier version of Angular here:

Deploying Angular Universal to Azure

But now this is out of date. There is no server.js generated anymore, instead you have to amend your web.config to point the the main.js which sounds like an improvement. I updated my yaml to this:

pool:
  name: Azure Pipelines
steps:
- task: gittools.gitversion.gitversion-task.GitVersion@5
  displayName: GitVersion

- 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: '$(Build.SourcesDirectory)/dist'
    TargetFolder: '$(Build.ArtifactStagingDirectory)/app/dist'

- task: AzureRmWebAppDeployment@4
  displayName: 'Azure App Service Deploy: app-name'
  inputs:
    azureSubscription: 'Pay-As-You-Go (f61dc7cf-0ca2-4982-bbe7-9b6527c2962b)'
    WebAppName: r3plica
    packageForLinux: '$(Build.ArtifactStagingDirectory)/app'
    WebConfigParameters: '-Handler iisnode -NodeStartFile dist/app-name/server/main.js -appType node'

And that should be it, but ofcourse, it's not that simple. Now I am getting an error if I run node dist/app-name/server/main.js. It's returning this:

ReferenceError: Blob is not defined at createBase64WorkerFactory (D:homesitewwwrootdistapp-nameservermain.js:1:1418371)

So I did a bit of looking around and someone suggested I install npm install --save-dev blob-polyfill which I did and then edit the server.ts file:

import { Blob } from 'blob-polyfill';

global['Blob'] = Blob;

But this does not have appeared to have done anything. The error still persists. Does anyone know what I have to do?


UPDATE

I decided to give this another go today. I ran npm build:ssr and copied the server & browser folders to a local webserver and ran node server/main.js and it complained that it couldn't find an index.html file at dist/my-project/browser/index.html which helped me. So I copied the entire dist folder to wwwroot and ran node dist/my-project/server/main.js and it worked.

So I updated my pipeline to do the same. I verified that it actually copies the whole dist folder and then I copy the web.config to the root. My web.config file looks like this:

<configuration>
    <system.web>
        <customErrors mode="Off" />
    </system.web>
    <system.webServer>
        <staticContent>
            <remove fileExtension=".woff2" />
            <mimeMap fileExtension=".woff2" mimeType="font/woff2" />
        </staticContent>
        <handlers>
            <!-- Indicates that the server.js file is a node.js site to be handled by the iisnode module -->
            <add name="iisnode" path="dist/my-project/server/main.js" verb="*" modules="iisnode"/>
        </handlers>
        <httpErrors errorMode="Detailed"></httpErrors>
    </system.webServer>
</configuration>

But when I try to load my website it just gives me an error:

HTTP Error 403.14 - Forbidden

A default document is not configured for the requested URL, and directory browsing is not enabled on the server.

which is really annoying. I had a look at the https://example.scm.azurewebsites.net and went to the debug console and typed node dist/my-project/server/main.js which came back with:

Node Express server listening on http://localhost:4000

So it should be working fine as far as I can tell. Does anyone have any idea why it isn't?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

So, once again I have managed to fix this. I poured hours into it and it was beginning to drive me mad. I decided to set up a local web server (iss) and try everything I could. In the end, it was this that saved me because iisnode was logging errors and I could see what was wrong.

If I kept the folder structure as it is when you do npm run build:ssr and update the webconfig to point to main.js like <add name="iisnode" path="dist/example-project/server/main.js" verb="*" modules="iisnode"/> you get an error similar to this:

Error: Failed to lookup view "index" in views directory "C:inetpubwwwrootdistexample-projectserverdistexample-projectrowser"

As you can see from the error, it's using a relative path from where main.js is. From this you can probably see how I fixed my issue.

I updated my tasks to include a new copy and I copy main.js to the root and update my web.config to this:

<add name="iisnode" path="main.js" verb="*" modules="iisnode"/>.

For completeness, here is my full web.config

<?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>
</configuration>

And this is my xaml for azure:

pool:
  name: Azure Pipelines
steps:
- task: gittools.gitversion.gitversion-task.GitVersion@5
  displayName: GitVersion

- task: NodeTool@0
  displayName: 'Use Node 12.x'
  inputs:
    versionSpec: 12.x
    checkLatest: true

- 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: '$(Build.SourcesDirectory)/dist'
    TargetFolder: '$(Build.ArtifactStagingDirectory)/dist'

- task: CopyFiles@2
  displayName: 'Copy web.config'
  inputs:
    SourceFolder: '$(Build.ArtifactStagingDirectory)/dist/example-project/browser'
    Contents: web.config
    TargetFolder: '$(Build.ArtifactStagingDirectory)'

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

- task: AzureRmWebAppDeployment@4
  displayName: 'Azure App Service Deploy: example-project'
  inputs:
    azureSubscription: 'Your Subscription'
    WebAppName: 'example-project'
    packageForLinux: '$(Build.ArtifactStagingDirectory)'
    enableCustomDeployment: true
    RemoveAdditionalFilesFlag: true

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share

2.1m questions

2.1m answers

62 comments

56.5k users

...