30

I have simple angular2-cli app (one page with model driven form - no router involved). With "ng serve" all works fine. I made production version with ng build --product. I copied all ./dist folder content into new folder under C:\inetpub\wwwroot. I made virtual app from IIS managment console. Defualt app file is index.html. I browse to app uri and i get only page with "Loading...". I try build without --product switch (only ng build) but result is the same. Angular app is not loading. Is there anything else needed to publish angular app on IIS?

PaulStanek
  • 451
  • 2
  • 5
  • 7
  • check browser console for errors if it just says 'Loading...' – Poul Kruijt Dec 23 '16 at 16:41
  • I found what was wrong. In index.html I should have instead . When I added dot, everything starts working. – PaulStanek Dec 24 '16 at 20:27
  • 1
    You will have a problem if you are going to use the router. But as you mentioned you won't, which means href=". " should suffice. You probably published your app in a subfolder. You can also use this subfolder name as base href – Poul Kruijt Dec 25 '16 at 07:02
  • You can deploy it without any Web.config – PrathapG Oct 03 '18 at 08:50

12 Answers12

37

Here is how I solve this situation;

  • Create project with angular-cli
  • Build your application with ng build
  • Open IIS, create new virtual directory and show dist folder
  • Set base href in your index.html from / to /yourAliasNameOnIIS
  • Use this web.config for redirecting requests to your index.html page

    <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" />
            <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
          </conditions>
          <action type="Rewrite" url="/yourAliasNameOnIIS" />
        </rule>
      </rules>
    </rewrite>
    

  • Convert your virtual directory to a web application

You can also use ng build --deploy-url "/yourAliasNameOnIIS" to change src path in dist/index.html.

I hope it helps!

Flea
  • 11,176
  • 6
  • 72
  • 83
ulubeyn
  • 2,761
  • 1
  • 18
  • 29
  • 6
    Just a note, the `--deployUrl` does not exist anymore (not sure if it ever was there), it's now `--deploy-url`. Further, it may be useful to also use `--base-href` to actually change the base href. The deploy url command simply changes the script src locations. – Newteq Developer May 12 '17 at 08:41
  • I followed this approach but was getting 404 errors on all css, js files etc. – Flea Sep 12 '17 at 18:23
  • Can you also do these steps with dummy project? I mean can you just create new empty angular project and do these steps? – ulubeyn Sep 12 '17 at 18:27
  • 2
    I answered the question with additional IIS Re-Write rules which added a little more functionality: https://stackoverflow.com/a/47442941/558509 – samneric Nov 22 '17 at 19:59
  • What if I don't want to host it in a virtual directory? What If I have another website built for it? Also can we somehow don't do that base href change? – mohammad rostami siahgeli Jan 15 '18 at 08:23
  • @mohammadrostamisiahgeli, good point! We change base href because we host it in a virtual directory. But I do not how to serve it as you mentioned. Please make an update if you find a better way. – ulubeyn Jan 15 '18 at 08:28
  • The base href did it for me. We host multiple apps under one site and I always forget this the first time I deploy to IIS. – Neville Mar 01 '19 at 14:05
  • i couldn't make it work without: `/yourAliasNameOnIIS/` (slash before and after) in both `web.config` and `index.html` – Learner Apr 11 '22 at 11:50
13

When you open the dev tools of your browser, you would have seen 404 messages when the app was trying to donwload the js, css etc files

You need to set the base href in index.html to

<base href="./">

this will make sure the base ref is relative to where your website lives in IIS. You also need to use hash location strategy otherwise, IIS will intercept your ng2 router URL changes and try to find a controller/action for the URL.

under the imports of your app.module.ts:

RouterModule.forRoot(routerConfig, { useHash: true })

I have done these 2 steps and all is working perfectly on Azure VM with IIS. Doing it this way also means it you do not have to put your SPA on the root and you can have multiple SPA's running happily next to each other (in different websites on IIS)

Jan Feyen
  • 535
  • 3
  • 13
  • Thank you, but exists a way to deploy the app without the use of hash? that's my main problem. Everything works great, but if you want to navigate to a specific route (like www.site.com/login) IIS returns 404 (expected behavior) but if the navigation it's made using the application, works fine (the problem comes using the navigation bar from the explorer) – Isaac Ojeda Jul 07 '17 at 19:26
  • add this to web.config: – Jan Feyen Apr 21 '18 at 08:08
7

For me, it was very simple:

  1. Run the ng build command. It will generate the dist folder.
  2. Make href="" in the index.html file.
  3. Give the dist folder path to IIS application and it will work.

This makes it even simpler, you do not need to modify the index.html file:

ng build -prod --base-href
Paweł Szczur
  • 5,484
  • 3
  • 29
  • 32
Dileep
  • 338
  • 4
  • 13
3

I referred many suggestion, what worked for me was this link

A good explanation why things need to be configured in a different way for an Angular app are clearly described here. Followed the steps in the link and then I added a web.config within the published files folder location with the below settings:

<?xml version="1.0"?>
<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" />
            <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
          </conditions>
          <action type="Rewrite" url="/" />
        </rule>
      </rules>
  </rewrite>
 </system.webServer>
</configuration>

The settings are also described in the link above. Hope this help someone.

Zaker
  • 537
  • 16
  • 30
2

I tried the below approach it worked.

  1. Create new website in IIS (through inetmgr)
  2. use "ng build --prod" - generating production version code
  3. Copy the dist folder's files then paste it to root folder of IIS website (Don't copy the folder and put that into root folder of IIS Website which will cause an issue)
  4. Set the credentials, authorization and etc... from your end.
  5. Set the root folder's access permission for "MACHINE_NAME\IIS_IUSRS & MACHINE_NAME\NETWORK SERVICE"
  6. Set the default page as "index.html" in IIS
  7. Now you can browse the website.
Srinivasan K K
  • 418
  • 4
  • 10
  • 1
    I have a few proxy settings in proxy.conf.js file. After running "ng build --aot --prod" I deployed the dist files as-is. The website is up and running but the pages that use the proxy settings are still using localhost. How do I setup the proxy settings in production? – user2347528 Sep 19 '17 at 17:36
  • "Copy the dist folder's files then paste it to root folder of IIS website (Don't copy the folder and put that into root folder of IIS Website which will cause an issue)". Can you explain me what issue? – Newbie Apr 07 '18 at 03:56
1

In addition to ulubeyn's answer that mostly worked for me, I added my own IIS re-write rules to enable:

1) the initial redirection from /dist to alias 2) Javascript downloads from alias and 3) Angular routing on the alias

<rules>
  <rule name="Redirect from blank URL to IIS Alias" stopProcessing="true">
    <match url="^/?$" />
    <action type="Rewrite" url="/MyDist" />
  </rule>
  <rule name="Redirect from /dist folder to IIS Alias" stopProcessing="true">
    <match url="^(.*)/dist" />
    <action type="Rewrite" url="/yourAliasNameOnIIS" />
  </rule>
  <rule name="Allow Angular URL Routing on IIS Alias" stopProcessing="true">
    <match url="^yourAliasNameOnIIS/*" />
    <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" url="/yourAliasNameOnIIS" />
  </rule>
  <rule name="Redirect to IIS Alias folder with parameters" stopProcessing="true">
    <match url="(.*)" />
    <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" url="/yourAliasNameOnIIS/{R:1}" appendQueryString="true" />
  </rule>
</rules>
samneric
  • 3,038
  • 2
  • 28
  • 31
1

for those who use angular i18n, you have to build the app for each language and put them in separate folders

ng build --output-path=dist/fr --prod --bh /fr/
ng build --output-path=dist/en --prod --bh /en/

and here is the config for iis

<?xml version="1.0" encoding="UTF-8"?>
 <configuration>
  <system.webServer>
    <directoryBrowse enabled="true" />
    <rewrite>
        <rules>
            <rule name="Imported Rule 1" stopProcessing="true">
                <match url="^../index\.html$" ignoreCase="false" />
                <action type="None" />
            </rule>
            <rule name="Imported Rule 2" stopProcessing="true">
                <match url="(..)" ignoreCase="false" />
                <conditions logicalGrouping="MatchAll">
                    <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
                    <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
                </conditions>
                <action type="Rewrite" url="{R:1}/index.html" />
            </rule>
            <rule name="Imported Rule 3">
                <match url="^$" ignoreCase="false" />
                <conditions logicalGrouping="MatchAll">
                    <add input="{HTTP_ACCEPT_LANGUAGE}" pattern="^fr" />
                </conditions>
                <action type="Redirect" url="/fr/" redirectType="Found" />
            </rule>
            <rule name="Imported Rule 5">
                <match url="^$" ignoreCase="false" />
                <conditions logicalGrouping="MatchAll">
                    <add input="{HTTP_ACCEPT_LANGUAGE}" pattern="^es" negate="true" />
                </conditions>
                <action type="Redirect" url="/en/" redirectType="Found" />
            </rule>
        </rules>
    </rewrite>
 </system.webServer>
 </configuration>
Fateh Mohamed
  • 20,445
  • 5
  • 43
  • 52
1

You can deploy it without any Web.config file as below,


You can find index.html in dist folder inside it find base href tag

now change its path as accordingly

Ex -: if deploying inside wwwroot

<base href="/">

Ex-: if deploying inside a folder in wwwroot

<base href="/FolderName/">
PrathapG
  • 751
  • 1
  • 7
  • 21
0

add web.config file to location app/src/ content of web.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>    
<system.webServer>
  <rewrite>
    <rules>
      <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>
</system.webServer>
</configuration>

in .angular-cli.json add web.config to assets section as follows:

"assets": [
    "assets",
    "favicon.ico",
    "web.config"
],
0

On IIS, you have to copy a web.config to the deployed folder:

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

<system.webServer>
  <security>
    <requestFiltering>
      <fileExtensions>
        <add fileExtension=".json" allowed="true" />
        <add fileExtension=".woff2" allowed="true" />
      </fileExtensions>
    </requestFiltering>
  </security>
  <staticContent>
    <remove fileExtension=".woff2" />
    <mimeMap fileExtension=".woff2" mimeType="application/json" />
    <remove fileExtension=".json" />
    <mimeMap fileExtension=".json" mimeType="application/json" />
  </staticContent>
  <rewrite>
    <rules>
      <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>
</system.webServer>

</configuration>

You can automatized like this creating the web.config file inside src and then adding this on .angular-cli.json:

"assets": [
    "assets",
    "favicon.ico",
    "web.config"
],
Xelz
  • 1,059
  • 2
  • 11
  • 16
0

what worked for me and very easy was to first configure my route as such

RouterModule.forRoot([
--some routes-- 
], { useHash: true })

so all my routes had # in front of them then use

ng build --base-href "./" --prod 

to build and then deployed my app in a folder inside wwwwroot.

0

Follow below steps:

  1. run below command. [ng build --prod --base-href='/']
  2. Create a folder i.e. "D:\SmartTrader-Angular"
  3. Copy dist content to D:\SmartTrader-Angular folder
  4. Create IIS site enter image description here
  5. No need to create web.config file.
  6. Restart site in IIS.
  7. It should be working now.