21

I've created an app using AngularJS with GAE (Google App Engine – Java).

I want to convert it compatible with SEO.

index.html

  • <meta name="fragment" content="!" />
  • <base href="/">

and the body is loaded dynamically through <div ui-view></div>.

app.js

$locationProvider.html5Mode(true);

The url works fine but when I refresh page I get 404 error.

Do you have any idea, what this causes?

4
  • Its important that your server is configured, so it always load the index.html (using app.js). check your .htaccess Commented Jul 27, 2013 at 16:47
  • I don't have .htaccess. could you help me to configure it? Commented Jul 29, 2013 at 7:04
  • Check out the comments of STEVER's post. Commented Jul 29, 2013 at 13:34
  • None of the answers acceptable ? @user2625111
    – code_ada
    Commented Apr 20, 2018 at 5:43

6 Answers 6

20

I'm sure you've already solved this, but for anybody else running into this issue:

Basically AngularJS's $locationProvider.html5mode(true) makes use of HTML5's history.pushState(), which artificially changes the user's history and address bar URL without reloading the page. If you create a route (in Angular) for /about, but don't have any matching route on the server, you will run into the issue where reloading the page reveals the fact that it's not there on the server. The simplest solution is to mirror your entry point for your app (/index.html?) for all routes accessible by your app.

See: https://stackoverflow.com/a/16570533/1500501

11

It should be helpful, official angular doc; https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-configure-your-server-to-work-with-html5mode

Still I'll paste the relevent part here but I would advice to look at document.

Apache Rewrites

ServerName my-app

DocumentRoot /path/to/app

<Directory /path/to/app>
    RewriteEngine on

    # Don't rewrite files or directories
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^ - [L]

    # Rewrite everything else to index.html to allow html5 state links
    RewriteRule ^ index.html [L]
</Directory>

Nginx Rewrites

server {
server_name my-app;

index index.html;

root /path/to/app;

location / {
    try_files $uri $uri/ /index.html;
}
}

Azure IIS Rewrites

<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="/" />
    </rule>
  </rules>
</rewrite>

2
  • 2
    This link provides the most comprehensive answers for most platforms. ASP.NET users should note that the "Azure" answer is good for almost anything IIS related...including IIS Express.
    – Cos Callis
    Commented Sep 17, 2015 at 19:43
  • 2
    For God's sake! THIS SHOULD BE THE ACCEPTED ANSWER! It is server agnostic and provides all the info you need to know about the issue itself and how to solve it.
    – vinitius
    Commented Jan 27, 2017 at 20:46
1

Try adding below section in your grunt file liverload middleware section.

livereload: {
        options: {
          open: true,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect().use(
                '/app/styles',
                connect.static('./app/styles')
              ),
              connect().use(
                '/apply',
                connect.static('./app/index.html')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      }  
   }
1

for me, the fix to the the following line as the first line inside tag of you index (main) page:

<base href="/">

Plus you need to configure IIS rewrite rule as following: (make sure you install iis rewrite extension first)

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

0

For the Java app running on GAE, you can use

URL rewrite filter

You'll find and XML file named urlrewrite.xml . Put all your routes in this xml, and configure it in a way so when you get a request like:

  • /location/edit/120211

it will be redirected to

  • #/location/edit/120211

and your app will have time to be bootstrapped and fire the routing

0

It's been a while since people were looking for this answer but I needed it today. I've made a working example with GAE, angularJS and ng-Route that has pretty formatted links.

Here is the link to the GitHub example

1
  • 1
    Please do not post answers that are only a link to an external resource. If that link breaks, then your answer becomes invalid. Posting links to other resources is encouraged, but you should also include information in your post about relevant information from that external resource or otherwise. Please check out This meta post to learn more about why this is generally frowned upon and can be considered off-topic. Commented Jun 9, 2017 at 18:18

Not the answer you're looking for? Browse other questions tagged or ask your own question.