Breaking Changes in Hexo 3.0

Tommy Chen edited this page Feb 14, 2015 · 9 revisions

Hexo 3 has been refactored and some APIs were changed. Here's what's changed in Hexo 3. Some changes may not be listed here. You can see the changelog for detailed information. You may also be interested in Migrating from 2.x to 3.0.


Command line interface is separated from the main module. It makes the CLI load faster. And you can use different versions of Hexo in each folders without updating the global hexo-cli frequently.

$ npm install hexo-cli -g

Slimmer Core Module

Some built-in plugins are separated from the core module in Hexo 3. It's more flexible and plugins can be updated without changing the core module.

You have to install the following plugins manually:

Besides, utilities are separated into a standalone module. hexo.util is not reachable anymore.

New Generator API

Generator API in Hexo 3 was changed completely. Here's an example of the usage of new API:

hexo.extend.generator.register('archive', function(locals){
  var posts = locals.posts.sort('-date');

  return {
    path: 'index.html',
    layout: 'index',
    data: posts

You have to return an object or an array in the generator. The object contains:

  • path: Path
  • layout: Layout (Optional, can be a string or an array)
  • data: Data

Hexo will handle routes for you. Do not modify hexo.route directly.

You can use hexo-pagination to help you build a generator with pagination.

Render Pipeline Changed

The pipeline of was changed in Hexo 3. Tag plugins in posts are not processed until all source files are loaded, which means it's possible to get all post data in tag plugins now!

Thanks to this new feature, internal links is implemented in Hexo 3. You can use the following tag plugins in your post now!

{% post_path hello-world %}
// /2015/01/16/hello-world/
{% post_link hello-world %}
// <a href="/2015/01/16/hello-world/">Hello World</a>
{% post_link hello-world Custom Title %}
// <a href="/2015/01/16/hello-world/">Custom Title</a>

{% asset_path example.jpg %}
// /2015/01/16/hello-world/example.jpg
{% asset_link example.jpg %}
// <a href="/2015/01/16/hello-world/example.jpg">example.jpg</a>
{% asset_link example.jpg Example %}
// <a href="/2015/01/16/hello-world/example.jpg">Example</a>
{% asset_img slug %}
// <img src="/2015/01/16/hello-world/example.jpg">

Smart Abbreviations

Hexo 3 uses abbrev to generate abbreviations for console plugins automatically. You don't have to define alias anymore.

# These commands are all equal to `hexo server`
$ hexo s
$ hexo se
$ hexo ser
$ hexo serv
$ hexo serve
$ hexo server

Async Tag Plugins

Since Hexo 3, we use Nunjucks instead of Swig for post rendering. They share simliar syntax but Nunjucks provides async rendering. You can write async tag by set async option to true when registering. For example:

var sizeOf = require('image-size');

// Get size of an image
hexo.extend.tag.register('image_size', function(args){
  var path = args[0];

  // You can use either Promise or callback
  // Here we use Promise for example
  return new Promise(function(resolve, reject){
    sizeOf(path, function(err, dimensions){
      if (err) return reject(err);
      resolve(dimensions.width + 'x' + dimensions.height);
}, {async: true});

Timezone Support

You can customize the timezone in _config.yml. Here's a list of available timezones.

timezone: Asia/Taipei

Get/Set Single Setting

You can get or set a single setting with hexo config command. For example:

$ hexo config server.port
# 4000
$ hexo config server.port 5000

Plugin Loading Mechanism

In Hexo 3, only plugins listed in package.json will be loaded, and plugins/scripts will be executed in sandbox so hexo namespace will be no longer exposed to global.

API Changes


  • hexo.init: loads config and plugins.
  • hexo.load/ loads source files.
  • hexo.unwatch: stops watching file changes.
  • before_exit filter: runs before exiting.
  • template_locals filter: modifies local variables in templates.


  • filter.apply was removed. Use filter.exec/filter.execSync instead.
  • Warehouse was updated to 1.0.


  • was removed. Use hexo.load or instead.
  • hexo.theme.generate was removed.
  • hexo.constant was removed.
  • hexo.bootstrap was removed.
  • get_posts helper was removed.



All APIs are promisifed in Hexo 3. We use bluebird instead of async for flow control for several reasons:

  • Better performance (Benchmark)
  • Elegant API
  • Better error handling

High Coverage

Coverage test is introduced in Hexo 3 which helps me to inspect which line of codes are not tested yet, and makes Hexo more reilable. Also, tests are not only run on Travis but also AppVeyor in order to increase the compatibility on Windows.

You can see the test reports here: