最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 前端项目搭建部署全流程(四):脚手架与业务模块构建

    正文概述 掘金(Phil_Hu)   2020-12-27   413

    1.前言

    继上一篇文章之后一个简单的React项目模板已经搭建好了,这篇文章主要写一下简易脚手架以及业务模块的生成命令行,以往我们使用较多的是vue-cli、create-react-app等开源脚手架,但是这些脚手架不一定符合我们当前使用的环境(比如公司的通用脚手架),这个时候我们就需要针对使用环境搭建一个脚手架,来提升整体的开发效率。

    仓库代码地址:https://github.com/huhaiqing106/MyProject/tree/master/DemoCli

    2.支持的功能

    这个脚手架写的比较简单,主要实现了两个功能:

    1. work init <project-name> <git or svn>根据可选仓库拉取远程模板,初始化一个项目
    2. work create <business-pageName>根据GIT仓库拉取业务模块模板,生成业务木块项目结构(这个模板没有实现功能,可以从这些方面去入手,比如包含一个标砖的查询界面或者内置一些通用的方法增、删、查、改等,可以快速构建一个简单的查询界面)

    3.初始化项目

    npm init -y
    

    3.1.安装依赖

    yarn add chalk commander download-git-repo inquirer node-svn-ultimate ora --dev
    

    chalk修改控制台输出内容样式

    commander命令行工具

    download-git-repo从GIT拉取远程模板

    inquirer交互式命令行工具

    node-svn-ultimate从SVN拉取远程模板

    ora显示loading动画

    3.2.创建bin目录

    bin目录下创建work-cli.js文件,文件顶部注解是告诉系统用node去执行,添加init命令

    #! /usr/bin/env node
    
    const program = require('commander');
    
    // 定义当前版本
    // 定义使用方法
    // 定义四个指令
    program
      .version(require('../package.json').version)
      .usage('<command> [options]')
      // 后期扩展支持根据配置的地址初始化模板
      // .command("init-config", "generate a new project from a config template")
      .command('init', 'generate a new project from git')
      .command('create', 'create a new business page from git');
    // 解析命令行参数
    program.parse(process.argv);
    
    

    创建完改文件我们通过node ./bin/work-cli 执行,控制台会出现如下结果

    前端项目搭建部署全流程(四):脚手架与业务模块构建

    如果每次都输入node ./bin/work-cli 就比较麻烦了,我们重新在package.json中增加启动命令

    {
      "name": "work-cli",
      "version": "0.0.1",
      "description": "work cli",
      "main": "index.js",
      "bin": {
        "work": "bin/work-cli.js"
      },
      ...
    }
    

    然后通过npm link挂载到全局,这样就只需要输入work就可以运行了

    前端项目搭建部署全流程(四):脚手架与业务模块构建

    我们可以通过npm list -g --depth 0查看全局的依赖,然后通过npm unlink卸载挂载到全局的命令,卸载的命令名就是当前工程下package.json中的name

    前端项目搭建部署全流程(四):脚手架与业务模块构建

    4.编写command命令

    4.1.init命令

    当执行work init时,node会自动从bin目录下查找work-cli-xxx.js的文件

    work init <project-name> <git or svn>
    

    work-cli-init.js代码如下,处理argv的参数以及分发到对应的仓库文件拉取模板,然后删除从仓库拉取下来之后目录中的.git/.svn文件,让目录与拉取仓库解绑,目录文件不展示仓库状态图标

    #!/usr/bin/env node
    
    const program = require('commander');
    const chalk = require('chalk');
    const ora = require('ora');
    const initSvn = require('./work-cli-svn');
    const initGit = require('./work-cli-git');
    const deleteFolder = require('./common/deleteFile');
    
    program.usage('<project-name> <git or svn>');
    program.parse(process.argv);
    
    // 当没有输入参数的时候提示
    if (program.args.length < 1) return program.help();
    
    const projectName = program.args[0];
    // 校验下项目名称
    if (!projectName) {
      console.log(chalk.red('\n Project should not be empty! \n'));
      return;
    }
    
    const warehouseType = program.args[1];
    // 校验仓库类型
    if (!warehouseType) {
      console.log(chalk.red('\n Warehouse should not be empty! \n'));
      return;
    }
    
    console.log(chalk.white('\n Start generating... \n'));
    // 加载图标
    const spinner = ora('Downloading...');
    spinner.start();
    
    const callBack = (err, fileName) => {
      spinner.succeed();
      if (err) {
        console.log(chalk.red('\n Copy project template exception'));
        console.log(`\n ${err}`);
      } else {
        try {
          deleteFolder('./' + projectName, fileName);
        } catch (error) {
          console.log(chalk.yellow('\n Delete ' + fileName + ' folder exception, but does not affect operation'));
        }
        console.log(chalk.green('\n Generation completed!'));
        console.log('\n To get started');
        console.log(`\n    cd ${projectName} \n`);
      }
    };
    
    if (warehouseType === 'svn') {
      initSvn(projectName).then((err) => {
        callBack(err, '.svn');
      });
    } else {
      const repository = 'direct:https://github.com/huhaiqing106/react-temlpate.git';
      initGit(repository, projectName).then((err) => {
        callBack(err, '.git');
      });
    }
    

    Git仓库拉取的时候repository需要特别注意下地址一定要带上direct:,GIT地址从这里copy,然后加上direct:

    前端项目搭建部署全流程(四):脚手架与业务模块构建

    4.1.1.work-cli-git文件

    这个文件很简单,就是从GIT拉取模板

    const download = require('download-git-repo');
    
    module.exports = (repository, projectName) => {
      return new Promise((resolve, reject) => {
        download(repository, projectName, { clone: true }, function (err) {
          resolve(err);
        });
      });
    };
    
    

    4.1.2.work-cli-svn文件

    const svnUltiMate = require('node-svn-ultimate');
    
    module.exports = (projectName) => {
      const svnUrl = 'xxxx';
    
      return new Promise((resolve, reject) => {
        svnUltiMate.commands.checkout(svnUrl, projectName, { username: 'xxx', password: 'xxx' }, function (err) {
          resolve(err);
        });
      });
    };
    

    这个文件是从SVN仓库拉取模板,这里需要注意几点,因为node是通过命令行去拉取的模板,所以我们的环境需要支持svn命令,参考如下:

    安装SVN命令行工具,附下载地址

    下载Apache Subversion command line tools,这是一个可以在cmd下使用的命令行工具,解压后把里面bin目录这个路径添加到环境变量的path,这样在cmd下就可以使用了,和Linux下使用svn的习惯一样了。

    配置环境变量

    安装目录\Apache-Subversion\bin\
    

    4.1.3.deleteFile文件

    这个文件主要是递归删除从仓库拉取下来的模板中的隐藏文件.svn/.git

    const fs = require('fs');
    
    /**
     * 寻找.svn文件,删除svn关联
     *
     * @param {*} pathStr
     */
    function deleteFolder(pathStr, fileName) {
      let files = [];
      if (fs.existsSync(pathStr)) {
        files = fs.readdirSync(pathStr, 'utf8');
        files.forEach(function (file, index) {
          let curPath = pathStr + '/' + file;
          // 匹配特定SVN文件夹,然后移除
          if (new RegExp(`^${fileName}$`).test(file)) {
            deleteFile(curPath);
          }
        });
      }
    }
    
    /**
     * 删除svn文件夹与文件
     *
     * @param {*} pathStr
     */
    function deleteFile(pathStr) {
      let files = [];
      if (fs.existsSync(pathStr)) {
        files = fs.readdirSync(pathStr, 'utf8');
        files.forEach(function (file, index) {
          let curPath = pathStr + '/' + file;
          if (fs.statSync(curPath).isDirectory()) {
            deleteFile(curPath);
          } else {
            fs.unlinkSync(curPath);
          }
        });
        fs.rmdirSync(pathStr);
      }
    }
    
    module.exports = deleteFolder;
    

    4.2.create命令

    create命令也一样,只是拉取的模板不同而已,所以直接上代码

    const program = require('commander');
    const chalk = require('chalk');
    const initGit = require('./work-cli-git');
    const ora = require('ora');
    const deleteFolder = require('./common/deleteFile');
    
    program.usage('<business-pageName>');
    program.parse(program.args);
    
    if (program.args.length < 1) {
      return program.help();
    }
    
    const pageName = program.args[0];
    
    if (!pageName) {
      console.log(chalk.red('\n PageName should not be empty \n'));
      return;
    }
    
    console.log(chalk.white('\n Start generating... \n'));
    // 加载图标
    const spinner = ora('Downloading...');
    spinner.start();
    
    const repository = 'direct:https://github.com/huhaiqing106/business-page-template.git';
    initGit(repository, pageName).then((err) => {
      spinner.succeed();
      if (err) {
        console.log(chalk.red('\n Copy business page template exception'));
        console.log(`\n ${err}`);
      } else {
        try {
          deleteFolder('./' + pageName, '.git');
        } catch (error) {
          console.log(chalk.yellow('\n Delete ' + fileName + ' folder exception, but does not affect operation'));
        }
        console.log(chalk.green('\n Generation completed!'));
      }
    });
    

    5.发布npm

    至此一个简易的脚手架已经搭建好了,本地我们可以通过npm link挂载到全局测试,测试通过之后,我们在发布到npm私服,然后通过npm install xxx -g将依赖安装到全局之后,就可以开心的玩耍了

    6.资料文件

    SVN安装教程:https://www.jianshu.com/p/725e49003e44

    SVN命令行工具: www.visualsvn.com/downloads/

    参考资料:https://juejin.cn/post/6844903807919325192#heading-10

    第一次记录写文章,文笔有限,多多包涵,ヾ(´ー`)ノ゛谢谢♪


    起源地下载网 » 前端项目搭建部署全流程(四):脚手架与业务模块构建

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元