外观
git仓库地址:https://github.com/TaleLin/lin-cms-koa
查看package.json,可知入口文件为项目根目录下的index.js文件:
require('@babel/register');
require('./app/starter');言简意赅,两行代码。第一行引用了@babel/register这个node包,查阅其官网(https://babeljs.io/docs/en/babel-register)可知这个库会修改node提供的require方法,当node程序去require对应后缀名(.es6、.es、.jsx、.mjs和.js)的文件(默认情况下不会去编译node\_modules目录里文件)时,这个库会先把库给编译掉再提供给node使用(见下图,往exports对象上绑定了register函数,在register函数里通过hookExtensions函数对指定拓展名的文件添加自定义的compileHook,其中添加hook的addHook方法是从pirates包中导入的)。
compileHook的内容很简单,就是判断当前没有在编译的话就把代码编译一下:
let compiling = false;
function compileHook(code, filename) {
if (compiling) return code;
try {
compiling = true;
return compile(code, filename);
} finally {
compiling = false;
}
}现在我们看下核心的compile函数:
function compile(code, filename) {
// merge in base options and resolve all the plugins and presets relative to this file
const opts = new OptionManager().init(
// sourceRoot can be overwritten
{
sourceRoot: path.dirname(filename) + path.sep,
...deepClone(transformOpts),
filename,
},
);
// Bail out ASAP if the file has been ignored.
if (opts === null) return code;
let cacheKey = `${JSON.stringify(opts)}:${babel.version}`;
const env = babel.getEnv(false);
if (env) cacheKey += `:${env}`;
let cached = cache && cache[cacheKey];
if (!cached || cached.mtime !== mtime(filename)) {
cached = babel.transform(code, {
...opts,
sourceMaps: opts.sourceMaps === undefined ? "both" : opts.sourceMaps,
ast: false,
});
if (cache) {
cache[cacheKey] = cached;
cached.mtime = mtime(filename);
}
}
if (cached.map) {
if (Object.keys(maps).length === 0) {
installSourceMapSupport();
}
maps[filename] = cached.map;
}
return cached.code;
}这里的主要逻辑是判断是否有缓存了的编译结果,如果有的话就直接使用之前缓存的编译结果没必要重新编译了,如果没有对应的缓存则通过babel.transform方法对源码进行编译处理。所以,项目中其他源码文件里我们就可以使用import/export关键字替代require来进行模块的导入导出了。
作用:加载一堆配置文件,然后启动web应用(添加数据解析、跨域支持、静态服务、日志打印等)。代码如下:
'use strict';
const fs = require('fs');
const path = require('path');
const { config } = require('lin-mizar/lin/config');
/\*\*
- 获取配置
\*/
function applyConfig () {
const cwd = process.cwd();
const files = fs.readdirSync(path.resolve(`${cwd}/app/config`));
for (const file of files) {
config.getConfigFromFile(`app/config/${file}`);
}
// 加载其它配置文件
config.getConfigFromFile('app/extensions/file/config.js');
}
const run = async () => {
applyConfig();
const { createApp } = require('./app');
const app = await createApp();
const port = config.getItem('port');
app.listen(port, () => {
console.log(`listening at http://localhost:${port}`);
});
};
// 启动应用
run();