抽离sdk 发布npm包
前面完成elpis的框架设计还有组件的设计,前端工程化。
最后是需要抽离成sdk,发布到npm。
1.elpis-core的loader的解析需要加上业务层的路径。
下面是controller举例:
const controller = {};
// 读取 elpis app/controller/**/**.js 所有文件
const elpisControllerPath = path.resolve(__dirname, `..${sep}..${sep}app${sep}controller`);
const elpisFileList = glob.sync(path.resolve(elpisControllerPath, `.${sep}**${sep}**.js`));
elpisFileList.forEach(file => {
handleFile(file);
});
// 读取 业务 app/controller/**/**.js 所有文件
const businessControllerPath = path.resolve(app.businessPath, `.${sep}controller`);
const businessFileList = glob.sync(path.resolve(businessControllerPath, `.${sep}**${sep}**.js`));
businessFileList.forEach(file => {
handleFile(file);
});
// 加载到app.controller下
function handleFile(file) {
//读取文件名
let name = path.resolve(file);
//获取文件路径
name = name.substring(name.lastIndexOf(`controller${sep}`) + `controller${sep}`.length, name.lastIndexOf(`.`))
name = name.replace(/[_-][a-z]/ig, (s) => s.substring(1).toUpperCase());
// 挂在middleware到内存app对象中
let tempController = controller;
const names = name.split(sep);
for(let i = 0, len = names.length; i < len; ++i) {
if(i === len - 1) {
const ControllerModule = require(path.resolve(file))(app);
tempController[names[i]] = new ControllerModule();
} else {
if(!tempController[names[i]]) [
tempController[names[i]] = {}
]
tempController = tempController[names[i]];
}
}
}
app.controller = controller;
这边主要是将之前的封装成一个handleFile方法,然后根据elpis内部和业务做相应的解析。
2. 将vue babel相关的东西暴露给业务使用
'@babel/runtime': path.dirname(require.resolve('@babel/runtime/package.json')),
'vue': require.resolve('vue'),
这边思考过一些公共的包如vue,pinia,elementui提出去做一个公共依赖,要求使用者必须安装这些。后期如果觉得需要我往这个方向修改。
3. elpis提供多个可扩展配置,比如dashboard路由,schema-view component扩展,schema-form扩展,schema-searchbar扩展,还有登录下拉提供扩展配置。
需要将业务的配置路径在webpack中配置下别名。然后将业务组件都集成在elpis内部的配置文件中。
const businessDashboardRouterConfig = path.resolve(process.cwd(), './app/pages/dashboard/router.js');
aliasMap['$businessDashboardRouterConfig'] = fs.existsSync(businessDashboardRouterConfig) ? businessDashboardRouterConfig : blankMoudulePath;
这里是通过判断是否能找到业务的这个配置文件,找不到创建一个空的文件,blankMoudulePath是一个空文件路径。最后把aliasMap里面的都配置成别名。
4. 加上database扩展
这边使用的是knex 引擎用的mysql2,具体配置都写在config中。
db: {
client: 'mysql2',
connection: {
host: 'xxxx',
port: '3306',
database: 'elpis-beta',
user: 'admin',
password: 'xxx',
},
pool: {
min: 5,
max: 10
}
},
extend中是通过app.config导入这个配置
module.exports = (app) => {
const { db: dbConfig } = app.config;
if(!dbConfig) {
return;
};
return require('knex')(dbConfig);
}
5.将pinia放在业务端统一管理
在boot.js(创建vue实例,统一配置路由的方法)中加一个参数businessPinia
import { createPinia, setActivePinia } from 'pinia';
let elpisPinia = null;
/**
* 获取 Elpis pinia
*/
export function getElpisPinia() {
if (!elpisPinia) {
elpisPinia = createPinia();
}
return elpisPinia;
}
/**
* 允许宿主注入 pinia
*/
export function setElpisPinia(pinia) {
if (pinia) {
elpisPinia = pinia;
setActivePinia(pinia);
}
return elpisPinia;
}
export default getElpisPinia();
这边是判断每个入口实例是否用了pinia 没有elpis创建。
6. 优化一下detail-panel展示逻辑
detail-panel中是遍历字段然后直接读取 这边考虑到有些字段如性别需要根据库里数字转成男女。具体实现是在detailPanelOption下加个字段displayRules,是一个对象里面是数字和男女的映射。
const changeText = (key, value) => {
const { schema } = components.value[name.value];
const item = schema?.properties?.[key];
const rules = item?.option?.displayRules;
if (rules) {
return rules[value] ?? value;
}
return value;
}
key就是字段key, value是接口返回值。
总结
现阶段完成整个elpis框架的开发和包的发布以及写了一个相应的demo。自己的架构思维和编码思维都得到了有效的提高。从前端工程化到nodejs后端,到npm发包,自己完整的实现了所有的流程。后续的话会根据业务修改elpis的相关代码。