在实际开发中,一般刚开始一个项目或者刚接手一个项目,我们会运行 npm install 下载安装所有依赖, 在实际开发中,可能也会使用各种命令行…… 来提高我们开发的效率。
与它相处了这么久,你真的了解 npm 这些东西吗?
 
本篇文章会分别介绍下面几个内容:
  • package.json
  • 解析命令行参数
  • 丰富终端交互体验
  • 发布 npm 包
  • 实战--开发小程序脚手架
 
项目背景:每次新建小程序页面要生成四个文件名相同的文件 ( .wxml、.wxss、.json  和 .js ),并且要在 app.json 的 pages 字段自动添加新页面路径, 在 .json 中写上当前页面的名字,非常的麻烦,所以~ 自己动手做一个 npm 脚本工具,一键生成重复性的文件,解放双手。

最终,我们希望实现一个这样的效果:

在工作目录下就会有对应的文件,并且 app.json 的 pages 字段自动添加新页面路径, 对应的 .json 也有当前页面的名字.

package.json 

第一步,相信大家都知道,npm init 之后,就会生成一个 package.json
我们会在 package.json 中添加以下代码
"repository": {
"type": "git",
"url": "https://github.com/beidan/nsp"
}

这样可以指明我的代码被托管在何处,用户可以使用 npm docs 命令打开该项目。但是如果 url 类型与 type类型不一致的话,那只会默认打开该包的 name

类似于一些简单的字段意思,我将不会详细说明,具体的规范可以在 package.json 规范 中查看。

在有些项目的 package.json 中,我们可能会看到下面这样的代码:

{
"bin": {
"nsp": "./bin/index.js"
},
"scripts": {
"precommit": "./hooks/pre-commit.js",
"prepush": "./hooks/pre-push"
}
}

bin 字段可以用来存放一个可执行的文件

执行 npm link 命令,它将会把 nsp 这个字段复制到 npm 的全局模块安装文件夹 node_modules 内,并创建符号链接(symbolic link,软链接),也就是将 nsp 的路径加入环境变量 PATH。就可以直接在命令行中使用 nsp ……

scripts 在每个命令前都会执行对应命令的 pre+scriptname 脚本,每个命令结束后会执行对应买了的 post+scriptname 脚本。如果没有定义,则不会执行对应的pre ,post命令。

解析命令行参数

为了实现功能,我们必然需要获取到用户命令行的一些参数,比如它希望新建页面,还是新建模块…然后处理获取到的数据。那么,要怎么获取到用户输入的数据?

我们可以使用 process.argv 拿到序列化的参数,当然,原生的处理方法都是比较麻烦的,nodejs社区里边已经有了比较成熟的命令行管理工具,比如 commander

好的,我们找到文章上面 bin 字段对应的可执行文件,在文件开始,我们需要告诉 shell 使用何种解释器来执行代码

#!/usr/bin/env node   //使用env来找到node,并使用node来作为程序的解释程序。

usr/bin/env 是一个程序,usr/bin/env node 会找到当前 PATH 中的 node 来解释后面的代码。

 
接下来,我们对 命令行 进行一些处理
program
.usage('[command] [options]') //在help中告诉用户如何使用
.command('page [pageName]') //定义命令行指令
.alias('pa') //重命名,定义一个更短的指令
.description('新建页面') //描述
.action((pageName) => {
console.log(pageName);
})
// 自定义帮助信息
.on('--help', function () {
console.log(' Examples:');
console.log('');
console.log(' $ nsp page index');
console.log(' $ nsp pa index');
console.log();
}); program.parse(process.argv); //解析命令行

丰富终端交互体验

好了,通过上面的代码,我们可以正常地获取到用户输入的内容了,但是,我们在开始某些命令之前,希望先询问下用户该页面的名称,方便写入每个页面对应的 json 里面。或者,我们希望他在做一些重要决定的时候,可以让我们控制,选择输入 y 还是 n。

我们可以借助 inquire 这个模块轻松实现,代码如下:

var questions = [
{
type: 'input', // input, confirm, list, rawlist, expand, checkbox, password, editor
name: 'selection', //可以在answer用这个值获取输入的值
message: '这个页面是做什么的?', //命令行中询问用户
default: false, //设置默认值,一般来说,会出现在选择中
}
]; inquirer.prompt(questions).then((answers, input)=> { }) //解析问题

非常容易理解,我们先创建一个 questions ,这个 questions 可以是单选,多选,密码类型… 然后解析问题,进行处理。

emmm…… 总感觉还少了一点什么,再用 chalk 这个美化命令行的模块。

看官方文档非常地直观了,可以让命令行变得色彩斑斓,就不赘述了。

发布 npm 包

理所当然,我们需要有仓库账号才允许将包发布到仓库中,可以直接去 npm 上注册。要翻墙。

如果已经注册了账号,可以用 npm login 登陆即可,使用命令行证明是否登陆成功。

$ npm who i am
beidan

登陆成功之后,就可以发布 npm 包了

$ npm publish

发布的时候,一般会有以下几个错误,可以选择性地阅读。

1. 没有将 registry 切回最初的源。

最初的 http://registry.npmjs.org 这个源国内用户访问非常慢,所以一开始很多人可能换成了国内淘宝的镜像:http://registry.npm.taobao.org。但是淘宝这个镜像没有开放上传的权限,因此会报这样的错误:

解决方法,在命令行改变源

npm set registry http://registry.npmjs.org  

2. 每次发布都需要增加 package.json 中的 version 的版本号,更新的版本号上传的版本要大于上次。

实战--开发小程序脚手架

下面贴相关的代码

var writeFile = function (path, name, tit) {
//在 app.json 中注册页面
util.setAppInfo(appConfig); fileType.map((item) => {
if (item == '.json') {
let content = '{"navigationBarTitleText": "' + tit + '"}';
fs.writeFile(basePath + item, content, (err)=> {
if (err) {
return console.log(err);
}
});
} else {
fs.writeFile(basePath + item, '' ,(err)=> {
if (err) {
return console.log(err);
}
});
}
})
} var creatApp = function (path, name, tit) {
//判断是否存在该目录
if (fs.existsSync(path)) {
console.log(chalk.red('该项目已存在,换个名字试试?'))
} else {
fs.mkdir(path, function (err) {
if (err) {
console.log(err);
throw err;
}
})
writeFile(path, name, tit)
}
}

为了优化体验,用户可能没有在指定目录下执行相关的命令,那么我们应该有个友好提示。

process.cwd()     //当前执行 node 命令时候的文件夹地址
__dirname //被执行的 js 文件的地址 ——文件所在目录

那我们可以这样判断用户是否在指定目录下

var isCorrect  = function () {
var baseUrl = path.resolve(__dirname, '../../'),
curUrl = process.cwd(); if(baseUrl !== curUrl) {
console.log(chalk.red(' 请在根目录下进行'));
process.exit();
}
}
 
 
 
参考资料:
凹凸实验室前端流程工具: https://github.com/o2team/athena

开始你的第一个npm脚本工具的更多相关文章

  1. npm 脚本

    查看安装的包: npm list -g --depth 0 考虑到用CLI这种方式来运行本地的webpack不是特别方便,我们可以设置一个快捷方式,在package.json添加一个npm脚本(npm ...

  2. 我想写一个前端开发工具(一):在npm发布模块

    有必要说说我为什么要开始写这个,正文从下面的第一条开始 我最近忙于公司的项目,一直没有抽出时间来写文章.本来想每个月写一片文章,保质保量,无奈上个月没有坚持. 这段时间有点忙,主要是由于公司业务调整, ...

  3. 十分钟通过 NPM 创建一个命令行工具

    大过年的,要不要写点代码压压惊?来花十分钟学一下怎么通过 NPM 构建一个命令行工具. 写了一个小 demo,用于代替 touch 的创建文件命令 touchme ,可以创建自带“佛祖保佑”注释的文件 ...

  4. npm 是node.js下带的一个包管理工具

    npm 是node.js下带的一个包管理工具          npm install -g webpack webpack是一个打包工具 gulp是一个基于流的构建工具,相对其他构件工具来说,更简洁 ...

  5. [译]为什么我要离开gulp和grunt转投npm脚本的怀抱

    原文链接:https://medium.freecodecamp.com/why-i-left-gulp-and-grunt-for-npm-scripts-3d6853dd22b8#.n7m1855 ...

  6. 用Node+wechaty写一个爬虫脚本每天定时给女(男)朋友发微信暖心话

    wechatBot 微信每日说,每日自动发送微信消息给你心爱的人 项目介绍 灵感来源 在掘金看到了一篇<用Node + EJS写一个爬虫脚本每天定时女朋友发一封暖心邮件>后, 在评论区偶然 ...

  7. 用 nodejs 写一个命令行工具 :创建 react 组件的命令行工具

    用 nodejs 写一个命令行工具 :创建 react 组件的命令行工具 前言 上周,同事抱怨说 react 怎么不能像 angular 那样,使用命令行工具来生成一个组件.对呀,平时工作时,想要创建 ...

  8. npm脚本和package.json

    1.什么是npm脚本 在创建node.js项目如一个vue项目,或一个react项目时,项目都会生成一个描述文件package.json . 比如npm允许在package.json文件里面,使用sc ...

  9. 如何发布一个 npm 包

    一 背景 在工作时,突然接到经理的一个要求,需要将一个react的高阶组件函数封装成一个npm包.之前从没弄过,当场还是有些懵逼的,但是这毕竟是工作,不能推脱.于是开始了学习.汤坑之旅.最终包发布,线 ...

随机推荐

  1. python识别html主要文本框

    在抓取网页的时候只想抓取主要的文本框,例如 csdn 中的主要文本框为下图红色框: 抓取的思想是,利用bs4查找所有的div,用正则筛选出每个div里面的中文,找到中文字数最多的div就是属于正文的d ...

  2. Entity Framework Core 2.0 使用代码进行自动迁移

    一.前言 我们在使用EF进行开发的时候,肯定会遇到将迁移更新到生产数据库这个问题,前面写了一篇文章介绍了Entity Framework Core 2.0的入门使用,这里面介绍了使用命令生成迁移所需的 ...

  3. 微信小程序---wx.request(OBJECT)

    详情 :https://mp.weixin.qq.com/debug/wxadoc/dev/api/network-request.html#wxrequestobject 1: 首先要配置你的域名 ...

  4. 《mysql必知必会》读书笔记--安全管理及数据库维护

    安全管理 mysql自带的mysql数据库中的user表可查看用户所有资料 创建用户帐号 CREATE USER ben IDENTIFIED BY 'p@$$wOrd' 重命名用户帐号 RENAME ...

  5. Problem P

    题意:FJ养牛,他想知道中间的牛是那一头: 思路:这道题有点水,思路就不写了 #include #include #include #define maxn 10005 using namespace ...

  6. Paint the Grid Reloaded(缩点,DFS+BFS)

    Leo has a grid with N rows and M columns. All cells are painted with either black or white initially ...

  7. css基础语法三

    []伪类选择器] 1.写法: 伪类选择器,在选择器后面,用:分隔,紧接伪类状态: eg : .a:link 2. 超链接的伪类状态: :link - 未访问状态 :visited - 已访问状态 :h ...

  8. Caused by: org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.security.AccessControlException):

    用windows连接hadoop集群执行mapreduce任务的时候出现以下错误: org.apache.hadoop.security.AccessControlException:Permissi ...

  9. AngularJS学习篇(十四)

    AngularJS 事件 ng-click 指令 ng-click 指令定义了 AngularJS 点击事件. <!DOCTYPE html> <html> <head& ...

  10. Python文件夹备份

    Python文件夹备份 import os,shutil def file_copy(path1,path2): f2 = [filename1 for filename1 in os.listdir ...