脚手架安装自定义模板和组件模板功能实现

新建一个组件库模板

发布一个npm包

js 复制代码
git clone https://github.com/imooc-lego/lego-components.git

cd lego-components/

//用cnpm会报错
npm i

// 启动项目
npm run serve

lego-components放至mj-cli-dev-template/mj-cli-dev-lego-components/template目录下;

修改tempalte文件夹里的package.json为ejs模板;

template/package.json 复制代码
{
  "name": "<%= className %>",
  "version": "<%= version %>"
}

template文件夹同级的package.json修改:

js 复制代码
{
  "name": "mj-cli-dev-lego-compoments",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

接着npm publish这个mj-cli-dev-lego-compoments包;

mongodb插入一条数据

我这里是用命令插入数据的;增加一个tag的标志,分为project和component;还可以增加一个ignore字段,是用来ejs模板转换时忽略某些文件;

js 复制代码
db.project.insert({name: '乐高组件库模版', 
    npmName: 'mj-cli-dev-lego-compoments',
    version: '1.0.0',
    type: 'normal',
    tag: ['component'],
    installCommand: 'npm install --registry=https://registry.npm.taobao.org',
    startCommand: 'npm run serve',
    ignore: '**/public/**'
})

项目和组件模版数据隔离

根据项目和组件的选择对数据做筛选;

js 复制代码
// getProjectInfo方法
this.template = this.template.filter((template) =>
    template.tag.includes(type)
);

从接口获取ignore进行拼装;

js 复制代码
//installNormalTemplate方法
const opts = {
    ignore: ["**/node_modules/**"],
};
if (this.templateInfo.ignore) {
    opts.ignore = opts.ignore.concat(this.templateInfo.ignore);
}

获取组件信息功能

组件和项目的逻辑基本一致;组件比项目多一个输入描述信息的命令;

先来修改一下mj-cli-dev-lego-components/template/package.json文件中;

js 复制代码
"description": "<%= description %>"

// 删除files,它会限制上传的文件数量

然后发布mj-cli-dev-lego-components@1.0.1版本;

安装模板时会报错,如下图:

这里我们可以在ignore中去忽略png格式的文件,修改一下mongodb中的数据;

js 复制代码
db.project.update({'name':'乐高组件库模版'},{$set:{'ignore': ['**/public/**', '**.png']}})

此时已经成功启动项目了;

自定义模板开发

在mj-cli-dev-template/mj-cli-dev-template-custom-vue3目录下复制一份mj-cli-dev-template-vue3;可以去本地install的目录地址下本地调试mj-cli-dev-template-custom-vue3模板的代码;最后将调试成功的代码发布npm;

mj-cli-dev-template-custom-vue3/package.json 复制代码
{
  "name": "mj-cli-dev-template-custom-vue3",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

创建mj-cli-dev-template-custom-vue3/index.js文件;

mj-cli-dev-template-custom-vue3/index.js 复制代码
const fse = require("fs-extra");
const inquirer = require("inquirer");
const ejs = require("ejs");

async function ejsRender(options) {
  const dir = options.targetPath;
  const { projectInfo } = options;
  return new Promise((resolve, reject) => {
    require("glob")(
      "**",
      {
        cwd: dir,
        ignore: options.ignore,
        nodir: true,
      },
      (err, files) => {
        if (err) {
          reject(err);
        }
        Promise.all(
          files.map((file) => {
            const filePath = path.join(dir, file);

            return new Promise((resolve1, reject1) => {
              ejs.renderFile(filePath, projectInfo, {}, (err, result) => {
                if (err) {
                  reject1(err);
                } else {
                  // ejs模板转换不成功,渲染结果需重新写入
                  fse.writeFileSync(filePath, result);
                  resolve1(result);
                }
              });
            });
          })
        )
          .then(() => {
            resolve();
          })
          .catch((err) => {
            reject(err);
          });
      }
    );
  });
}

async function install(options) {
  const projectPrompt = [];
  const descriptionPrompt = {
    type: "input",
    name: "componentDescription",
    message: "请输入项目描述信息",
    default: "",
    validate: function (v) {
      const done = this.async();

      setTimeout(function () {
        if (!v) {
          done("请输入项目描述信息");
          return;
        } else {
          done(null, true);
        }
      }, 0);
    },
  };
  projectPrompt.push(descriptionPrompt);
  const obj = await inquirer.prompt(projectPrompt);
  options.projectInfo.description = obj.componentDescription;
  try {
    //拷贝模版代码至当前目录
    const { sourcePath, targetPath } = options;

    // 确保目录存在,不存在会创建一个
    fse.ensureDirSync(sourcePath);
    fse.ensureDirSync(targetPath);
    fse.copySync(sourcePath, targetPath);
    const opts = {
      ignore: ["**/node_modules/**"],
      targetPath,
      projectInfo: options.projectInfo,
    };
    if (options.templateInfo.ignore) {
      opts.ignore = opts.ignore.concat(options.templateInfo.ignore);
    }
    await ejsRender(opts);
  } catch (e) {
    throw e;
  }
}
module.exports = install;
mj-cli-dev-template-custom-vue3/template/package.json 复制代码
{
  "name": "<%= className %>",
  "version": "<%= version %>",
  "description": "<%= description %>",

npm publish新的包mj-cli-dev-template-custom-vue3

mongodb中插入一条数据:

js 复制代码
db.project.insert({name: 'vue3自定义模板', 
    npmName: 'mj-cli-dev-template-custom-vue3',
    version: '1.0.0',
    type: 'custom',
    tag: ['project'],
    installCommand: 'cnpm install',
    startCommand: 'npm run serve',
    ignore: ['**/public/**']
})
相关推荐
sg_knight2 分钟前
VSCode如何修改默认扩展路径和用户文件夹目录到D盘
前端·ide·vscode·编辑器·web
一个处女座的程序猿O(∩_∩)O12 分钟前
完成第一个 Vue3.2 项目后,这是我的技术总结
前端·vue.js
mubeibeinv12 分钟前
项目搭建+图片(添加+图片)
java·服务器·前端
逆旅行天涯19 分钟前
【Threejs】从零开始(六)--GUI调试开发3D效果
前端·javascript·3d
m0_7482552640 分钟前
easyExcel导出大数据量EXCEL文件,前端实现进度条或者遮罩层
前端·excel
web147862107231 小时前
C# .Net Web 路由相关配置
前端·c#·.net
m0_748247801 小时前
Flutter Intl包使用指南:实现国际化和本地化
前端·javascript·flutter
飞的肖1 小时前
前端使用 Element Plus架构vue3.0实现图片拖拉拽,后等比压缩,上传到Spring Boot后端
前端·spring boot·架构
青灯文案11 小时前
前端 HTTP 请求由 Nginx 反向代理和 API 网关到后端服务的流程
前端·nginx·http
m0_748254882 小时前
DataX3.0+DataX-Web部署分布式可视化ETL系统
前端·分布式·etl