《一统江湖的大前端》系列是自己的前端学习笔记,旨在介绍javascript在非网页开发领域的应用案例和发现各类好玩的js库,不定期更新。如果你对前端的理解还是写写页面绑绑事件,那你真的是有点OUT了,前端能做的事情已经太多了, 手机app开发 , 桌面应用开发 , 用于神经网络人工智能的库 , 页面游戏 , 数据可视化 , 甚至 嵌入式开发 ,什么火就搞什么,活脱脱一个蹭热点小能手。如果你也觉得前端的日常开发有些枯燥,不妨一起来看看前端的另一番模样。



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

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

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

  • 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

    用于创建接口实例,成功调用后返回一个接口实例,调用后使用方法如下:
  var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
  • rl.question(query, callback)

    实例方法,提供一个问答式单行交互方法,向用户展示提示信息,然后接受并处理用户输入,调用方法如下:
  rl.question('你学会怎么用了吗?',function(input){
console.log('你输入了:',input);
})
  • rl.write(info)

    实例方法,向创建rl接口实例时连接的output输出流输出信息,通常使用主进程输出流process.stdout,调用方法如下:
  rl.write('我是这样用的');

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

3.child_process

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

  • child_process.spawn()

    实际执行方法,其他方法均为基于此方法的封装,使用方式如下:
    const { spawn } = require('child_process');
const ls = spawn('ls', ['-lh', '/usr']); ls.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
}); ls.stderr.on('data', (data) => {
console.log(`stderr: ${data}`);
}); ls.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
  • child_process.exec(), child_process.execFile()及同名的同步方法

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

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



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

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

github地址为:Inquirer.js地址

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

API使用举例:

  const questions = [];

  inquirer
.prompt(
/* Pass your questions in here */
[{
type: 'confirm',
name: 'toBeDelivered',
message: 'Is this for delivery?',
default: false
}]
)
.then(answers => {
// Use user feedback for... whatever!!
});

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

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

github地址为:Commander.js地址

git风格命令行,是指通过主指令+子指令+参数的模式运行命令实现功能,和guide风格命令行没有本质区别,只是使用习惯的偏好。

API使用举例:

program
.version('0.0.1')
.description('An application for pizzas ordering')
.option('-p, --peppers', 'Add peppers')
.option('-P, --pineapple', 'Add pineapple')
.option('-b, --bbq', 'Add bbq sauce')
.option('-c, --cheese <type>', 'Add the specified type of cheese [marble]')
.option('-C, --no-cheese', 'You do not want any cheese')
.parse(process.argv);

来看看官方提供的这个Pizza订购工具pizza.js的效果(老外是有多喜欢吃Pizza!!!):

六.不同风格的实现思路

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 XXXyarn global add XXX直接从npm上下载并全局安装,然后即可全局使用。

七.要什么demo?直接搞实战!

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

  • 1.删除旧目录
  • 2.新建目录
  • 3.从远程git仓库指定分支下载代码
  • 4.在本地建立新分支并

auto_download.js源码:

var child_process = require('child_process');
function execTask(issueNumber, openLocalhost) {
//示例中的自定义配置信息从configJson对象中获取
var originDir = configJson['项目信息']['远程仓库地址'];
var originBranch = configJson['feature分支']['远程分支名称'];
var destDir = configJson['项目信息']['本地仓库地址'];
var projectName = configJson['项目信息']['项目名称'] + '_issue';
var devBranch = configJson['本地开发']['默认分支前缀'] + issueNumber; //执行下载脚本
var issue_process = child_process.spawn('download_dev_branch.bat',
[destDir, projectName, originDir, originBranch, devBranch],
{
stdio : 'inherit'
}); //监听标准输出
issue_process.stdout
.on('exit', function (number) {
console.log(number);
console.log('感谢您使用Dash-Toolbox!')
});
} execTask(12315, true);

自动化脚本download_dev_branch.bat源码:

@echo off
rem 当前脚本用于将远程仓库的开发分支代码下载至指定的本地目录并生成开发分支
rem %1 - 本地仓库文件夹
rem %2 - 本地指定分支文件夹名
rem %3 - 远程仓库地址
rem %4 - 远程开发分支名
rem %5 - 包含issue代码的本地分支
@echo on
cd %1
rmdir /s/q %2
mkdir %2 && cd %2
git init
git remote add origin %3
git fetch origin %4 :%5 --progress --no-tags
git checkout %5
exit(0)

使用方法:

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

自动化脚本的部分也可以采用nodeFile API来实现。

八.后记

在学习了以上知识后,笔者决定开发一款命令行工具——Dash-Toolbox

其目的主要是:

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

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



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

一统江湖的大前端(6)commander.js + inquirer.js——懒,才是第一生产力的更多相关文章

  1. 一统江湖的大前端(2)—— Mock.js + Node.js 如何与后端潇洒分手

    <一统江湖的大前端>系列是自己的前端学习笔记,旨在介绍javascript在非网页开发领域的应用案例和发现各类好玩的js库,不定期更新.如果你对前端的理解还是写写页面绑绑事件,那你真的是有 ...

  2. 一统江湖的大前端(4)shell.js——穿上马甲我照样认识你

    <一统江湖的大前端>系列是自己的前端学习笔记,旨在介绍javascript在非网页开发领域的应用案例和发现各类好玩的js库,不定期更新.如果你对前端的理解还是写写页面绑绑事件,那你真的是有 ...

  3. 一统江湖的大前端(10)——inversify.js控制反转

    <大史住在大前端>前端技术博文集可在下列地址访问: [github总基地][博客园][华为云社区][掘金] 字节跳动幸福里大前端团队邀请各路高手前来玩耍,团队和谐有爱,技术硬核,字节范儿正 ...

  4. 一统江湖的大前端(8)- velocity.js 运动的姿势(上)

    [摘要] 介绍CSS动画和JS动画的基本特点,以及轻量级动画库velocity.js的基本用法. 示例代码托管在:http://www.github.com/dashnowords/blogs 博客园 ...

  5. 一统江湖的大前端(3) DOClever——你的postman有点low

    <一统江湖的大前端>系列是自己的前端学习笔记,旨在介绍javascript在非网页开发领域的应用案例和发现各类好玩的js库,不定期更新.如果你对前端的理解还是写写页面绑绑事件,那你真的是有 ...

  6. 一统江湖的大前端(1)——PPT制作库impress.js

    <一统江湖的大前端>系列是自己的学习笔记,旨在介绍javascript在非网页开发领域的应用案例和发现各类好玩的js库,不定期更新.如果你对前端的理解还是写写页面绑绑事件,那你真的是有点O ...

  7. 【一统江湖的大前端(8)】matter.js 经典物理

    目录 [一统江湖的大前端(8)]matter.js 经典物理 一.经典力学回顾 二. 仿真的实现原理 2.1 基本动力学模拟 2.2 碰撞模拟 三. 物理引擎matter.js 3.1 <愤怒的 ...

  8. 一统江湖的大前端(5)editorconfig + eslint——你的代码里藏着你的优雅

    <一统江湖的大前端>系列是自己的前端学习笔记,旨在介绍javascript在非网页开发领域的应用案例和发现各类好玩的js库,不定期更新.如果你对前端的理解还是写写页面绑绑事件,那你真的是有 ...

  9. 一统江湖的大前端(7)React.js-从开发者到工程师

    目录 一. 前端打怪升级指南 1.1 我应该从哪个框架开始学? 1.2 一次转职 1.3 二次转职 1.4 转职-其他 二. 为什么你应该学习React 2.1 技术栈的延伸 2.2 组件化开发 2. ...

随机推荐

  1. Javaweb-request与response

                           Javaweb-request与response              Servlet   生命周期(什么时候创建的,什么时候销毁的);     Se ...

  2. mongodb建立索引

    创建索引 索引:以提升查询速度 语法:db.集合.ensureIndex({属性:1}),1表示升序,-1表示降序 具体操作:db.t255.ensureIndex({name:1}) db.t1.f ...

  3. mybatis3源码阅读之SqlSessionFactoryBuilder

    /** 构造器,根据配置或者代码生成SqlSessionFactory,采用分布构建的Builder模式 /* public class SqlSessionFactoryBuilder { /** ...

  4. ps入门学习

    快捷键 打开 ctrl+O 切换显示窗口 ctrl+tab 隐藏工具栏和面板  tab 只隐藏面板不隐藏工具栏  shift+tab 切换屏幕模式  F 文件的新建与格式 1.新建文档Ctrl+N,存 ...

  5. sqlserver 电脑重启以后服务突然无法启动 报错

    可能是sql server 评估期已过  在升级中输入产品密钥试试

  6. High Availability手册(3): 配置

    各种配置在命令行状态下,多用crm进行 Global Cluster Options 这个类型是全局配置,主要包含下面两个: no-quorum-policy quorum的意思是最低法定人数,pac ...

  7. 多个router和多个network

    一般搭建成功了opentack后,都会按照文档的这样创建网络 Scenario 1: one tenant, two networks, one router Scenario 2: two tena ...

  8. Dubbo与Nginx区别

    Dubbo的负载均衡已经是服务层面的了,和nginx的负载均衡还在http请求层面完全不同.至于二者哪个优秀,当然没办法直接比较. 涉及到负载均衡就涉及到你的业务,根据业务来选择才是最适合的. dub ...

  9. xss挖掘初上手

    本文主要总结了xss可能出现的场景.偏向于案例,最后分享一哈简单的绕过和比较好用的标签. 1.搜索框 首先看能否闭合前面的标签. 如输入111”><svg/onload=alert(1)& ...

  10. [Swift]LeetCode382. 链表随机节点 | Linked List Random Node

    Given a singly linked list, return a random node's value from the linked list. Each node must have t ...