背景
用一个东西之前如果不了解它的原理那就是想相当于一个搬运工,我们拒绝做搬运工
那么他的原理、代码执行的流程、生命周期是什么呢?
咱们带着问题一探究竟
本博客是基于hexo框架,主题butterfly构建完成的
hexo执行过程
hexo 是基于nodejs
通过执行node hexo s
就会生成可访问的静态文件,那么他的原理是什么呢?
首先你得了解nodeJs的npm
hexo是一个npm模块,执行
node hexo s
就是执行该模块模块初始化代码
1
2
3
4
5
6
;
// hexo模块依赖了hexo-cli
require('hexo-cli')();hexo模块依赖了
hexo-cli
,hexo-cli初始化代码如下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54module.exports = entry;
function entry(cwd = process.cwd(), args) {
// process.argv = hexo 后面的参数
args = camelCaseKeys(args || minimist(process.argv.slice(2), {string: ['_']}));
// hexo临时的上下文
let hexo = new Context(cwd, args);
// findPkg: 首先在node_modules寻找package.json,找不到则从上层目录寻找,直到找到package.json
return findPkg(cwd, args).then(path => {
if (!path) return;
// 此时的path就是当前hexo博客所处的位置
hexo.base_dir = path;
/**
* loadModule:加载node_modules/hexo/lib/hexo/index.js,加载的伪代码如下
* const resolve = require('resolve')
* const modulePath = resolve.sync('hexo', { basedir: path });
* const Hexo = require(modulePath);
* return new Hexo(path, args);
*/
return loadModule(path, args);
}).then(mod => {
// 真正的hexo
if (mod) hexo = mod;
// hexo是基于控制台交互的,所以优先加载console组件,注册几个默认的组件逻辑,比如help。。。避免连报错都无法提示
require('./console')(hexo);
/**
* 加载node_modules/hexo/lib/hexo/index.js之后,执行init初始化方法
* init 会往hexo.extend 注册很多组件以及组件的方法
* 比如console组件是用来 和控制台交互的,那么会注册方法:help\server\generate\clean等
*/
return hexo.init();
}).then(() => {
let cmd = 'help';
// 从组件console控制台获取 hexo的命令,如server 或 generate等
if (!args.h && !args.help) {
const c = args._.shift();
if (c && hexo.extend.console.get(c)) {
cmd = c;
}
}
// 监听退出方法,做一些清理的工作,比如说,如果是http服务则停止
watchSignal(hexo);
// 执行从console获取到的方法,如执行server或者clean或者help或者generate等
return hexo.call(cmd, args).then(() => hexo.exit());
});
}hexo的设计思路和nodeJs的核心思想高度相似,都是注册很多事件,然后触发一个事件,每个事件都有自己的回调,这样使hexo扩展性极高
核心逻辑就是
hexo.init
以及hexo.call
hexo.init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31init() {
// 注册内部的插件
require('../plugins/console')(this); // 和控制台交互的组件
// 以下的组件基本都是围绕着console组件中的命令展开的,比如generate命令:生成文章
// 那么filter组件,在生成文章的前后对文章内容做一些处理,比如说替换
require('../plugins/filter')(this);
// 那么generator组件,就是用来生成页面
require('../plugins/generator')(this);
// helper
require('../plugins/helper')(this);
require('../plugins/injector')(this);
require('../plugins/processor')(this);
require('../plugins/renderer')(this);
require('../plugins/tag')(this);
// Load config
return Promise.each([
'update_package', // 升级hexo,package.json的hexo版本为^6.0.0,也就是说有更新时会自动更新package.json里面的version值
'load_config', // 加载配置文件: _config.yml
'load_theme_config', // 加载主题配置文件,如主题是butterfly,则加载hexoc.config.theme_config = _config.butterfly.yml
// 加载扩展插件,优先resolve项目的package.json中的dependencies以hexo开头的依赖
// 其次加载并执行用户scripts目录和hexo-theme/scriptes里面的脚本
'load_plugins'
], name => require(`./${name}`)(this)
).then(() => this.execFilter('after_init', null, {context: this})
).then(() => {
// Ready to go!
this.emit('ready');
});
}hexo.call
上一步init
注册完组件以及加载完扩展脚本后,就要执行真正用户的指令了,比如说generate,或者gen,或者g缩写命令是node模块abbrev提供的转换,实际注册的名称为generate,经过abbrev转换之后,注册了递减的别名:generate\generat\genera\gener\gene\gen\ge\g
生成静态文件过程
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 老曹的私房站!
评论