文件模块

创建Node.js命令行项目

备注:package.json要一样,即所有依赖的版本要一致,github中的文档也查阅对应版本

初始化项目

  • 新建一个空项目
  • 进入这个项目,运行yarn init -y 初始化项目,它会创建一个package.json文件,将版本号改为0.0.1
  • 创建一个index.js在里面写代码,并运行它console.log('Hello!Node.js')
  • node index就可以运行
  • 接下来要做一个命令行程序,类似:

image.png

Commander.js

  • 我们需要借助一个库Commander.js,安装这个库:yarn add commander
  • 如何使用这个库呢? CRM学习法,直接复制文档中可运行的代码
const program = require('commander');
const pkg = require('./package.json')  




// `.version()`方法可以设置版本
program  





   .version(pkg.version)
 
program





  .option('-d, --debug', 'output extra debugging')
  .option('-s, --small', 'small pizza size')
  .option('-p, --pizza-type <type>', 'flavour of pizza');

program.parse(process.argv);

当我们试着运行node index -h,结果显示:

image.png

-h 是哪里来的?

  • CRM学习法,接着我们去尝试修改代码
const  program  = require('commander');
const pkg = require('./package.json')  
  




program  





    .version(pkg.version)





program





    .option('-x, --xxx', 'what the x ???')

program.parse(process.argv);

运行结果:

image.png

说明option就是用来声明命令行有哪些选项,-h显而易见是使用commander默认自带的,只要使用-h就会输出命令行有哪些选项

  • 接着观察文档中的代码,我们不妨在index.js中console.log(program.opts().xxx)

image.png

运行node index,结果显示:

image.png

运行node index -xnode index --xxx,结果显示:

image.png

说明这个选项就像一个开关,只要运行命令行的时候只要写了-x对应的--xxx就有了,到这里node就可以运行index.js 后面可以跟-x 或 --xxx 选项,即能接收用户传的参数了

  • 如何让命令支持子命令?即 node index add?不妨去看下文档,文档中在标题为Commands的地方就有有关子命令的代码,CRM学习法,粘贴过来,运行它
const  program  = require('commander');



const pkg = require('./package.json')  




  




program  





    .version(pkg.version)








program





    .option('-x, --xxx', 'what the x ???')



program



    .command('clone <source> [destination]')
    .description('clone a repository into a newly created directory')
    .action((source, destination) => {
        console.log('clone command called');
    });



program.parse(process.argv);

program有一个选项叫-x;它还有一个子命令叫clone,它的描述是.description,它的作用是.action

命令行中运行代码

image.png

这次除了显示options之外,还多了一个Commands下的clone子命令

打印add命令提示

接着用CRM学习法,修改代码,把clone改为add试一试!

备注: 通过读文档知道,如何给命令添加多个参数

program
   .option('-c, --compress [percentage]') // 0 或 1 个参数
   .option('--preprocess <file...>') // 至少 1 个参数
   .option('--test [name...]') // 0 或多个参数
const  program  = require('commander');



const pkg = require('./package.json')  




  




program  





    .version(pkg.version)








program





    .option('-x, --xxx', 'what the x ???')



program



    .command('add <taskName> [other...]')


    .description('add a task')


    .action(() => {
        console.log("Hi!!!")
    });



program.parse(process.argv);

image.png

尝试用一下吧!!

image.png

如何输出用户使用add子命令添加的多个任务名呢?

const  program  = require('commander');



const pkg = require('./package.json')  




  




program  





    .version(pkg.version)








program





    .option('-x, --xxx', 'what the x ???')



program



    .command('add <taskName> [other...]')


    .description('add a task')


    .action((x,y) => {

        const words = x + " " + y.join(" ")

        console.log(words)

    });




program.parse(process.argv);

image.png

备注: 如果真的遇到报错,也不用慌,观察报错信息和查阅github中的文档去试着修改代码,打log,去解决!!!

打印clear 命令提示

  • 再添加一个clear的子命令吧!
const  program  = require('commander');



const pkg = require('./package.json')  




  




program  





    .version(pkg.version)








program





    .option('-x, --xxx', 'what the x ???')



program



    .command('add <taskName> [other...]')


    .description('add a task')


    .action((x,y) => {

        const words = x + " " + y.join(" ")

        console.log(words)

    });




program
    .command('clear [all]')
    .description('clear all tasks')
    .action(() => {
        console.log('this is clear')
    });

program.parse(process.argv);

image.png

实现创建任务功能add

如果是命令行程序,它的入口文件不应该叫index.js,把它改为cli.js(command line)

再新建一个index.js,这个index.js就是我们提供的所有功能,如add、clear功能

看下拆分后的文件

// cli.js

const  program  = require('commander');
const pkg = require('./package.json')  
const api = require("./index.js")


program  

   .version(pkg.version)
program

    .option('-x, --xxx', 'what the x ???')

program

    .command('add <taskName> [other...]')

    .description('add a task')

    .action((x,y) => {

        const words = x + " " + y.join(" ")

        api.add(words)

    });



program

    .command('clear [all]')

    .description('clear all tasks')

    .action(() => {

        console.log('this is clear')

    });



program.parse(process.argv);





// index.js

module.exports.add = (title) => {
    console.log('add')
}

现在要想一下如何实现add的功能呢?

我们应该将add的内容放到数据库中,但是没有数据库,推荐将add的内容放到用户的Home目录~

Node.js如何获取到用户的Home目录呢?Google一下:node.js get home directory,CRM学习法,先抄代码运行一下

const homedir = require('os').homedir();

image.png

但是home目录用于是可以在环境变量中配置的,因此我们最好获取用户的home变量,Google一下:node.js get home variable,CRM学习法,先抄代码运行一下

const HOME = process.env.HOME;
  • 接着我们要在Home目录中创建文件,存储add的内容todo(查API:devdocs.io/)

在window中用\表示路径,在mac和os中用/表示路径,还要使用//、/\转义符转义

那么怎么兼容多个系统的写法呢?

node.js提供了一个方法,专门用来拼路径,home.todo之间不用加任何斜杠,它会根据不同的系统帮我们加不同的斜杠

const p = require("path")
const dbPath = p.join(home,'.todo')
  • fs.readFile的文档:

image.png

options中的encoding一般不写,默认是utf-8

flag是什么呢?点击下devdocs中的链接

image.png

读文件如果用a+的模式读,读文件内容并可以往里面追加内容,如果没有文件,默认会帮我们创建文件,这个好像更加符合我们的需求

得到的结果放到回调的参数中,一个是error,另外一个是data,data有可能是string也有可能是buffer,不如统一转成string

const homedir = require('os').homedir();



const home = process.env.HOME || homedir;



const p = require("path")



const dbPath = p.join(home,'.todo')
const fs = require('fs')



module.exports.add = (title) => {



    // 读取之前的任务



    fs.readFile(dbPath,{flag: 'a+'},(err,data) => {
        console.log(data.toString())
    })
    // 往里面添加一个 title任务
    // 存储任务文件
}

执行node cli add xxx,得到的内容是一个回车(空文件默认内容是回车)

image.png

执行start ~ 打开根目录,home目录下创建了文件

image.png

这样我们已经可以通过readFile,读取到之前的任务了

  • 如果我们发现读取文件的内容是空的,我们需要创建一个空数组用来存储任务todo
const homedir = require('os').homedir();



const home = process.env.HOME || homedir;



const p = require("path")



const dbPath = p.join(home, '.todo')


const fs = require('fs')



module.exports.add = (title) => {



    // 读取之前的任务



    fs.readFile(dbPath, {flag: 'a+'}, (error, data) => {


        if (error) {


            console.log(error)


        } else {


            let list


            try {


                list = JSON.parse(data.toString())


            }catch (error2){
                list = []


            }


            console.log(list)
        }
    })
    // 往里面添加一个 title任务
    // 存储任务文件
}

image.png

  • 接着,我们就可以往里面放todo了
const homedir = require('os').homedir();



const home = process.env.HOME || homedir;



const p = require("path")



const dbPath = p.join(home, '.todo')


const fs = require('fs')



module.exports.add = (title) => {



    // 读取之前的任务



    fs.readFile(dbPath, {flag: 'a+'}, (error, data) => {


        if (error) {


            console.log(error)


        } else {


            let list


            try {


                list = JSON.parse(data.toString())


            } catch (error2) {

                list = []


            }


            const task = {
                title: title,
                done: false
            }
            list.push(task)
            console.log(list)
        }
    })
    // 往里面添加一个 title任务
    // 存储任务文件
}

image.png

  • 接着把它存到todo里面,当然要把list变成字符串,因为文件里只能存字符串

查 devdocs 文档fs.writeFile(),'[]’表示参数可以不传

image.png

const homedir = require('os').homedir();



const home = process.env.HOME || homedir;



const p = require("path")



const dbPath = p.join(home, '.todo')


const fs = require('fs')



module.exports.add = (title) => {



    // 读取之前的任务



    fs.readFile(dbPath, {flag: 'a+'}, (error, data) => {


        if (error) {


            console.log(error)


        } else {


            let list


            try {


                list = JSON.parse(data.toString())


            } catch (error2) {

                list = []


            }


            // 往里面添加一个 title任务
            const task = {
                title: title,
                done: false
            }
            list.push(task)
            // 存储任务文件
            const string = JSON.stringify(list)
            fs.writeFile(dbPath,string,(error3) => {
                if(error3){
                    console.log(error3)
                }
            })
            console.log(list)
        }
    })
    
    
}

我们可以通过cat ~/.todo看下文件中的内容,当前是空的

我们使用add子命令添加一个todo试一下

image.png

到这里说明我们的add命令已经可以使用了!!!

封装优化代码

代码如果可以优化成下面的代码就完美了!!

module.exports.add = (title) => {

    // 读取之前的任务





    const list = db.read()

    // 往里面添加一个 title任务
    list.push({title, done: false})

    // 存储任务文件
    db.write(list)

下面正式优化代码吧

新建一个文件db.js

  • 接下来,删除todo文件rm ~/.todo

  • 测试下add命令是否可用 node cli add 买水

image.png

完整代码:

// cli.js

const program = require('commander');
const api = require("./index.js")
const pkg = require('./package.json')


program  

    .version(pkg.version)
program

    .option('-x, --xxx', 'what the x ???')

program

    .command('add <taskName> [other...]')

    .description('add a task')

    .action((x,y) => {

        const words = x + " " + y.join(" ")

        api.add(words)

    });



program

    .command('clear [all]')

    .description('clear all tasks')

    .action(() => {

        console.log('this is clear')

    });



program.parse(process.argv);





// index.js

const homedir = require('os').homedir();
const home = process.env.HOME || homedir;
const p = require("path");
const dbPath = p.join(home, '.todo');
const fs = require('fs');
const db = require("./db.js");
// 优化后的代码
module.exports.add = async (title) => {
    // 读取之前的任务
    const list = await db.read()
    // 往里面添加一个 title任务
    list.push({title, done: false})
    // 存储任务文件
    await db.write(list)
}


// db.js
const homedir = require('os').homedir();
const home = process.env.HOME || homedir;
const p = require("path")
const fs = require('fs')
const dbPath = p.join(home, '.todo')

const db = {
    read(path = dbPath) {
        return new Promise((resolve, reject) => {
            fs.readFile(path, {flag: 'a+'}, (error, data) => {
                if (error) {
                    // 如果失败就返回error
                    reject(error)
                } else {
                    let list
                    try {
                        list = JSON.parse(data.toString())
                    } catch (error2) {
                        list = []
                    }
                    // 如果成功就将异步的结果返回到外面
                    resolve(list)
                }
            })
        })
    },
    write(list,path = dbPath) {
        return new Promise((resolve, reject)=>{
            const string = JSON.stringify(list)
            fs.writeFile(dbPath,string,(error) => {
                if(error){
                    reject(error)
                }else{
                    resolve()
                }
            })
        })
    }
}
module.exports = db

注意:

  • 在异步的代码中不能直接return,我们需要使用Promise,成功到的时候使用resolve(list)将结果传告诉外面,失败的时候使用reject(error),将error告诉外面
  • 由于调用db.read()返回的是Promise,于是我们可以使用await,await可以拿到Promise的结果,由于这里使用了await,因此它外面的函数必须标记为async
  • 拆分的文件的思路:将想要的优化后的效果写在index.js中
module.exports.add = (title) => {

    // 1.读取之前的任务
    const list = db.read()

    // 2.往里面添加一个 title任务
    list.push({title, done: false})

    // 3.存储任务文件
    await db.write(list)
  • 添加版本号时需要从package.json中读版本号,这样在node cli.js --version时就可以知道当前命令的版本号了
const pkg = require('./package.json')

program  
    .version(pkg.version)

然后把之前未优化的代码一部分一部分的拆开,这种技巧就是面向接口编程,即先把接口想好,再把代码变成这些接口,代码再怎么复杂别人不想看,只想看上面代码中接口的部分逻辑

消除WebStorm的警告

如何消除webstorm中可恶的下划波浪线?

为什么会有下划波浪线?

因为被标记为下划线的代码,对于webstorm来说根本不知道是从哪里来的,这些被划线的部分,只有在Node.js中才有,但是webstorm并不知道你用的是Node.js

因此我们需要做一些配置

image.png

如果没有相应的Library就点击Download去下载相应的Library

另外还需要删除代码中暗灰色的代码,这些代码是声明了但是没有使用的变量

我们一定要保证IDEA在不该报错的时候一定不要报错,如果有错误,一定要马上改掉,否则如果报错积累多了,就没办法发现哪里是真正的错误

完成所有功能

实现clear清除任务功能

add功能已经实现了,接下来要实现以下clear

我们应该先想一下接口应该是怎样的

program  
    .command('clear [all]')  
    .description('clear all tasks')  
    .action(() => {  
        api.clear()
    });
  • 接下来实现以下clear
module.exports.clear = async() => {  
    await db.write([])  
}

备注:node.js中的代码都是异步的

运行node cli clear就会将~/.todo文件中的内容替换为空数组

实现展示全部任务功能

接下来要实现一个效果:

当用户在命令行输入node cli.js的时候,应该展示所有的任务todo

我们怎么知道用户没有传命令add和clear呢?

我们尝试打印console.log(process.argv)

image.png

也就是说,如果process.argv的长度为2,就说明用户只传了node.exe 和 cli.js 这两个路径作为参数,而没有传子命令,此时就让它展示所有的任务todo

先把接口写好:

if(process.argv.length === 2){
    void api.showAll()
}

备注: void的作用仅仅是为了强制消除webstorm的警告

再写一下showAll的具体逻辑:

module.exports.showAll = async () => {




    // 读取之前的任务





    const list = await db.read()




    // 打印之前的任务
    list.forEach((task,index) => {
        console.log(`${task.title ? '[✘]': '[✔]'}${index + 1} - ${task.title}`)
    })
}

尝试添加任务,并使用node cli.js来展示当前的全部任务todo

image.png

实现用户对任务打✔ 和 打 ✘

我们应该给用户一个可选择的列表,让用户可以自己选择选项,做了就打✔,没做就打✘

我们需要借助一个库来做列表:github.com/SBoudrias/I…

使用CRM学习法,copy能运行的代码

先安装这个库

yarn add @inquirer/prompts

copy 能运行的例子

如下图所示中的example

image.png

看下运行的效果:

image.png

CRM学习法第二步: 改代码

module.exports.showAll = async () => {




    // 读取之前的任务





    const list = await db.read()




    inquirer.prompt(
        {
            type: "list",
            name: "index",
            message: "请选择你想操作的任务",
            choices: list.map((task, index) => {
                return `${task.title ? '[✘]' : '[✔]'}${index + 1} - ${task.title}`
            })
        })
        .then(answer => {
            console.log(answer.index)
        })
}

image.pngimage.png

选择之后得到的结果不是我们想要的,我们只想要下标index,choices是不是有其他写法?
选择的内容是[✘]1 - 买水,但是得到的值是下标index?

去文档中搜关键字choices

image.png

从文档中可以看出choices的可以是数组,数组的值可以是name,value形式的对象

我们尝试让name是内容,value是index

module.exports.showAll = async () => {




    // 读取之前的任务





    const list = await db.read()




    inquirer.prompt({


        type: "list",


        name: "index",


        message: "请选择你想操作的任务",


        choices: list.map((task, index) => {
            return {name:`${task.title ? '[✘]' : '[✔]'}${index + 1} - ${task.title}`,value:index.toString()}

        })
    }).then(answer => {


        console.log(answer.index)


    })


}


image.png

image.png

那么如果用户不想选择怎么办?

加个退出功能

给用户加个退出

module.exports.showAll = async () => {




    // 读取之前的任务





    const list = await db.read()




    inquirer.prompt({


        type: "list",


        name: "index",


        message: "请选择你想操作的任务",


        choices: [{name: '退出',value: '-1'},...list.map((task, index) => {
            return {name:`${task.title ? '[✘]' : '[✔]'}${index + 1} - ${task.title}`,value:index.toString()}

        })]
    }).then(answer => {


        console.log(answer.index)


    })


}


image.png

支持对话状态时创建、修改、删除任务

如果用户既不想选择又不想退出,而是想添加todo,每次还要退出运行node cli add xxx,太麻烦

选择列表中再加一个可以添加任务的选项

module.exports.showAll = async () => {




    // 读取之前的任务





    const list = await db.read()




    inquirer.prompt({


        type: "list",


        name: "index",


        message: "请选择你想操作的任务",


        choices: [{name: '退出', value: '-1'}, ...list.map((task, index) => {
            return {name: `${task.title ? '[✘]' : '[✔]'}${index + 1} - ${task.title}`, value: index.toString()}
        }), {name: '+ 新增任务', value: '-2'}]
    }).then(answer => {


        console.log(answer.index)


    })


}


image.png

image.png

先将问答列表做好,接下来根据用户选择index的值,执行后续的逻辑

完整代码:

const db = require("./db.js");

const inquirer = require("inquirer");

// 优化后的代码
module.exports.add = async (title) => {
    // 读取之前的任务
    const list = await db.read()
    // 往里面添加一个 title任务
    list.push({title, done: false})
    // 存储任务文件
    await db.write(list)
}

module.exports.clear = async () => {
    await db.write([])
}



module.exports.showAll = async () => {
    // 读取之前的任务
    const list = await db.read()
    inquirer.prompt({
        type: "list",
        name: "index",
        message: "请选择你想操作的任务",
        // 用户可以选择退出、对选择的todo任务打✔✘,新增任务
        choices: [{name: '退出', value: '-1'}, ...list.map((task, index) => {
            return {name: `${task.done ? '[✔]' : '[✘]'}${index + 1} - ${task.title}`, value: index.toString()}
        }), {name: '+ 新增任务', value: '-2'}]
    }).then(answer => {
        const index = parseInt(answer.index)
        if (index >= 0) {
            // 选择了一个todo任务
            inquirer.prompt({
                type: "list",
                name: "action",
                message: "选择操作",
                // 如果选择了一个todo任务,用户可以选择退出、标记todo任务已完成、未完成、删除、修改标题和退出
                choices: [
                    {name: '退出', value: 'quit'},
                    {name: '已完成', value: 'markAsDone'},
                    {name: '未完成', value: 'markAsUndone'},
                    {name: '改标题', value: 'updateTitle'},
                    {name: '删除', value: 'remove'},

                ]
            }).then(answer2 => {
                // 对用户的选择执行步同的业务处理
                switch (answer2.action) {
                    case 'markAsDone':
                        list[index].done = true
                        db.write(list)
                        break;
                    case 'markAsUndone':
                        list[index].done = false
                        db.write(list)
                        break;
                    case 'updateTitle':
                        inquirer.prompt({
                            type: 'input',
                            name: 'title',
                            message: "新的标题",
                        }).then((answer) => {
                            list[index].title = answer.title
                            db.write(list)
                        });
                        break;
                    case 'remove':
                        // 从下标index删除一个
                        list.splice(index, 1)
                        db.write(list)
                        break;
                }
            })
        } else if (index === -1) {
            // 选择了退出
        } else if (index === -2) {
            // 创建任务
            inquirer.prompt({
                type: 'input',
                name: 'title',
                message: "输入任务标题",
            }).then((answer) => {
                list.push({
                    title: answer.title,
                    done: false
                })
                db.write(list)
            });
        }
    })
}

备注:修改标题时,要让用户输入要修改的标题,因此要去文档中查input相关的example

image.png

再次封装优化代码

把一堆代码取一个恰当的名字(函数),然后调用它

const db = require("./db.js");

const inquirer = require("inquirer");


// 创建任务
module.exports.add = async (title) => {
    // 读取之前的任务
    const list = await db.read()
    // 往里面添加一个 title任务
    list.push({title, done: false})
    // 存储任务文件
    await db.write(list)
}

// 清除任务
module.exports.clear = async () => {
    await db.write([])
}

// 打印全部的任务
module.exports.showAll = async () => {
    // 读取之前的任务
    const list = await db.read()
    printTasks(list)
}

// 打印全部任务todoList
function printTasks(list) {
    inquirer.prompt({
        type: "list",
        name: "index",
        message: "请选择你想操作的任务",
        // 用户可以选择退出、对选择的todo任务打✔✘,新增任务
        choices: [{name: '退出', value: '-1'}, ...list.map((task, index) => {
            return {name: `${task.done ? '[✔]' : '[✘]'}${index + 1} - ${task.title}`, value: index.toString()}
        }), {name: '+ 新增任务', value: '-2'}]
    }).then(answer => {
        const index = parseInt(answer.index)
        if (index >= 0) {
            askForAction(index, list)
        } else if (index === -1) {
            // 选择了退出
        } else if (index === -2) {
            askForCreateTask(list)
        }
    })
}

// 选择了一个todo任务
function askForAction(index, list) {
    const actions = {markAsDone, markAsUndone, updateTitle, remove}
    inquirer.prompt({
        type: "list",
        name: "action",
        message: "选择操作",
        // 如果选择了一个todo任务,用户可以选择退出、标记todo任务已完成、未完成、删除、修改标题和退出
        choices: [
            {name: '退出', value: 'quit'},
            {name: '已完成', value: 'markAsDone'},
            {name: '未完成', value: 'markAsUndone'},
            {name: '改标题', value: 'updateTitle'},
            {name: '删除', value: 'remove'},

        ]
    }).then(answer2 => {
        // 对用户的选择执行步同的业务处理
        const action = actions[answer2.action]
        action && action(list,index)
    })
}

// 询问创建任务
function askForCreateTask(list){
    inquirer.prompt({
        type: 'input',
        name: 'title',
        message: "输入任务标题",
    }).then((answer) => {
        list.push({
            title: answer.title,
            done: false
        })
        void db.write(list)
    });
}
// 任务标记已完成
function markAsDone(list,index){
    list[index].done = true
    void db.write(list)
}

// 任务标记未完成
function markAsUndone(list,index){
    list[index].done = false
    void db.write(list)
}
// 更新任务标题
function updateTitle(list,index){
    inquirer.prompt({
        type: 'input',
        name: 'title',
        message: "新的标题",
    }).then((answer) => {
        list[index].title = answer.title
        void db.write(list)
    });
}
// 移出任务
function remove(list,index){
    // 从下标index删除一个
    list.splice(index, 1)
    void db.write(list)
}

温馨提示

Webstorm还有一个好用的功能sructure,可以清晰的看清楚当前代码的组织结构,声明了哪些函数,导出了什么函数等

image.png

最终效果

2压缩版2.gif

如何发布到npm

接下来要将代码发布出去,让所有人都可以使用我们的代码

修改package.json

  • 发布的时候name必须是唯一的
  • cli.js是给命令行使用的代码,main.js才是todo工具的逻辑部分代码
  • cli.js变成note命令

image.png

  • cli.js要加一个shebang,它的作用是告诉命令行要用node来执行代码
    #!/usr/bin/env node

  • cli.js必须是可执行文件,方法是在当前项目命令行中执行下面的代码:chmod +x cli.js

image.png

  • 发布之前要告诉npm哪些文件是要上传的,因此要修改"files:["*js"]"

image.png

运行命令行

  • 可以使用npm发布也可以使用yarn发布
  • 发布之前一定要将淘宝源切回到原始源,因为taobao源是不接受你publish的文件的,只有原始源才接受

nrm use npm

  • 使用npm adduser 登录npm ,提示one-time-password的时候意思是要输入一次性的密码,会发到注册时的邮箱,输入即可

image.png

  • 接着我们就可以使用npm publish发布我们的包文件了

  • 如果报下面的错,可能是我们的包名已经存在了

image.png

得到下面的提示,就表示包发布成功了!

image.png

如下图所示,在npm账号里已经有发布的包了!
image.png

任何人都可以使用发布的工具了

使用

yarn global add node-notebook-reagen

遇到的问题

但是运行 note时,发现找不到命令note

微信图片_20230621185303.png

使用绝对路径可以调到

e8b3021d17097eb7c9aeacc19209a27.png

或者配置路径

运行npm -g bin,打印npm将要安装可执行文件的文件夹,将结果中的路径配置到系统环境变量中

image.png

全局安装

当在命令行中运行npm i node-notebook-reagen -g全局安装时,就会将下载的包文件放到E:\Node\node_global\node_modules中(路径E:\Node\node_global是配置的环境变量path)

image.png

当运行note时, 实际上运行的是node cli.js

image.png

Node就会到E:\Node\node_global\node_modules\node-notebook-reagen中找到对应的cli.js执行

image.png

运行结果:

image.png

局部安装

当在命令行中运行npm i node-notebook-reagen 局部安装时,会就会将下载的包文件放到F:\cs\node_modules

image.png

当运行note时, 实际上运行的是node cli.js

image.png

Node就会到F:\cs\node_modules\node-notebook-reagen中找到对应的cli.js执行

image.png

运行结果:

image.png

项目地址

npm包安装

github地址

改版

修改完代码后,记得修改package.json中的版本号,同时重新发布新的版本npm publish绝对不可以把同一个版本publish两次

用户如果要更新版本运行

npm i node-notebook-reagen@lastest选择自己想安装的版本即可

常见错误

  • 发布的包名跟线上包名重复,不允许发布,请改名
  • 用户名和密码不匹配,请重置密码
  • 没有改版本号,不能重复发布同一版,请升级版本
  • 其他问题自行Google

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYaafghp' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片