Tuan Anh

container nerd. k8s || GTFO

Embedding Liquid code snippet with jekyll

If you want to share some Liquid code snippet or say some Django code, jekyll would try to process it as it looks like valid Liquid template and throw some weird errors.

The solution is to use raw tag. Again, I cannot use raw tag nested inside raw tag. Though, you would probably never have to do it, unless writing a blog post about something like this.

{% include analytics.html %}

Monthly/yearly post archive generator plugin for jekyll

Basically, this plugin will generate a archive based on your specified layout so that you can access it at url like

example.org/2014/
example.org/2014/08/

At first, I thought this is one of the default feature of jekyll but I was mistaken toto for jekyll. toto was another static site generator that I used before.

Anyway, this is what you are gonna get at the end.

jekyll archive plugin
1 - Example result of using jekyll archive plugin

I’m not the author of this plugin. I just modified it to suit my needs, adding stuff like: grouping post, generate yearly archive.

If you want to take a peak, head over to the plugin’s repo on GitHub.


Blogging with jekyll

I started using jekyll with Github Pages few years back but Github Pages didn’t allow plugins at the time and I do want to hack a bit around jekyll for my needs so I gradually move to self-hosting. As for static blog doesn’t require much resource, I opted for the lowest package on RamNode which goes for $15 a year (a bit over a buck a month for a 128MB RAM VPS). This is actually plenty for my needs.

Install jekyll

Install rvm or rbenv. If you already have one, skip this, then install jekyll

curl -L https://get.rvm.io | bash -s stable --ruby=2.0.0
gem install jekyll

Create your new blog and git init it.

jekyll new example.org
cd example.org
git init
git add .
git commit -m "Initial commit"
jekyll serve --watch

Deploy

I create a script on my repo post-receive. Upon receive my push commit, the script will rebuild the site from source, output it to nginx public folder /usr/share/nginx/html/example.org and purge varnish cache afterword. Purging varnish cache is optional but I do change my CSS/JS occationally now and then so I put it there as well.

You can do this by following this tutorial on DigitalOcean - “How To Deploy Jekyll Blogs with Git”. It’s pretty easy to follow. Use your copy-paste-fu.

Note: If you’re using Ubuntu 14.04 or later, you will have to do to apt-get install nodejs as well. jekyll itself doesn’t depend on nodejs but execjs does.

Others

I wrote a bunch of posts about jekyll as well. Check these out if they interest you.

Happy blogging. Don’t forget to share your cool jekyll hack on your new hippy blog.


BetterTube - A jekyll plugin for embedding YouTube videos

Sample syntax

{% youtube http://youtu.be/NiYCgVKioI4 %}

or even shorter

{% youtube NiYCgVKioI4 %}

Basically, this plugin will replace your youtube tag with a beautiful, responsive thumbnail of the video instead of loading the iframe and a bunch of other stuff along with that iframe, right on page load (pagespeed, remember?). On click, it will replace the image with the iframe for embedding video and play (autoplay=1). And did i mention it’s responsive too?

I will publish this plugin on Github as soon as I clean up the code.

The plugin is now available on Github.


Optimizing the hell out of your site for PageSpeed

Static assets bundling

I wrote a post about static assets combine on jekyll but the idea is similar to other framework. You can even do this on Wordpress via plugin called W3TC IIRC. As for your theme’s images, use CSS sprites to combine it to a single image. There are many tools for this purpose.

This step is critial because number of requests has a very high impact on page load. You would get a few points for PageSpeed already after this step.

Make use of Content Delivery Network (CDN)

CDN deploys your content across multiple, geographically dispersed servers, making your page loads faster from vistors’ perspective.

Also, try to load external library from a popular CDN. Chance your visitors already cache jQuery on Google CDN is pretty high. Why not take advantage of this?

CDN is cheap now. Even the free option CloudFlare is pretty good. Use it.

Minify CSS/JS/HTML

This one doesn’t take much time either. CloudFlare can also do it for you if you’re lazy.

Defer, async when possible

Defer and async all the scripts where possible. The rules are simple

  • Without defer or async, HTML parsing is paused when js code executes.

  • Defer will delay the script execution until HTML parsing is done.

  • Async won’t care when the script will be available. The script will be executed as soon as it’s ready. You may not want to use async if you have other scripts depend on that.

If you need to put external scripts (analytics, ads, etc..) on your site, try to find their async version. Most of the popular ads network provide async code snippet for your site.

Put JavaScript which are deferable in the bottom before </body in case your visitors’ browsers are not HTML5-compatible.

Optimize images

Yahoo Smush.it is a popular tool for this purpose. There’s a WordPress plugin to make it even easier to use. If you prefer an app for offline use, ImageOptim is good.

Use static site generator

jekyll is good. I have a very good experience with it. If you want a ready-to-use jekyll, take a look at Octopress. There are tons of other options as well. Take a pick.

Reverse proxy

If you’re already using a static site generator and nginx to serve it, I’m not sure if a reverse proxy would help. In my benchmark, varnish has roughly the same performance as nginx when serving static html. However, say you’re using a dynamic language like PHP with WordPress, varnish helps a lot. An old website of mine used to be able to handle 200,000 hit a day on a single $5 droplet on DigitalOcean where peak user online count was around 800, according to Google Analytics. Without varnish, the site was pretty much unresponsive.

I uses varnish to drop cookies on static assets as well as reverse proxy in front of nginx.

Google’s mod pagespeed

Pretty easy to install with apache, a bit more troublesome with nginx. I highly recommend you to install this. It makes your job a whole lot easier.

Conclusion

I did few of those tweaks and get 93/100 on Pagespeed and 99/100 on gtmetrix. Not bad for half an hour of your time huh. If i have more time, I will aim for something closer to 100 on Pagespeed.

There’s one suggestion on PageSpeed I don’t really understand . Until I figure it out, my score is probably stucked here.

None of the above-the-fold content on your page could be rendered without waiting for the following resources to load.


Static assets combine with jekyll

If you have several css files, each for different purpose, combining it into one would minimize HTTP requests and improve load times significantly. jekyll mades it very easy with include tag.

Here’s how you do it.

  • Move all the css files you want to include to _includes folder.

  • You create a new layout in _layouts folder called style.html and includes the needed css there.

---
layout: nil
---
 
/* syntax css, base css, or whatever you need to include */
{% include css/style.css %}
{% include css/syntax.css %}

This file is basically your base css file, including all the frequently used files.

  • Next, create your css file like below, include it in your head tag and you’re done. All your css files are now included in the layout style which you used as a base css for your main css.
---
layout: style
---

/* Your custom css goes here */

Alternatively, if your css file is rather small, you can embeded them right into the HTML file/layout like this. I’m not a fan of this as it would look a bit mess up, even just in the source code.

<head>
<title>Your page title</title>
  <style>
    /* include it here. It will be replaced as your css file content */
  </style>
</head>

Last step: check your PageSpeed score again and smile.


Things you may not know about JavaScript array

Let’s begin with creating an array.

arr = [1,2,3];
typeof a;
> "object"

you get object. Wow, so how would I check whether it is an array? Here’s how people usually do it.

if ('[object Array]' === Object.prototype.toString.call(arr)) {
  // your code
}

Next, what if I’m trying to access index that is greater than current length?

arr[10] = 10;

Seems ok!? No index out of range error whatsoever !? Let’s take a look at it again.

> [1, 2, 3, undefined × 7, 100]

Looks like JavaScript automatically expands the array and filled the blank with undefined.

What about if I’m trying to shrink the array

arr.length = 1;
> [1]

JavaScript reduces the size and keeps only elements from 0 to new length.

What if I try something like this

arr['hello'] = 100;
> [1]

Hmm, where is hello? Let’s try to access it again

arr['hello'];
> 100

Phew, it’s still there.

Ok, let’s stop making fun about JavaScript here for now. No matter how you see it, JS is a pretty good language. I kinda the language in general but some stuff, it’s just weird!! Though I have to admit, it’s fun to debug.


Returning query result as json array with Oracle 10G

I love Postgres SQL and one of my favorite feature is ability to return the query result as a JSON array string.

select array_to_json(array_agg(row_to_json(t)))
from (
  select * from my_table
) t

I wonder if I could do the same with Oracle.

Too bad the Oracle version at work is a bit rusty so it’s a bit more troublesome to get it work. We have to first, generate XML using DBMS_XMLGEN and then transform it to JSON using a XLTS stylesheet.

function ref_cursor_to_json (p_ref_cursor in sys_refcursor,
p_max_rows in number := null,
p_skip_rows in number := null) return clob
as
l_ctx         dbms_xmlgen.ctxhandle;
l_num_rows    pls_integer;
l_xml         xmltype;
l_json        xmltype;
l_returnvalue clob;
begin

-- generate JSON from REF Cursor

l_ctx := dbms_xmlgen.newcontext (p_ref_cursor);

dbms_xmlgen.setnullhandling (l_ctx, dbms_xmlgen.empty_tag);

-- for pagination
if p_max_rows is not null then
dbms_xmlgen.setmaxrows (l_ctx, p_max_rows);
end if;

if p_skip_rows is not null then
dbms_xmlgen.setskiprows (l_ctx, p_skip_rows);
end if;

-- get the XML content
l_xml := dbms_xmlgen.getxmltype (l_ctx, dbms_xmlgen.none);

l_num_rows := dbms_xmlgen.getnumrowsprocessed (l_ctx);

dbms_xmlgen.closecontext (l_ctx);

close p_ref_cursor;

if l_num_rows > 0 then
-- perform the XSL transformation
l_json := l_xml.transform (xmltype(get_xml_to_json_stylesheet));
l_returnvalue := l_json.getclobval();
else
l_returnvalue := g_json_null_object;
end if;

l_returnvalue := dbms_xmlgen.convert (l_returnvalue, dbms_xmlgen.entity_decode);

return l_returnvalue;

end ref_cursor_to_json;

If you want to read more about this, head over to this blog post on ORA-00001 blogspot.

This utility is available as part of plsql-utils on Google Code along with many other cool PL/SQL utilities. You should check it out if you have time.

link bài gốc

How to connect to remote Postgres DB through ssh tunnel

Open a SSH tunnel on your local machine. Here I’m openning a tunnel on my local port 5555, mapping it to the remote 5432 default port of Postgres.

If you have already changed the default port of Postgres, change it accordingly here as well

ssh -fNg -L 5555:localhost:5432 username@host

I’m going to use pgAdmin 3 app to connect to Postgres db. Just follow the new connection instruction as you’re connecting a local database.

If you’re using IDENT authentication, your local username has to be matched with the username you’re trying to log on to. Either switch to PASSWORD authentication or create a new username on remote db that match your local username as below and you’re good to go.

CREATE USER myuser;
ALTER USER myuser WITH PASSWORD 'password';
ALTER USER myuser WITH CREATEUSER CREATEDB;

Speed up jekyll site generation with rsync

Jekyll doesn’t support incremental generation so if your site contains loads of static assets like image, audios,.. jekyll is gonna stroke everytime you re-generate your site by deleting and re-generate/re-coppying everything. This little trick below will help you speeding up jekyll generation process by skipping all the static assets that you specified, until jekyll comes up with a better solution.

  • Rename your static asset folder with underscore in front. jekyll is going to ignore this when generating site. Assume this folder is named images. You will rename it to be _images.

  • In your _config.yml, add the line below. This line basically means that when re-generating, the folder called images in generated folder is not getting touched.

keep_files: ["images"]
  • Keeping in the source and generated folder in sync with a little plugin and rsync. Created a file name rsync_image_generator.rb in _plugins folder with the content below.
module Jekyll    
  class RsyncImageGenerator < Generator
    def generate(site)
      system('mkdir -p _site');
      system('rsync --archive --delete _img/ _site/img/');
    end
  end
end  

From now on, jekyll will ignore the _images folder in your source and images in _sites folder when generating your site. We keep it in sync by using rsync, which is much better/faster than delete/copy process jekyll is using.

Github Pages does support jekyll gems now but it’s kinda limited.