People collaborating

Installing WordPress on top of your Angular App

The problem

When companies decided to build their core application with modern Javascript libraries and frameworks such as React, Vue.js or Angular, they do so because of their native feel and amazing user experience. As the application scales and the proof of concept is achieved, more time and money will be invested in marketing and improving SEO.

Soon the marking team will want to run their own experiments to try and increase the conversion rate and test other campaigns. Now the marketing team will flood the engineering teams backlog with marketing related tasks such as updating blog posts, changing images, user flow tracking integrations, etc. This will exponentially slow down the rate of development on business objectives. So how do you give the marketing team their freedom and clear up the engineering back log?

The solution

Give the people what they want! A solution I’ve used a few times now is to install and and configure WordPress to take care of the static pages of the website. As you probably already know WordPress ships with a great admin user interface where almost anyone and log in and alter the static parts of the website with little or no technical experience. With a WordPress admin interface, the marketing team won’t have to bother the engineers with tasks that could disrupt their focus.

NOTE: There are plenty of other great content management systems out there that will do the job.

I’ve shared the nignx configuration below that I’ve used to direct traffic to the right code base depending on the requested route. I serve the WordPress pages from the http://www.my-app.com/ base directory and the Angular application from a sub-directory http://www.my-app.com/app/.

server {

    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www/wordpress;
    index index.html index.php;

    server_name www.my-app.com; 
    server_tokens off; 

    error_log /var/log/nginx/error.log; 
    access_log /var/log/nginx/access.log; 

    ##########################
    #### WordPress Routes ####
    ##########################

    location = / {
        # WordPress site log files
        error_log /var/log/nginx/wordpress-error.log; 
        access_log /var/log/nginx/wordpress-access.log; 
        try_files $uri $uri/ /index.php?$args;
    }

    # Other WordPress routes ...

    location ~ .php$ {
        fastcgi_split_path_info ^(.+.php)(/.+)$;
        include fastcgi_params;
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
    }

    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }

    location ~* .(js|css|png|jpg|jpeg|gif|ico)$ {
        expires max;
        access_log off;
        log_not_found off;
    }

    # robots.txt fallback to index.php
    location = /robots.txt {
        # Some WordPress plugins gererate robots.txt file
        allow all;
        try_files $uri $uri/ /index.php?$args @robots;
        access_log off;
        log_not_found off;
    } 

    # additional fallback if robots.txt doesn't exist
    location @robots {
        return 200 "User-agent: *\nDisallow: /wp-admin/\nAllow: /wp-admin/admin-ajax.php\n";
    }

    # Deny all attempts to access hidden files such as
    #.htaccess, .htpasswd, .DS_Store (Mac) excepted
    # .well-known directory. Keep logging the requests 
    # to parse later (or to pass to firewall
    # utilities such as fail2ban)
    location ~ /.(?!well-known\/) {
        deny all;
    }

    # Deny access to any files with a .php extension 
    # in the uploads directory for the single site
    location /wp-content/uploads {
        location ~ .php$ {
            deny all; 
        }
    }

    # Deny access to any files with a .php extension
    # in the uploads directory
    # Works in sub-directory installs and also in 
    # multisite network
    # Keep logging the requests to parse later 
    # (or to pass to firewall utilities such as fail2ban)
    location ~* /(?:uploads|files)/.*.php$ { 
        deny all; 
    } 


    ##########################
    ####  Angular Routes  ####
    ##########################

    location ^~/app/ {
        # User Portal log files
        error_log /var/log/nginx/portal-error.log;
        access_log /var/log/nginx/portal-access.log;
        alias /var/www/dist/my-angular-bundle/;
        try_files $uri$args $uri$args/ /index.html =404;
    }
}

Comment if you have any questions!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.