npm包发布

9 阅读3分钟

抽离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的相关代码。