写点什么

懒,才是第一生产力

  • 2020-04-01
  • 本文字数:4448 字

    阅读完需:约 15 分钟

懒,才是第一生产力

[懒]——才是第一生产力

你没有看错,懒绝对是第一生产力,技术的进步,很多时候都是因为一些非常聪明的人难以忍受一些(在他们眼里)枯燥重复且低效的东西,从而发明出的东西,无论这些新发明在经历了迭代和打磨之后看起来多么牛逼耀眼,但其本质基本都可以归纳为:


是聪明的懒人搞出的,可以让自己更省事的东西。


jQuery 的流行,是因为开发者懒得为 DOM 编写跨浏览器兼容性代码;


Angular.js 的流行, 是因为开发者连 DOM 都懒得操作;


Bootstrap 的流行, 是因为开发者懒得编写自适应样式;


Webpack 的流行, 是因为开发者懒得做一系列上线前的准备工作 …


有的人越懒越牛逼,有的人越懒越逗逼,看来懒也是个技术活,懒出高度,懒出艺术,那才是真的高端懒。

从 GUI 到 CLI

GUI(Grapic User Interface,即图形化用户界面)和 CLI(Command Line Interface,即命令行交互界面)都有其拥护者。大家都懒,只是对懒的认知不同,用 GUI 的人懒得去记命令,用 CLI 的人懒得去挪鼠标。


很多前端童鞋都通过可视化工具小乌龟来管理 git 代码仓库,可视化工具的好处在于可以让初学者可以更直观更容易地去管理代码。


但是笔者发现很多熟练的开发者都更喜欢使用命令行工具(以下简称 Cli 工具),不仅因为 Cli 工具可以满足装 X 需求,更是因为它可以帮你省掉很多繁琐的移动鼠标和点击的动作。有时候你并不需要去记忆很多指令和参数(当然用的次数多了,你不想记也记住了),几乎所有的命令行工具只要简单滴使用-h 或–help 参数就可以打印出帮助文件,你完全可以边学边用,逐步熟悉。



很多熟悉 Vue 的同学都使用过 vue-cli 命令行工具来初始化一个 Vue 项目,如下图所示,通过向导式问答收集关键参数信息,然后自动生成相应的工程文件,比你自己各种新建文件和新建文件夹效率高多了。



接下来,请跟随笔者一起,看看一个前端开发人员如何从零开始打造一款属于自己的 Cli 工具吧~

相关知识储备

1.前提条件:你需要一些 Node.js 的 API 知识和一些基本的命令行使用经验。详细的文档可以访问 NodeJs 官方 API 获取更多信息。


2.readline:readline 工具包用于逐行处理信息,常用的 API 包括:


createInterface:


用于创建接口实例,成功调用后返回一个接口实例,调用后使用方法如下:


Javascript 代码


1 var rl = readline.createInterface({ input: process.stdin, output: process.stdout });    
复制代码


rl.question(query, callback)


实例方法,提供一个问答式单行交互方法,向用户展示提示信息,然后接受并处理用户输入,调用方法如下:


Javascript 代码


1 rl.question('你学会怎么用了吗?',function(input){ console.log('你输入了:',input); })    
复制代码


rl.write(info)


实例方法,向创建 rl 接口实例时连接的 output 输出流输出信息,通常使用主进程输出流 process.stdout,调用方法如下: -


Javascript 代码


1    rl.write('我是这样用的');    
复制代码


做个 Demo 轻松一下(demo 的源码请在附件拿):



3.child_process


child_process 包提供了利用子进程执行命令或调用文件的能力,常用的 API 包括:


child_process.spawn()


实际执行方法,其他方法均为基于此方法的封装,使用方式如下:


Javascript 代码


01    const { spawn } = require('child_process');    02    const ls = spawn('ls', ['-lh', '/usr']);    03    04    ls.stdout.on('data', (data) => {    05      console.log(`stdout: ${data}`);    06    });    07    08    ls.stderr.on('data', (data) => {    09      console.log(`stderr: ${data}`);    10    });    11    12    ls.on('close', (code) => {    13      console.log(`child process exited with code ${code}`);    14    });    
复制代码


childprocess.exec(), childprocess.execFile()及同名的同步方法


均是对 spawn 方法一定程度上的封装,使用更方便。


再来个 Demo 轻松一下,通过在 windows 命令行工具中执行 js 文件,执行了 dir 命令(demo 的源码请在附件拿):



ps:乱码的问题涉及到子进程和主进程通讯时的信息的编码和解码问题,遇到实际问题的童鞋可以了解一下 iconv-lite 这个插件。

guide 风格命令行开发工具——inquirer.js

github 地址为:


Inquirer.jsguide 风格的命令行,指提问-回答模式的命令行,inquirer.js 支持常见的 input 输入,单选,多选,是/否等常见提问类型,并暴露了增加自定义类型的接口,参考官方文档很容易使用。


API 使用举例:


Javascript 代码


01    const questions = [];    02    03      inquirer    04      .prompt(    05          /* Pass your questions in here */    06          [{    07            type: 'confirm',    08            name: 'toBeDelivered',    09            message: 'Is this for delivery?',    10            default: false    11          }]    12      )    13      .then(answers => {    14         // Use user feedback for... whatever!!    15      });    
复制代码


来看看官方提供的一个 Pizza 订购工具 pizza.js 的效果(是不是有 vue-cli 的既视感):


git 风格命令行开发工具——commander.js

github 地址为:


Commander.js(https://github.com/SBoudrias/Inquirer.js) git 风格命令行,是指通过主指令+子指令+参数的模式运行命令实现功能,和 guide 风格命令行没有本质区别,只是使用习惯的偏好。


API 使用举例:


Javascript 代码


1    program    2      .version('0.0.1')    3      .description('An application for pizzas ordering')    4      .option('-p, --peppers', 'Add peppers')    5      .option('-P, --pineapple', 'Add pineapple')    6      .option('-b, --bbq', 'Add bbq sauce')    7      .option('-c, --cheese <type>', 'Add the specified type of cheese [marble]')    8      .option('-C, --no-cheese', 'You do not want any cheese')    9      .parse(process.argv);    
复制代码


来看看官方提供的这个 Pizza 订购工具 pizza.js 的效果:


不同风格的实现思路

1.基本架构


web 版本


前端使用任意框架制作,点击某功能按钮时,向后端发送带参请求


后端为 node 服务器,**指定端口,接收到客户端请求后,调用具体功能


根据后端执行情况信息在前端展示的实时性要求,选择长连接或普通连接


后端使用 child_process 或相关类库实现命令并将信息传输至前端


Guide 风格命令行


直接使用 inquirer.js 库编写问题组或分支问题树


inquirer.js 最终将用户输入绑定在一个对象上


使用 inquirer.js 收集到的参数


带参数运行命令或脚本


git 风格命令行


直接使用 commander.js 库的 API 编写支持的指令


commander.js 会从注册的命令及子命令中寻找匹配


使用 commander.js 收集到的参数运行对应的命令或脚本


2.其他问题


兼容性


使用多种脚本格式 为了兼容不同运行环境,可以为实际需要执行的命令准备.bat 和.sh 两套脚本,在 node.js 代码中根据 process.platform 查询当前系统环境并调用对应格式的脚本


使用兼容性插件库 例如《一统江湖的大前端(4)——Shell.js》中提及的 shell.js 库,可将自动化脚本重构为 js 版本代码,实现跨平台运行。


全局执行命令


开发版本 开发版本的程序,可以在代码根目录中使用 npm link 将其注册为全局安装,当开发完毕正式发布后,使用 npm unlink 去除连接即可。


发布版本 当 node 包开发完成并使用 publish 命令正式发布以后,即可通过 npm install -g XXX 或 yarn global add XXX 直接从 npm 上下载并全局安装,然后即可全局使用。

要什么 demo?直接搞实战!

接下来我们在 Windows 环境下实现一个自动化脚本,实现的功能主要包括:


1.删除旧目录


2.新建目录


3.从远程 git 仓库指定分支下载代码


4.在本地建立新分支并


auto_download.js 源码:-


Javascript 代码


01    var child_process = require('child_process');    02    function execTask(issueNumber, openLocalhost) {    03        //示例中的自定义配置信息从configJson对象中获取    04        var originDir = configJson['项目信息']['远程仓库地址'];    05        var originBranch = configJson['feature分支']['远程分支名称'];    06        var destDir = configJson['项目信息']['本地仓库地址'];    07        var projectName = configJson['项目信息']['项目名称'] + '_issue';    08        var devBranch = configJson['本地开发']['默认分支前缀'] + issueNumber;    09    10        //执行下载脚本    11        var issue_process = child_process.spawn('download_dev_branch.bat',    12            [destDir, projectName, originDir, originBranch, devBranch],    13            {    14                stdio : 'inherit'    15            });    16    17            //**标准输出    18            issue_process.stdout    19            .on('exit', function (number) {    20                console.log(number);    21                console.log('感谢您使用Dash-Toolbox!')    22            });    23    }    24    25    execTask(12315, true);    
复制代码


自动化脚本 download_dev_branch.bat 源码:-


Bash 代码


01    @echo off    02    rem 当前脚本用于将远程仓库的开发分支代码下载至指定的本地目录并生成开发分支    03    rem %1 - 本地仓库文件夹    04    rem %2 - 本地指定分支文件夹名    05    rem %3 - 远程仓库地址    06    rem %4 - 远程开发分支名    07    rem %5 - 包含issue代码的本地分支    08    @echo on    09    cd %1    10    rmdir /s/q %2    11    mkdir %2 && cd %2    12    git init    13    git remote add origin %3    14    git fetch origin %4 :%5 --progress --no-tags    15    git checkout %5    16    exit(0)    
复制代码


使用方法: 在文件目录下开启命令行 cmd.exe,输入 node auto_download 即可看到在对应的目录下载了代码:


感觉如何?有没有爽到?反正笔者自己是爽到了。

后记

在学习了以上知识后,笔者决定开发一款命令行工具——Dash-Toolbox。 其目的主要是:


在保密性要求较高所以不通外网的环境下,将常用的文档资源集中化,将常规的动作自动化。


在全局环境下命令行中输入 dash 即可启动 Guide 模式,输入 dash -h 类似命令即可支持 Git 模式,并已经制作了 Web 模式的首页。来先睹为快感受一下:




其实是受够了一次次花 20 秒钟改代码,然后花 20 分钟提交代码和发布的过程,尽管代码提交后的流程已经打通了 jenkins 的自动化流程,但代码提交前的本地工作仍然是手动的,我真的只是懒而已。

后续的规划是:

  • 完成 git 风格命令行工具编写

  • 完成基本功能对应的自动化执行脚本编写

  • 内源发布,邀请内测

  • 学习 Node API,完善命令行工具功能及容错机制

  • 学习 React 技术栈,开发 GUI 版本

  • 学习 Electron 技术栈,开发桌面应用版本

  • 核心功能版本迭代及 Bug 修复

  • 开源发布


本文转载自 华为云产品与解决方案 公众号。


原文链接:https://mp.weixin.qq.com/s/20iu0DQf2KwSs-VhcMCRtg


2020-04-01 14:531007

评论

发布
暂无评论
发现更多内容

架构师训练营第二周作业

文智

极客大学架构师训练营

架构师训练营—第二周学习总结

Geek_shu1988

面向对象设计原则----单一职责原则(SRP)

张荣召

Java中的遍历(遍历集合或数组的几种方式)

keaper

Java List 遍历

金融科技推进数字金融“新基建”,着力建设三种类型数字金融基础设施

CECBC

金融 科技 科技革命

第 2 周 作业

Pyr0man1ac

架构师训练营 Week2 作业 1

lucian

极客大学架构师训练营

面向对象设计原则----接口分离原则(ISP)

张荣召

案例分析--反应式编程框架Flower的设计

张荣召

第二周

等燕归

第二周课后练习

薛凯

国内首个区块链村正式落地:数字经济的裂变之路

CECBC

区块链 数字经济

OOA-OOD:面向对象分析/设计练习

张荣召

架构师训练营 1 期 - 第二周总结(vaik)

行之

架构师训练营第二周学习总结

薛凯

架构师训练营第二周心得

CmHuang

#第二周作业

vitaminc

MySQL是如何实现可重复读的?

超超不会飞

MySQL

从四个问题透析Linux下C++编译&链接

华为云开发者联盟

c++ Linux 编程

深入理解JVM垃圾回收算法 - 标记整理算法

Skye

标记整理 双指针算法 Lisp2 引线整理算法

[架构师训练营第1期]第二周学习总结

猫切切切切切

极客大学架构师训练营

架构师训练营 Week2 作业 2【学习总结】

lucian

极客大学架构师训练营

graylog日志分析系统上手教程

MySQL从删库到跑路

Apache Linux 运维 日志分析 实时 Web 日志分析器

架构训练营 - 第 2周课后作业 - 学习总结

Pudding

第二周学习框架设计总结

三板斧

极客大学架构师训练营

华为:与全球180万云与计算开发者共成长,共创行业新价值

华为云开发者联盟

作业-2020-09-27

芝麻酱

第二周总结

等燕归

架构师训练营 - 第 2 周课后作业(1 期)

Pudding

为什么区块链巨头企业一定会诞生在中国的原因分析

CECBC

区块链 科技

架构师训练营—第二周作业

Geek_shu1988

懒,才是第一生产力_行业深度_华为云产品与解决方案_InfoQ精选文章