Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deploying multiple versions of Angular app to Azure App Service

I have an Angular application which I can deploy to Azure App Service without any issues.

First I compile my application using the following command:

ng build --output-path=dist --aot -prod

Then I add the following web.config to the dist folder:

<configuration>
    <system.webServer>
         <rewrite>
            <rules>
              <rule name="AngularJS 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="/" />
              </rule>
            </rules>
          </rewrite>
          <caching enabled="true" enableKernelCache="true">
              <profiles>
                  <add extension=".js" policy="DisableCache" kernelCachePolicy="DisableCache" />
              </profiles>
          </caching>
    </system.webServer>
</configuration>

I then zip the contents of the dist folder up and drag it into my Azure application ( https://<site.scm.azurewebsites.net>/ZipDeploy ). At this point the app works fine.

My problem is that I would like to deploy different versions of the application for different locales.

I compile my different versions using the following commands:

ng build --output-path=dist/en --aot -prod --bh /en/ --i18n-format=xlf --locale=en

ng build --output-path=dist/fr --aot -prod --bh /fr/ --i18n-file=src/locale/messages.fr.xlf --i18n-format=xlf --locale=fr

This outputs the folders en and fr to /dist containing the different versions of the app. I add a web.config to each version of the app e.g inside /dist/en and dist/fr.

Next, I zip up the en & fr folders and deploy it using ZipDeploy as above.

I can see my application homepage working fine at:

https://<site>.azurewebsites.net/en
https://<site>.azurewebsites.net/fr

However - when I get redirected to my application at https://<site>.azurewebsites.net/fr/redirect.html#state.... (I'm signing in using Azure B2C), I get the following error:

You do not have permission to view this directory or page.

This feels like iis is trying to literally interpret my url as a directory instead of letting Angular handle the routing but I'm not sure.

Does anybody know how to do this correctly?

like image 263
TomSelleck Avatar asked Apr 11 '18 13:04

TomSelleck


People also ask

Can we deploy Angular app in Azure App Service?

You'll create your Angular app locally with Angular CLI. You'll push it to a GitHub repository. You'll create a static web app on Azure and connect it to the “main” branch of the project's repository. You'll create a “develop” repository.

Can we deploy multiple applications in app service?

Yes, the setup is very much possible and is a common requirement. You can deploy multiple separate 'WebApps' under an 'App Service Plan'.

How do you deploy Angular app Azure App Service from Visual Studio code?

Open the VS Code and open the project folder path. In VS code search Azure App Service and install. Before deploying to Azure, we must build our Angular app using the below command which will build the Angular project and will create all necessary files to a dist folder.


2 Answers

For anyone looking for a generic solution see below.

It does 2 things:

  • Handle default language via redirect (our default language is de)
  • Handle rewires for any language
    • it uses regex to capture the language part (2 character language string + slash) from the beginning of the path, for example de/ or en/
    • it then uses the capture group to rewrite the path

Note:

  • This will not limit which language codes a user can request via url
  • If you want to be specific which languages are supported you can replace the regex with the following to only support de + en + fr:
    ^((?:de|en|fr)\/).*
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <httpRedirect enabled="true">
      <add wildcard="/" destination="/de" />
    </httpRedirect>  
    <rewrite>
      <rules>
        <rule name="angular" stopProcessing="true">
          <match url="^(.{2}\/).*" />
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
          </conditions>
          <action type="Rewrite" url="/{R:1}" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>
like image 137
ntziolis Avatar answered Oct 08 '22 01:10

ntziolis


We had also the problem for our i18n multi-languages website created by angular-cli.

What you need:

1) ensure that you have only 1 web.config in the root folder (not under ./fr or ./en)

2) ensure that your fr/index.html has the right base tag

<base href="/fr/">

3) ensure that your en/index.html has the right base tag

<base href="/en/">

4) the content of your unique web.config needs to include the following code:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
      <rewrite>
        <rules>
            <rule name="SPA Routes FR" stopProcessing="true">
                <match url="fr/.*" />
                <conditions logicalGrouping="MatchAll">
                    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                    <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                    <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
                </conditions>
                <action type="Rewrite" appendQueryString="true" url="fr/index.html" />
            </rule>
            <rule name="SPA Routes EN" stopProcessing="true">
                <match url="en/.*" />
                <conditions logicalGrouping="MatchAll">
                    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                    <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                    <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
                </conditions>
                <action type="Rewrite" appendQueryString="true" url="en/index.html" />
            </rule>
        </rules>
    </rewrite>
  </system.webServer>
</configuration>

The "appendQueryString" is needed if you have some query parameters with your URL.

like image 25
hugo Avatar answered Oct 08 '22 00:10

hugo