<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Martin</title>
    <description>The latest articles on DEV Community by Martin (@junkern).</description>
    <link>https://dev.to/junkern</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F401219%2Fdffa8ed4-8a86-426d-b2e7-d30544d32800.png</url>
      <title>DEV Community: Martin</title>
      <link>https://dev.to/junkern</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/junkern"/>
    <language>en</language>
    <item>
      <title>Best practices on responding to AJAX calls in Wordpress Plugins</title>
      <dc:creator>Martin</dc:creator>
      <pubDate>Fri, 20 Nov 2020 10:28:28 +0000</pubDate>
      <link>https://dev.to/junkern/best-practices-on-responding-to-ajax-calls-in-wordpress-plugins-439b</link>
      <guid>https://dev.to/junkern/best-practices-on-responding-to-ajax-calls-in-wordpress-plugins-439b</guid>
      <description>&lt;p&gt;&lt;em&gt;Preface (you can skip it, if you want): A customer came up to me with a request to build an application and combine it with an existing Wordpress installation. At the beginning I was hesitant, but I found, that using "Wordpress as a Backend" has quite a few advantages: It has baked-in user roles and capabilites and you can use already existing plugins to simplify your own development.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Task
&lt;/h2&gt;

&lt;p&gt;As I mentioned in the preface, using Wordpress as a backend comes with a few benefits, I decided to program the new application as a plugin. But I neither wanted to use the (sometimes weird) combination of PHP and HTML nor send all the needed data via forms to the backend.&lt;/p&gt;

&lt;p&gt;I wanted to stick with tools I was more familiar with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I choose Vue.js as my frontend for the application.&lt;/li&gt;
&lt;li&gt;And the backend would be a Wordpress plugin.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When developing with a frontend framework like Vue.js, you have to use AJAX calls for communication with your backend. And that's when I found out, that the existing documentation on AJAX with Wordpress feels quite old (&lt;a href="https://codex.wordpress.org/AJAX_in_Plugins"&gt;https://codex.wordpress.org/AJAX_in_Plugins&lt;/a&gt;) and there are no complete code examples and no best practices on how to work with AJAX calls when using Wordpress.&lt;/p&gt;

&lt;h2&gt;
  
  
  Content
&lt;/h2&gt;

&lt;p&gt;In this article I will not only cover "AJAX with Wordpress", but also a few related topics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wordpress AJAX basics&lt;/li&gt;
&lt;li&gt;Responding to AJAX calls from your Wordpress plugin&lt;/li&gt;
&lt;li&gt;Authorization&lt;/li&gt;
&lt;li&gt;Frontend best-practices&lt;/li&gt;
&lt;li&gt;Ship your frontend together with your plugin&lt;/li&gt;
&lt;li&gt;Nonces&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wordpress AJAX basics
&lt;/h2&gt;

&lt;p&gt;Please turn on debugging (&lt;a href="https://wordpress.org/support/article/debugging-in-wordpress/"&gt;https://wordpress.org/support/article/debugging-in-wordpress/&lt;/a&gt;) by using both &lt;code&gt;WP_DEBUG&lt;/code&gt; and &lt;code&gt;WP_DEBUG_LOG&lt;/code&gt;, it will make your life easier :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codex.wordpress.org/AJAX_in_Plugins#Debugging"&gt;This wordpress article&lt;/a&gt; explains the basics of responding to ajax calls.&lt;/p&gt;

&lt;p&gt;Here is a Gist which also describes everything you should know:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;One thing to remark: You always have to check for permissions in your AJAX calls&lt;/p&gt;

&lt;h2&gt;
  
  
  Responding to AJAX calls
&lt;/h2&gt;

&lt;p&gt;Within your functions it is highly recommended to use &lt;code&gt;wp_send_json_success&lt;/code&gt; or &lt;code&gt;wp_send_json_error&lt;/code&gt; functions to send data back to the client (&lt;a href="https://wordpress.stackexchange.com/questions/149158/why-use-wp-send-json-over-echo-json-encode"&gt;here is a informative stackexchange post on that&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;On default settings, the client has to send all data as &lt;code&gt;x-www-form-url&lt;/code&gt;, otherwise you cannot access it with &lt;code&gt;$_POST['something']&lt;/code&gt;. I did not like that and &lt;a href="https://wordpress.stackexchange.com/questions/177554/allowing-admin-ajax-php-to-receive-application-json-instead-of-x-www-form-url"&gt;found a way to send parse the data when using application/json Content-Type&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;json_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file_get_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'php://input'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your &lt;code&gt;$data&lt;/code&gt; variable contains all the request data. You could now use object destructuring to access the data more easily (&lt;a href="https://stackoverflow.com/questions/28232945/destructuring-assignment-in-php-for-objects-associative-arrays"&gt;but it depends on your PHP version&lt;/a&gt;). Skip to the &lt;em&gt;Frontend Best practices&lt;/em&gt; section when you are curious on how to send data from the frontend to the AJAX handler&lt;/p&gt;

&lt;h2&gt;
  
  
  Authorization
&lt;/h2&gt;

&lt;p&gt;As explained in the first section, you have to do the authorization for your AJAX functions/routes yourself. It really depends on the application and use case of your plugin. You can try to use Wordpress built-in &lt;a href="https://developer.wordpress.org/reference/functions/current_user_can"&gt;current_user_can&lt;/a&gt; function, or build your own permissions/role system, which I had to do. In the end, I ended up with following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;json_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file_get_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'php://input'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nv"&gt;$id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;locationId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// I check whether the current user is allowed to access the given location&lt;/span&gt;
&lt;span class="c1"&gt;// If not the function returns wp_send_json_error(null, 401)&lt;/span&gt;
&lt;span class="nf"&gt;checkUserAccessToLocation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Frontend Best Practices
&lt;/h2&gt;

&lt;p&gt;You should have a single component in your frontend project which handles the calls to the backend: It is easier to maintain and reduces the probability of errors. I am using Vue.js and have a simple &lt;code&gt;class&lt;/code&gt; for handling the communication with the backend (I am using &lt;a href="https://github.com/axios/axios"&gt;axios&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;BackendCommunicationService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;buildCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{[&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;action&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;action&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;action&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/wp-admin/admin-ajax.php&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ..... other functions&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the &lt;code&gt;buildCall&lt;/code&gt; function within the &lt;code&gt;class&lt;/code&gt; is easy: &lt;code&gt;this.buildCall({action: 'insert_name', name: 'Foobar'})&lt;/code&gt;. This will call your (hopefully previously) defined &lt;code&gt;wp_ajax_insert_name&lt;/code&gt; ajax action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shipping your plugin
&lt;/h2&gt;

&lt;p&gt;I wanted to ship the plugin with the full application code. So I &lt;code&gt;build&lt;/code&gt; the frontend project and copy the generated &lt;code&gt;dist&lt;/code&gt; folder into an &lt;code&gt;assets&lt;/code&gt; folder of the plugin. Here is my bash script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;frontend &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm run build
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; dist/&lt;span class="k"&gt;*&lt;/span&gt; ../plugin/assets/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to have predictable file names, I have to add &lt;code&gt;filenameHashing: false&lt;/code&gt; to my &lt;code&gt;vue.config.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now I have my frontend code in the assets folder. How do I include the plugin with the whole application into wordpress? The easiest way I found is by using a &lt;a href="https://wordpress.com/support/shortcodes/"&gt;shortcode&lt;/a&gt;. This is my PHP code to ship my application through a shortcode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nf"&gt;add_shortcode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'get_ll_include_tags'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'get_ll_include_tags_func'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;get_ll_include_tags_func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Load JS files&lt;/span&gt;
    &lt;span class="nf"&gt;wp_register_script&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'vue-app.js'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;plugin_dir_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;__FILE__&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'assets/js/app.js'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;wp_enqueue_script&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'vue-app.js'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;wp_register_script&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'vue-vendors.js'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;plugin_dir_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;__FILE__&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'assets/js/chunk-vendors.js'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;wp_enqueue_script&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'vue-vendors.js'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Load CSS files of application&lt;/span&gt;
    &lt;span class="nf"&gt;wp_register_style&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'vue-app.css'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;plugin_dir_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;__FILE__&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'assets/css/app.css'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;wp_enqueue_style&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'vue-app.css'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;wp_register_style&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'vue-vendors.css'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;plugin_dir_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;__FILE__&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'assets/css/chunk-vendors.css'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;wp_enqueue_style&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'vue-vendors.css'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;


    &lt;span class="nb"&gt;ob_start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"app__loading-spinner"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;Application is loading...
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;ob_get_clean&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I can use &lt;code&gt;[get_ll_include_tags]&lt;/code&gt; in any wordpress page and my application will be loaded.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nonces
&lt;/h2&gt;

&lt;p&gt;To be honest, this is a topic I am still indecisive about. Nonces are there for a good reason, but as all AJAX calls are &lt;code&gt;POST&lt;/code&gt; requests and I am checking the authorization for every call, I am not sure whether nonces are needed? But please correct me, if I am wrong! If nonces are needed, I already have a few ideas on how to implement them.&lt;/p&gt;

&lt;h1&gt;
  
  
  The End
&lt;/h1&gt;

&lt;p&gt;I hope this helps some people, I wish I had had such a post when starting with PHP Wordpress plugin development.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: I am new to Wordpress plugin development and PHP, so please comment if you find an error or have a remark on something:)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>php</category>
    </item>
    <item>
      <title>Deploy a Vue app with a Nodejs backend to Heroku</title>
      <dc:creator>Martin</dc:creator>
      <pubDate>Mon, 14 Sep 2020 09:08:40 +0000</pubDate>
      <link>https://dev.to/junkern/deploy-a-vue-app-with-a-nodejs-backend-to-heroku-2mc9</link>
      <guid>https://dev.to/junkern/deploy-a-vue-app-with-a-nodejs-backend-to-heroku-2mc9</guid>
      <description>&lt;p&gt;Many tutorials about deploying a Vue app to Heroku are using a very simple setup with no server (or a really simple one only using express as a server dependency).&lt;/p&gt;

&lt;p&gt;But what about deploying an app with more complex server which has a lot of dependencies? I couldn’t find a good and working tutorial, so I wrote this one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;My Vue App is not only a frontend, but also needs a backend. Of course I could deploy the frontend and backend to different services and maybe utilize CDNs for the frontend, but I wanted to have everything in the same repository and server.&lt;/p&gt;

&lt;p&gt;All the Node.js server code is in the root folder and I have a seperate &lt;code&gt;frontend&lt;/code&gt; folder for my Vue.js app.&lt;/p&gt;

&lt;p&gt;Developing the project locally was no problem. That’s why I thought pushing to Heroku would as well be a piece of cake.&lt;/p&gt;

&lt;p&gt;My server code needs a simple &lt;code&gt;npm install &amp;amp;&amp;amp; npm start&lt;/code&gt; and the Vue.js app has to be build with &lt;code&gt;npm run build&lt;/code&gt;. On the server side I am using &lt;code&gt;fastify&lt;/code&gt; and with the help of &lt;code&gt;fastify-static&lt;/code&gt; I am serving the &lt;code&gt;frontend/dist&lt;/code&gt; folder to the users.&lt;/p&gt;

&lt;p&gt;So, in order to build everything upon deployment, the command for the build step in my root package.json would be: &lt;code&gt;cd frontend &amp;amp;&amp;amp; npm run build&lt;/code&gt;? Wrong!&lt;/p&gt;

&lt;h2&gt;
  
  
  Analysis and Solution
&lt;/h2&gt;

&lt;p&gt;First of all, all the Vue.js dependencies are not installed, so we are missing a &lt;code&gt;npm install&lt;/code&gt; in the frontend folder. But Heroku apparently sets &lt;code&gt;NODE_ENV=prod&lt;/code&gt; and &lt;code&gt;NPM_CONFIG_PRODUCTION=true&lt;/code&gt; so when running an &lt;code&gt;npm install&lt;/code&gt; no devDependencies get installed. I tried different approaches to get Heroku to install and build everything correctly (e.g. &lt;a href="https://stackoverflow.com/questions/22954782/install-devdependencies-on-heroku"&gt;https://stackoverflow.com/questions/22954782/install-devdependencies-on-heroku&lt;/a&gt; , &lt;a href="https://dev.to/jmbejar/how-to-quickly-deploy-a-vuejs-app-to-heroku-5b0f"&gt;https://dev.to/jmbejar/how-to-quickly-deploy-a-vuejs-app-to-heroku-5b0f&lt;/a&gt;) but in the end I resorted to a simple build script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#/bin/bash
npm install —only=dev # installs only dev dependencies
npm install            # installs prod dependencies
npm run build          # builds the Vue.js app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script resides in the &lt;code&gt;frontend&lt;/code&gt; folder. And I call this script from the root &lt;code&gt;package.json&lt;/code&gt; by using&lt;/p&gt;

&lt;p&gt;&lt;code&gt;“heroku-postbuild”: “cd frontend &amp;amp;&amp;amp; ./build.sh”,&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now upon deployment all my server dependencies get installed as well as my Vue.js frontend being build.&lt;/p&gt;

&lt;p&gt;There are surely other ways to accomplish this, but my approach works for me and is easy to understand.&lt;/p&gt;

</description>
      <category>node</category>
      <category>vue</category>
      <category>heroku</category>
    </item>
    <item>
      <title>Adding SSL when using Heroku and Namecheap</title>
      <dc:creator>Martin</dc:creator>
      <pubDate>Thu, 04 Jun 2020 09:57:44 +0000</pubDate>
      <link>https://dev.to/junkern/adding-ssl-when-using-heroku-and-namecheap-5bl1</link>
      <guid>https://dev.to/junkern/adding-ssl-when-using-heroku-and-namecheap-5bl1</guid>
      <description>&lt;p&gt;I have fought a few hours to try to get SSL working when using a Heroku Dyno together with a domain bought on Namecheap. I didn’t want to use any Namecheap paid SSL solution, because Heroku offers SSL for free.&lt;/p&gt;

&lt;p&gt;My goal is simple: Every user should end up on &lt;a href="https://example.com" rel="noopener noreferrer"&gt;https://example.com&lt;/a&gt; regardless whether they visit the website with &lt;em&gt;https/http&lt;/em&gt; or &lt;em&gt;www/non-www&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To make it more clear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://example.com" rel="noopener noreferrer"&gt;http://example.com&lt;/a&gt; =&amp;gt; &lt;a href="https://example.com" rel="noopener noreferrer"&gt;https://example.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://www.example.com" rel="noopener noreferrer"&gt;http://www.example.com&lt;/a&gt; =&amp;gt; &lt;a href="https://example.com" rel="noopener noreferrer"&gt;https://example.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.example.com" rel="noopener noreferrer"&gt;https://www.example.com&lt;/a&gt; =&amp;gt; &lt;a href="https://example.com" rel="noopener noreferrer"&gt;https://example.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://example.com" rel="noopener noreferrer"&gt;https://example.com&lt;/a&gt; =&amp;gt; &lt;a href="https://example.com" rel="noopener noreferrer"&gt;https://example.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;In the beginning I wanted to achieve everything using the Namecheap DNS settings. And even though &lt;a href="https://www.namecheap.com/blog/alias-next-generation-host-record/" rel="noopener noreferrer"&gt;Namecheap introduced ALIAS records&lt;/a&gt; last July and me reading a lot of articles on that topic I could not get it to work. Sometimes the redirects from &lt;em&gt;www&lt;/em&gt; to &lt;em&gt;non-www&lt;/em&gt; did not work, sometimes the &lt;em&gt;https&lt;/em&gt; website did not respond. The issue is, that Namecheap does the DNS resolution, but it does not have the SSL certificates (Heroku has them).&lt;/p&gt;

&lt;p&gt;The (in my eyes not most elegant solution, but it works flawlessly) is to use application-level redirects. That means in your application you issue an redirect to the &lt;em&gt;https&lt;/em&gt; URL when an incoming request was using &lt;em&gt;http&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Heroku (and most other platforms) deal with the whole SSL problem (they do the SSL termination), so your application only receives &lt;em&gt;http&lt;/em&gt; requests. In order for you to know whether a request was originally using &lt;em&gt;http&lt;/em&gt; or &lt;em&gt;https&lt;/em&gt; you have to look into the x-forwarded-proto header (&lt;a href="https://devcenter.heroku.com/articles/http-routing#heroku-headers" rel="noopener noreferrer"&gt;Heroku documenation on that&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Using the header value to redirect to &lt;em&gt;https&lt;/em&gt; when you have encountered an &lt;em&gt;http&lt;/em&gt; request (I am using &lt;a href="https://www.fastify.io/" rel="noopener noreferrer"&gt;fastify&lt;/a&gt; and Node.js here):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fast&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fastify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fastify&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fast&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;fastify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addHook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;onRequest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-forwarded-proto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-forwarded-proto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;fastify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.0.0.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In addition to the implementation at the application level, you have to setup your two Heroku domains: One for the root domain and one for the &lt;em&gt;www&lt;/em&gt; subdomain:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fii9j33ia0xbbj86o6ltr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fii9j33ia0xbbj86o6ltr.png" alt="Heroku Settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now for the last part, the Namecheap DNS settings! These are the only two settings I have for that domain:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F91dt3v1i6hxf8j2azrg1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F91dt3v1i6hxf8j2azrg1.png" alt="Namecheap Settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope this helps some of you out there! Stay safe :)&lt;/p&gt;

</description>
      <category>security</category>
      <category>javascript</category>
      <category>node</category>
      <category>heroku</category>
    </item>
  </channel>
</rss>
