Auto-Deploy Tool Makes Hexo Easier to Use
Since our blogs deployed, now we can post our articles. Hexo is a static blog system, so we need to run a command to generate and deploy the new article. I think it’s not that convenient and wonder is there any possible ways to make it easier. Searching online, I found some existing tools that can be used. But I love doing things on my own, plus the principal of this feature is not complicated, so I decided to build my own tool. This article well introduces my auto-deploy tool. You are free to use or edit it for your blogs.
Node.js
At first, I need to select a coding language. The blog is on Ubuntu, a Linux environment, which means Shell and Python are the most convenient coding language to use. Besides, the Node.js required by Hexo is on the waiting list too. I used Shell a lot but seldom write Shell scripts; I love Python, but currently, I use Node.js every day due to internship. So I’d choose Node.js to do this job. If time promise, I will add Python and Shell version of this tool. No intend to update this; A more powerful tool comes out: Hexo-Auto-Deployer
Principal
Now, let’s look at what we should do if we post new articles manually.
- Upload
.md
file to_post
directory (whathexo new
command does is generate.md
file by given template) - Use
hexo d -g
to generate and deploy
For the first step, I currently simply use sftp to upload. And I’m considering building a tool to download new articles from OneDrive.
The second step is the main point of this article. And it contains two parts:
- Watch the changes of
_post
directory:- add
- delete
- edit
- Run run command
Directory watching
How does a program know the changes within a directory? The first idea is to use setInterval
function to obtain all files of the directory consistently. And then, by comparing the newly acquired last-modified-time(mTime
) and last obtained time, we can know whether files were edited. But this method has a drawback: the interval time is tricky to set. Too short to waste resources while too long to have a slow response. No one wants to wait a long time before they can see what they’ve just written. If so, why not just publish it manually?
Looking through the official document of fs
module, I find the function watch
which exactly meets my desire. It can know the changes of given files on time by an event handler. Codes below are the basic version.:
1 | const fs = require('fs'); // file system module |
Straight forward. Function watch
takes a param and a call-back function. The param is the directory to watch, where we use path.resolve
to build the path. By the way, __dirname
is the current working directory. The call-back function takes two params, event
is the type of event which I will not use in this tool, and the filename
is the name of the file that triggered the change event.
Key point
If you run the codes above and try to add or edit files, you may find the output of every action is more than once. This is because some actions, like writing, some editors may clean old content and write the new one. And some actions may have some middle states that continue tens of or hundreds of milliseconds.
You may at first think that’s not a big problem. But obviously, this wastes lots of resources. You don’t want the tool to deploy your blog twice more whenever you post a new article. So let’s make some changes.
1 | const fs = require('fs'); // file system module |
You see, I introduced a signal variable wait
that initially set to false
. The first time a change occurs, a delayed function will be placed: set that signal variable to false again. Meanwhile set the wait
signal variable to the return value of setTimeout
function. Because the return value is greater than zero, wait
variable will be treated as true
in if condition.
Deploy
Running Shell commands need child_process
module, which can be used after import. For example, ‘ll` command:
1 | const { exec } = require('child_process'); |
The stdout
is the output when success and stderr
is that when an error occurs. I won’t use them in this tool.
Combining codes of running commands and codes of watching changes, we can see the whole block of codes.
1 | const fs = require('fs'); |
Function exec
can take a second param, options. The deploy command needs to run under the root directory of your blog. So I add a cwd
option to change the working directory. The reason why I do not simply place the program under the root directory of my blog is that I’m running a multi-language blog. And there are two directories to watch. If you are running a multi-language blog too, you may want to have some reference here.
1 | const fs = require('fs'); |