The Sampson Project

How to run Angular2 and htaccess

« Back to Blogs

How to setup .htaccess rules with Angular 2


The second major version of Angular is awesomely powerful. By pre-compiling templates into code highly optimized for today's JavaScript, it gives you all the benefits of hand-written code with the productivity of a framework. Once the first view is rendered, subsequent pages are routed through the integrated Component Router for near-instant rendering.

A cool feature of the new Component Router is code-splitting. Users load only the code required to render the view they request.

Because all pages are loaded through the Angular2 Router, what happens when when you need to load a URL directly? Well, nothing! you're going to get a 404 Not Found error. Because Javascript does all the routing, even though you see your path in the URL bar, you technically never navigate away from your index page. To get to a certain component, first you have to load you main page, then navigate to your desired component.

Seems like a major downside right?? How do we get around that? One way is to use prepend index.html to the request path. Instead of going to example.com/place/to/go you can do example.com/index.html?place/to/go and Angular2 will redirect you to the correct component. But that is not user friendly. If a user is at a page, and they copy down what is in the URL bar, they are going to expect to be able to return to that page by going back that URL.

Luckily, there IS a better way. Two actually. the first is to instead use the "HashLocationStrategy" class. Instead of your pretty folder structure URL example.com/place/to/go users see example.com#place/to/go. Ugly, but it works. The better solution (read: my preferred solution) is to utilize server-side URL rewriting. Let's use Apache and .htaccess as an example.

.htaccess

To load a a URL to directly, you need to route any page requests to your index page. In Apache, you do that by using rewrite rules. Here's a sample that routes all URLs to index.html in the root of your web directory.


# turn on the rewrite engine
RewriteEngine On

# set the rewrite base to your root path
RewriteBase /

# don't rewrite if file exists
RewriteCondition %{REQUEST_FILENAME} !-f

# capture the uri and append it as query string
RewriteRule $(.*)$ index.html?$1

Save the code above as .htacess, and place it the the root of your website. Now you can access any component by the same path you setup in angular e.g.example.com/component

The above solution is great if your entire SPA (single page app) lives in Angular. But most apps need data and data means you need a backend. To request data from a php file, you COULD have the php file in your request route (easiest way). Since the above rule doesn't rewrite files that exist, you'll be just fine. But, I'm a fan of modular routing. I want to request a path for my data and have it work on any backend (php, ruby, node.js) with minimal modification.

What we can do instead is add a route prefix for angular.

Route Prefixes

There are many ways you might approach tackling this issue. The way I chose is to use route prefixes. Any route that should be sent to Angular, prepend with ng/ so our request for the blog component becomes example.com/ng/blog

Now all we have to do is update our .htaccess


# turn on the rewrite engine
RewriteEngine On

# set the rewrite base to your root path
RewriteBase /

# if the request starts with ng
RewriteCond %{REQUEST_URI} ^/ng

# and the request doesn't point to a file
# (important to prevent an infinite loop)
RewriteCond %{REQUEST_FILENAME} !-f

# rewrite to index.html
RewriteRule ^(.*)$ index.html?$1


With the above rule, you can add additional routes for your backend without having to worry about your angular app hijacking your requests. This was a super basic example, so it won't cover everything, but it should get you headed in the right direction. For a more in-depth look at .htaccess rewrites check out this excellent blog post. I hope this post has been valuable, next will be a write up on how to combine FCGI, Sinatra and Angular2 to build a simple personal blog on shared hosting. Til Next Week!