How to improve the performance of your Axios API requests

There are two simple changes you need to make in order to drastically improve Axios performance:

  • Don’t create the HTTP agent for every request
  • Enable HTTP Keep-Alive

The Axios docs show that when using a request config you should specify agents like this:

//...
  httpAgent: new http.Agent({ keepAlive: true }),
  httpsAgent: new https.Agent({ keepAlive: true }),
//...

But of course, this means you’re creating two new agents for every request.

Instead you should make an Axios Helpers file which imports Axios, sets the defaults, and then exports Axios:

//axios_helpers.ts

import axios from 'axios'

import https from 'https'

const agent = new https.Agent({
    keepAlive: true
})

axios.defaults.httpsAgent = agent

export default axios

and where ever you use axios, you should import it from this file so that the default agent is set, and HTTP Keep-Alive is enabled.

// page.tsx

//before

import axios from 'axios'

//after

import axios from '../utils/axios_helpers'

How to finish your MVP in a weekend.

You’ve got an idea, you’ve done your research and now you must validate your idea by building an MVP.

Here are some ideas and tips to ensure you get that MVP wrapped-up in a weekend:

  • Don’t be concerned about using the latest library or framework, use PHP and JQuery if it means you get the job done quicker.
  • Don’t even think about future scalability, no AWS auto-scaling. Opt for the free plan from Cloudflare for your CDN.
  • Don’t waste time setting up a pipeline to minify your JS and CSS, just check the boxes in the Cloudflare dashboard and they’ll minify everything for you.
  • Don’t spend time setting up HTTPS, or ensuring you redirect from HTTP to HTTPS. Again it’s just a Cloudflare checkbox.
  • Don’t charge anything for your MVP, give it away for free. Don’t setup Stripe or any other payment system.
  • Don’t spend time on design or a logo, use a free landing page template and consider using an emoji for your logo.
  • When registering your domain name, use a provider like Gandi which provides whois privacy for free.
  • Don’t register or setup any social media profiles.
  • Do setup Google Analytics (or similar), its quick and will help you validate your idea.

Finally, launch as quickly as possible and start spreading the word on HN and PH, if you have created something people want and are willing to pay for, then give yourself permission to improve your MVP and do some of the things above. If not, discard it, or pivot. Good luck!

Here’s a successful MVP that I’ve built in a weekend using the methods above:

How to set PHP memory limit and max execution time in your Dockerfile

If you want to set the PHP memory limit and/or max execution time to something other than the default, you can do this in your container during build. Use following in your Dockerfile:

RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini && \
sed -i -e "s/^ *memory_limit.*/memory_limit = 4G/g" 
-e "s/^ *max_execution_time.*/max_execution_time = 0/g" 
/usr/local/etc/php/php.ini

The RUN commands above will copy the default production ini file, and then will modify the memory_limit and set it to 4 gigabytes in the ini file. It also sets the max_execution_time to zero, meaning there is no max.

Modify Search API sort order in Drupal using a hook

If you need to change the sort order of the Drupal 7 Search API using code, here is an example using hook_search_api_query_alter:

function MYMODULE_search_api_query_alter(SearchApiQueryInterface $query) {
    $query->sort('my_field_name', 'DESC');
}

Published
Categorized as Drupal

How to use a relative path to your JS and CSS in Drupal 7

By default, Drupal uses an absolute path, and will insert your domain name into the path to your JS and CSS files.

You can override this, in template.php, like so:

function YOURTHEME_process_html(&$vars) {

  //convert absolute URLs (https://www...) into relative (/some/path) for JS and CSS only
  foreach (array('scripts','styles') as $replace) {
      if (!isset($vars[$replace])) {
          continue;
      }

      $vars[$replace] = str_replace("https://stage.example.com", '', $vars[$replace]);
      $vars[$replace] = str_replace("https://www.example.com", '', $vars[$replace]);
  }

}
Published
Categorized as Drupal

Drupal: How to use the Context Module to include javascript on specific pages

I needed a solution which allowed me to include Optimizely’s A/B testing snippet on certain pages, and have the ability to change those page rules without modifying code.

I do this using the Context module, I apply a class to the body for a node with the path “demo”, like so:

Then, in html.tpl.php, in the <head> of my document, I have the following code:

<?php 
  if (!empty($classes)) {
    if (strpos($classes, 'has-optimizely') !== false) {
      print '<script src="https://cdn.optimizely.com/js/xxxx.js"></script>';
    }
  }
?>
Published
Categorized as Drupal

Images in Drupal RSS Feed, without additional modules

There is an easier way to include the image associated with your node in a Drupal Views RSS feed. No additional modules are required.

Firstly you need to add the Media RSS namespace to your views-view-rss.tpl.php:

<rss version="2.0" xml:base="<?php print $link; ?>"<?php print $namespaces; ?> xmlns:media="http://search.yahoo.com/mrss/">

Secondly, in the row style template for your RSS feed (mine is called views-view-row-rss–market-news-rss-feed–feed.tpl.php), you need add a media element, and enter your image field name, your image style, and your dimensions:

<?php

/**
 * @file
 * Default view template to display a item in an RSS feed.
 *
 * @ingroup views_templates
 */
?>
  <item>
    <title><?php print $title; ?></title>
    <link><?php print $link; ?></link>
    <description><?php print $description; ?></description>
    <media:content url="<?php print image_style_url('news_old_style__300x250_', $node->field_image['und'][0]['uri']); ?>" type="image/jpeg" medium="image" height="250" width="300" lang="en" />
    <?php print $item_elements; ?>
  </item>

Lastly, make the field data available to the template above by adding the following to your template.php

function nadex_preprocess_views_view_row_rss(&$vars) {
  $view     = &$vars['view'];
  $options  = &$vars['options'];
  $item     = &$vars['row'];
 
  // Use the [id] of the returned results to determine the nid in [results]
  $result = &$vars['view']->result;
  $id   = &$vars['id'];
  $node   = node_load( $result[$id-1]->nid );
  $vars['node'] = $node;
}

Thanks to these guys for the inspiration:

Published
Categorized as Drupal, RSS

Drupal: How to access fields in html.tpl.php

When developing my AMP subtheme for Drupal 7, I wanted to only include the amp-youtube extension if the current page actually contained a YouTube video. The amp-youtube extension javascript can only be included in the HEAD of the HTML document, so in Drupal, your html.tpl.php must know about content which is usually only available at node.tpl.php level. Here is the solution:

In your template.php

function MYTHEME_preprocess_html(&$vars) {
//we need to know if the page contains a YouTube video, so we create the variable below and reference it in html.tpl.php
if ($node = menu_get_object()) {
$vars['youtube_video_id'] = $node->field_youtube_video_id;
}
}

in your html.tpl.php

<?php
//include amp-youtube extention if page contains a YT video
if ($youtube_video_id):
?>
    <script async custom-element="amp-youtube" src="https://cdn.ampproject.org/v0/amp-youtube-0.1.js"></script>
<?php endif;?>

 

Published
Categorized as AMP, Drupal

Curata and Drupal Integration

So you want to integrate Curata with your Drupal site? Here’s how:

  1. Install BlogAPI, and Services modules
  2. Enable the above modules, and also “MetaWeblog Provider” and “Old Blogger Provider” for Blog API, and the Services, “Services XMLRPC Server”.
  3. Under Home » Administration » Structure » Services create a new endpoint of type XMLRPC, both name and endpoint URL should be “curata”.
  4. Under the resources tab of your newly created service, check all boxes under “blogger” and “metaWeblog” sections.
  5. At this point you might want to create a new content type for articles published from Curata, it should only contain title, body, image* fields. Having fields other than these, which are required fields, is a problem because will be left blank and therefore prevent Curata from being able to publish. I created a content type called “Curata Article” and referenced it in the step below.
  6. Next you need to create a Role within Drupal, the only permissions it requires are “Manage content with BlogAPI”, “Administer content”, “Curata Article: Create new content”, “Curata Article: Edit any content”, “Curata Article: Delete any content”. Now create a user with this role assigned.
  7. In Home » Administration » Configuration » Web services  » BlogAPI, set the default provider to “Blogger” and select the content type you will allow Curata to publish to, probably the “Curata Article” content type you created in step 5.
  8. Now you’re ready to hook up Curata. Login and go to CCS. Under the share menu, click on CMS then “Add CMS channel”.
  9. Enter your Drupal website URL, the “discover” feature will fail because, unlike WordPress, XMLRPC is not advertised to the world.
  10. Enter your endpoint URL, should be https://www.example.com/curata and provide the credentials for the user account you created in step 6.
  11. Click the authenticate button and Curata will connect and get a list of Content Types it can publish to, as defined in step 7.
  12. The rest of the Curata settings are down to your personal preference. Save all changes and then share some of your approved content from within CCS, ensure it appears in Drupal and you’re all set.

* I have not been able to get Curata to publish images directing into Drupal. To get around this you can edit your “Post Body” field in the Article Display settings within Curata. Here is my post body template:

{% if ARTICLE_PICTURE_URL_FULL %}
<div itemprop="image" itemscope itemtype="https://schema.org/ImageObject">
<figure>
<img src="{{ ARTICLE_PICTURE_URL_FULL }}" alt="{{ ARTICLE_TITLE }}">
<figcaption>{{ ARTICLE_TITLE }} <cite>{{ PUBLISHER_NAME }}</cite></figcaption>
</figure>      
</div> 
{% endif %}

<div class="curata-article-body">
{{ ARTICLE_FULL_HTML }}
<a target="_blank" href="{{ ARTICLE_URL }}">Read the source article at {{ PUBLISHER_NAME}}</a>
</div>