How to get html5Mode application to be root relati

2019-08-06 05:53发布

问题:

To help with SEO and deep linking, I turned on html 5 mode in my angular project like this:

index.html

<base href="/webapplicationname/">

app.js

  // use the HTML5 History API
  $locationProvider.html5Mode(true);

web.config

  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Main Rule" 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="/webapplicationname/" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>

My IIS Express debugging root is http://localhost:10223 and my local dev root is http://myvirtualmachine/webapplicationname.

/webapplicationname/ does not exist in my debugging set up. Nor does it exist in the other environments past dev. But it has been handed down to me that any environment could be off the root or be in a web application folder with a name I don't control, so I can't count on or make a pattern.

I want to just use / as my base. If I did, it would work in debugging. I want to have that work in other environments regardless of where the web application lives relative to the web server root.

As it stands, If I change the root to /, as in <action type="Rewrite" url="/" /> and <base href="/">, / points to the wrong place in my local dev environment. It would point to http://myvirtualmachine/ instead of http://myvirtualmachine/webapplicationname, which will cause 404s. It needs to point to the root of my app, not the root of the web server!

How can I get ~/-like functionality here?

回答1:

Instead of changing the base, you can use the $locationProvider like

$locationProvider.html5Mode({
  enabled: true,
  requireBase: false
});

This should help you.



回答2:

Here's what I did to get this working. If anyone has a cleaner way, please let me know.

I did turn off requireBase as Rabi said, which I think helps if you are dynamically creating the base.

  $locationProvider.html5Mode({
    enabled: true,
    requireBase: false
  });

Instead of <base href="WhateverTheApplicationRootIs" />, I did this at the same spot in the html head element:

  <script type="text/javascript">
    var firstPathPart = document.location.pathname.split("/")[1];
    var href;
    switch (firstPathPart) {
      case '':
      case 'login':
      case 'forgot-password':
      case 'activation':
      case 'home':
      case 'mymainmenu1':
      case 'mymainmenu2':
      case 'profile':
        href = '/';
        break;
      default:
        href = '/' + firstPathPart + '/';
    };
    document.write("<base href='" + href + "' />");
  </script>

which basically says dynamically write the base. Write the base to point to the first segment of the url path, except if that happens to be one of my top level angular paths, in which case make the root /.

In the web.config, I left the reference to /webapplicationname/. That's allowed in our shop, as web.config is considered environment specific anyway. So it's allowed to vary from environment to environment and be managed containing separate settings.

Why did I do this? Because having the base be different things in different environments is not acceptable in our shop. index.html is source code, not configuration. The source code has to be the same in every environment although settings files like web.config are allowed to vary.