『壹』 nodejs中require的路径是一个文件夹时发生了什么
在引用文件模块的时候后要加上文件的路径:/.../.../xxx.js表示回绝对路径答、./xxx.js表示相对路径(同一文件夹下的xxx.js),../表示上一级目录。
如果既不加/.../、../又不加./的话,则该模块要么是核心模块,要么是从一个node_moles文件夹加载。
『贰』 nodejs调用文件时为什么前面加点和斜杠
点和斜杠 表示路径前缀。写完整路径(绝对路径)是一件繁琐的事情,所以大家都喜欢用相对路径表示(也就是点和斜杠作为前缀),例如:./app/main.js----表示项目文件夹下的app/main.js 文件,而绝对路径可能是:D:/workplace/testProject/app/main.js。
“./“ 这里可以代表 “D:/workplace/testProject/“ 从而使得路径简化,其实“./”可以代表任何路劲前缀,也就是不用管路径有多长多深,它都只表示当前项目文件夹下的文件。
『叁』 nodejs安装不上,怎么回事
下载nodejs引擎,32bit version或者64bit version
下载最新版的npm zip格式压缩包:http://nodejs.org/dist/npm/
在硬盘某个位置,如D盘下建立一个文件nodejs,把上面两个下载的东西都放在这里,npm要解压。
配置两个环境变量:一个是PATH上增加node.exe的目录D:\\nodejs,一个是增加环境变量NODE_PATH,值为D:\\nodejs\\node_moles。
win7环境配置在系统》高级系统设置》高级》环境变量》系统变量中查找PATH,编辑加上D:\\nodejs,再加上NODE_PATH变量和值。
安装express:打开cmd命令行,使用命令行定位到这Node目录下,键入指令npm install express[安装express至相对路径]或npm install express -g[安装express至绝对路径]
到这里,你在命令行里面输入node -v如果输出nodejs的版本则安装成功。
更新nodejs的版本可以在命令行中输入: npm update npm -g
『肆』 使用 nodejs 批量给文章添加二维码图片
大家好,我是前端西瓜哥。
因为最近公众号没有涨粉,所以打算给我的个人博客网站(blog.fstars.wang)上的所有文章底部添加公众号的二维码。
为此我打算用 nodejs 写个批量处理文件的简单脚本。
我的具体需求是这样的。
文章都是用 markdown 文件写的,这是一种纯文本的文件格式,并且都位于 posts 文件夹下。
现在我们需要将 所有 markdown 文件的末尾都加上我的公众号二维码图片 ,即加上下面这种格式的内容。
其中有个模板文件,不需要添加图片,所以我们要设置一个 黑名单 。
此外 有些文章已经加了该图片,我们也需要将这些文章排除在外 ,防止文章出现两张相同图片。同时也能防止不小心多次执行脚本,导致不可逆的修改。
我们先看完整的代码。
我们先设置好要用到的几个变量,然后将它们全都放到文件开头。
放到开头是为了让我们在需要时快速修改,符合相关代码高内聚原则。如果这些变量流散在代码逻辑中,当我们要改配置时,就要找上半天。
这里我引入了 nodejs 内置的 fs 库。fs 指的是文件系统(File System),fs 库就是专门用来处理文件的这么一个库。
fs/promise 则是fs 的 promise 版,将原来 fs 方法的回调参数移除,然后返回一个 promise。
我们就用这个 promise 版的 fs,因为它能写出同步形式的代码,可读性会更好。
fs.readdir() 方法能够读取目录内容,返回一个字符串数组,里面是所有的文件名。
接下来我们就去遍历这个数组。这里有个 初学者容易犯的错误,就是会去使用 forEach 方法。
因为 forEach 是 for 循环的一层封装,会执行传入的回调函数。但 forEach 的这个函数并不是 async 函数,所以是无法等待 await 方法执行完的。
async 函数其实是挺新的特性,forEach 则是存在了很长时间,当时 forEach 并没有考虑 async 这种东西,为了兼容,以后也不会。
所以你需要使用原生的 for 循环方法。for 和 for...of 都可以。
然后我们检查一下文件名是否在黑名单中,如果在,跳过此轮循环,直接进入下一轮。
然后我们要将文件名、和它所在的目录名组合,生成一个绝对路径。
直接使用文件名是不行的,因为 脚本会以被执行时所在的工作目录进行路径计算的,文件名是个相对于指定目录的相对路径,相对工作目录不一定是正确的。
接着是使用 fs.readFile 读取文件内容,记住要将 encoding 设置为 'utf8',否则你会拿到一个二进制的内容。
如果文件中已经有图片了,就跳过。
否则在文件末尾通过 fs.appendFile 方法添加图片内容。
脚本写好了,我们准备执行了。
首先为了可以吃后悔药,我强烈建议你想将文件通过版本控制软件(如 git),先存一个档。当脚本配合得不是很好时,我们可以轻松愉快地回滚到修改前的版本。当然拷贝一份作为备份也行。
总之,备份很重要。
改改配置,然后执行。
成功!
大家可以去我的 blog.fstars.blog 看看,现在所有文章下都有这二维码图片了。
『伍』 如何在ubuntu安装nodejs环境
直接在软件库安装:
sudoapt-getinstallnodejs
『陆』 nodejs编译后js文件名前缀
Node.js 是一个基于 Chrome V8 引擎的 javaScript 运行环境。
Node与javaScript的区别在于,javaScript的顶层对象是window,而node是global
//这里使用的var声明的变量不是全局的,是当前模块下的,用global声明的表示是全局的
var s = 100;
global.s = 200;
//这里访问到的s是var生命的
console.log(s); //100
//这里访问到的才是全局变量
console.log(global.s); //200
模块:在node中,文件和模块是一一对应的,也就是一个文件就是一个模块;每个模块都有自己的作用域,我们通过var申明的变量并非全局而是该模块作用域下的。
(2)mole模块
1、文件查找
1)首先按照加载的模块的文件名称进行查找,如果没有找到,则会带上 .js、.json 或 .node 拓展名在加载
2)以 '/' 为前缀的模块是文件的绝对路径。 例如,require('/home/marco/foo.js') 会加载 /home/marco/foo.js 文件。
3)以 './' 为前缀的模块是相对于调用 require() 的文件的。 也就是说,circle.js 必须和 foo.js 在同一目录下以便于 require('./circle') 找到它。
4)当没有以 '/'、'./' 或 '../' 开头来表示文件时,这个模块必须是一个核心模块或加载自 node_moles 目录。
5)如果给定的路径不存在,则 require() 会抛出一个 code 属性为 'MODULE_NOT_FOUND' 的 Error。
2、mole 作用域
在一个模块中通过var定义的变量,其作用域范围是当前模块,外部不能够直接的访问,如果我们想一个模块能够访问另外一个模块中定义的变量,可以有一下两种方式:
1)把变量作为global对象的一个属性,但这样的做法是不推荐的
2)使用模块对象 mole。mole保存提供和当前模块有关的一些信息。
在这个mole对象中有一个子对象exports对象,我们可以通过这个对象把一个模块中的局部变量对象进行提供访问。
//这个方法的返回值,其实就是被加载模块中的mole.exports
require('./02.js');
3、__dirname:当前模块的目录名。
例子,在 /Users/mjr 目录下运行 node example.js:
console.log(__dirname);
// 输出: /Users/mjr
console.log(path.dirname(__filename));
// 输出: /Users/mjr
4、__filename:当前模块的文件名(处理后的绝对路径)。当前模块的目录名可以使用 __dirname 获取。
在 /Users/mjr 目录下运行 node example.js:
console.log(__filename);
// 输出: /Users/mjr/example.js
console.log(__dirname);
// 输出: /Users/mjr
(3)process(进程)
process 对象是一个全局变量,提供 Node.js 进程的有关信息以及控制进程。 因为是全局变量,所以无需使用 require()。
1、process.argv
返回进程启动时的命令行参数。第一个元素是process.execPath。第二个元素是当前执行的JavaScript文件的路径。剩余的元素都是额外的命令行参数。
console.log(process.argv);
打印结果:
2、process.execPath返回启动进程的可执行文件的绝对路径。
3、process.env 返回用户的环境信息。
在process.env中可以新增属性:
process.env.foo = 'bar';
console.log(process.env.foo);
可以通过delete删除属性:
delete process.env.foo;
console.log(process.env);
在Windows上,环境变量不区分大小写
4、process.pid 属性返回进程的PID。
5、process.platform属性返回字符串,标识Node.js进程运行其上的操作系统平台。
6、process.title 属性用于获取或设置当前进程在 ps 命令中显示的进程名字
7、process.uptime() 方法返回当前 Node.js 进程运行时间秒长
注意: 该返回值包含秒的分数。 使用 Math.floor() 来得到整秒钟。
8、process.versions属性返回一个对象,此对象列出了Node.js和其依赖的版本信息。
process.versions.moles表明了当前ABI版本,此版本会随着一个C++API变化而增加。 Node.js会拒绝加载模块,如果这些模块使用一个不同ABI版本的模块进行编译。
9、process对象-输入输出流
var a;
var b;
process.stdout.write('请输入a的值: ');
process.stdin.on('data', (chunk) => {
if (!a) {
a = Number(chunk);
process.stdout.write('请输入b的值:');
}else{
b = Number(chunk);
process.stdout.write('a+b的值:'+(a+b));
process.exit();
}
});
(4)Buffer缓冲器
Buffer类,一个用于更好的操作二进制数据的类,我们在操作文件或者网络数据的时候,其实操作的就是二进制数据流,Node为我们提供了一个更加方便的去操作这种数据流的类Buffer,他是一个全局的类
1、如何创建使用buffer
Buffer.from(array) 返回一个 Buffer,包含传入的字节数组的拷贝。
Buffer.from(arrayBuffer[, byteOffset [, length]]) 返回一个 Buffer,与传入的 ArrayBuffer 共享内存。
Buffer.from(buffer) 返回一个 Buffer,包含传入的 Buffer 的内容的拷贝。
Buffer.from(string[, encoding]) 返回一个 Buffer,包含传入的字符串的拷贝。
Buffer.alloc(size[, fill[, encoding]]) 返回一个指定大小且已初始化的 Buffer。 该方法比 Buffer.allocUnsafe(size) 慢,但能确保新创建的 Buffer 不会包含旧数据。
Buffer.allocUnsafe(size) 与 Buffer.allocUnsafeSlow(size) 返回一个指定大小但未初始化的 Buffer。 因为 Buffer 是未初始化的,可能包含旧数据。
// 创建一个长度为 10、且用 01 填充的 Buffer。
const buf1 = Buffer.alloc(10,1);
// 创建一个长度为 10、且未初始化的 Buffer。
// 这个方法比调用 Buffer.alloc() 更快,但返回的 Buffer 实例可能包含旧数据,因此需要使用 fill() 或 write() 重写。
const buf2 = Buffer.allocUnsafe(10);
const buf3 = Buffer.from([1, 2, 3]);
const buf4 = Buffer.from('tést');
console.log(buf1); //<Buffer 01 01 01 01 01 01 01 01 01 01>
console.log(buf2); //<Buffer 00 00 00 00 08 00 00 00 07 00>
console.log(buf3); //<Buffer 01 02 03>
console.log(buf4); //<Buffer 74 c3 a9 73 74>
2、Buffer对象提供的toString、JSON的使用
1)buf.toString(encoding,start,end)
var bf = Buffer.from('miaov');
console.log(bf.toString('utf-8',1,4)); //iaov
console.log(bf.toString('utf-8',0,5)); //miaov
console.log(bf.toString('utf-8',0,6)); //miaov
2)buf.write(string,offset,length,encoding)
string 要写入 buf 的字符串。
offset 开始写入的偏移量。默认 0,这里指的是buffer对象的起始要写入的位置。
length 要写入的字节数。默认为 buf.length - offset。
encoding string 的字符编码。默认为 'utf8'。
返回: 已写入的字节数。
var str = "miaov hello";
var bf = Buffer.from(str);
var bf2 = Buffer.alloc(8);
//从0开始写入5个
bf2.write(str,0,5);
console.log(bf);
console.log(bf2);
3)buf.toJSON()
const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);
const json = JSON.stringify(buf);
console.log(json);
// 输出: {"type":"Buffer","data":[1,2,3,4,5]}
3、Buffer中静态方法的使用
1)Buffer.isEncoding(encoding) : 判断是否是Buffer支持的字符编码,是则返回true,不是则返回false
console.log(Buffer.isEncoding('utf-8')); //true
2)Buffer.isBuffer(obj) :如果 obj 是一个 Buffer,则返回 true,否则返回 false。
(5)fs(文件系统)
该模块是核心模块,需要使用require('fs')导入后使用,该模块主要用来操作文件
1、fs.open(path, flags, mode, callback)
path:要打开的文件的路径;
flags:打开文件的方式 读/写;
mode:设置文件的模式 读/写/执行
callback(err,fd):文件打开以后,在回调函数中做相应的处理,回调函数的两个参数:
err:文件打开失败的错误保存在err里面,如果成功err为null
fd:被打开文件的标识
var fs = require('fs');
fs.open('./test.txt','r',function(err,fd){
if(err){
console.log("文件打开失败");
}else{
console.log("文件打开成功");
}
});
2、fs.openSync(path, flags, mode) :返回文件描述符。
var fs = require('fs');
console.log(fs.openSync('./test.txt','r')); //3
3、fs.read(fd, buffer, offset, length, position, callback)
从 fd 指定的文件中读取数据;
buffer 指定要写入数据的 buffer;
offset 指定 buffer 中开始写入的偏移量;
length 指定要读取的字节数;
position 指定文件中开始读取的偏移量。 如果 position 为 null,则从文件的当前位置开始读取;
callback 有三个参数 (err, bytesRead, buffer)
示例:test.txt 中的值为123456789
fs.open('./test.txt','r',function(err,fd){
if(!err){
var bf = Buffer.alloc(5);
fs.read(fd,bf,0,5,0,function(){
console.log(bf.toString()); //12345
})
}
});
4、fs.write(fd, buffer, offset, length, position, callback)
将 buffer 写入到 fd 指定的文件。
offset 指定 buffer 中要开始被写入的偏移量,length 指定要写入的字节数。
position 指定文件中要开始写入的偏移量。 如果 typeof position !== 'number',则从当前位置开始写入。
callback 有三个参数 (err, bytesWritten, buffer),其中 bytesWritten 指定 buffer 中已写入文件的字节数。
var fs = require('fs');
fs.open('./test.txt','r+',function(err,fd){
if(!err){
var bf = Buffer.alloc(5);
fs.read(fd,bf,0,5,0,function(){
console.log(bf.toString()); //12345
});
var bf = Buffer.from('test数据');
fs.write(fd,bf,0,10,0);
fs.write(fd,'测试数据2',10,'utf-8');
}
});
fs.write(fd, string, position, encoding, callback)
将 string 写入到 fd 指定的文件。 如果 string 不是一个字符串,则会强制转换成字符串。
position 指定文件中要开始写入的偏移量。 如果 typeof position !== 'number',则从当前位置开始写入。
encoding 指定字符串的编码。
callback 有三个参数 (err, written, string),其中 written 指定字符串中已写入文件的字节数。 写入的字节数与字符串的字符数是不同的。
5、fs.exists(path,callback)检查指定路径的文件或者目录是否存在
fs.appendFile(path, data, callback):将数据追加到文件,如果文件不存在则创建文件。
//检查文件是否存在
var fs = require('fs');
var filename = './test2.txt';
fs.exists(filename,function(isExists){
if(!isExists){
fs.writeFile(filename,'miaov',function(err){
if(err){
console.log("文件创建失败");
}else{
console.log("文件创建成功");
}
});
}else{
fs.appendFile(filename,'-leo',function(err){
if(err){
console.log("文件内容追加失败");
}else{
console.log("文件内容追加成功");
}
})
}
});
(6)前端项目自动化构建
1、创建myProject项目文件以及对应的文件夹
var projectData ={
'name':'myProject',
'fileData':[
{
'name':'css',
'type':'dir'
},{
'name':'js',
'type':'dir'
},{
'name':'images',
'type':'dir'
},{
'name':'index.html',
'type':'file',
'content' : '<html>\n\t<head>\n\t\t<title>title</title>\n\t</head>\n\t<body>\n\t\t<h1>Hello</h1>\n\t</body>\n</html>'
}
]
};
var fs = require('fs');
if(projectData.name){
// 创建项目文件夹
fs.mkdirSync(projectData.name);
var fileData = projectData.fileData;
if(fileData && fileData.length){
fileData.forEach(function(file){
//文件或文件夹路径
file.path = './'+projectData.name +'/'+ file.name;
//根据type类型创建文件或文件夹
file.content = file.content || '';
switch(file.type){
case 'dir':
fs.mkdirSync(file.path);
break;
case 'file':
fs.writeFileSync(file.path,file.content);
break;
default:
break;
}
});
}
}
2、自动打包多个文件
var fs = require('fs');
var filedir = './myProject/dist';
fs.exists(filedir,function(isExists){
if(!isExists){
fs.mkdirSync(filedir);
}
fs.watch(filedir,function(ev,file){
//只要有一个文件发生了变化,我们就需要对文件夹下的所有文件进行读取、合并
fs.readdir(filedir,function(err,dataList){
var arr = [];
dataList.forEach(function(file){
if(file){
//statSync查看文件属性
var info = fs.statSync(filedir + '/' +file);
//mode文件权限
if(info.mode === 33206){
arr.push(filedir + '/' +file);
}
}
});
//读取数组中的文件内容
var content = '';
arr.forEach(function(file){
var c = fs.readFileSync(file);
content += c.toString()+'\n';
});
//合并文件中的内容
fs.writeFileSync('./myProject/js/index.js',content);
})
});
});
(7)使用node进行web开发
1、搭建一个http的服务器,用于处理用户发送的http请求
//加载一个http模块
var http = require('http');
//通过http模块下的createServer创建并返回一个web服务器对象
var server = http.createServer();
//开启 HTTP 服务器监听连接,只有调用了listen方法以后,服务器才开始工作
server.listen(8000,'localhost');
//服务器是否正在监听连接
server.on('listening',function(){
console.log("listening..........");
});
//每次接收到一个请求时触发,每个连接可能有多个请求(在 HTTP keep-alive 连接的情况下)。
server.on('request',function(){
res.write('<p>hello</p>');
res.end();
});
2、request方法有两个参数:request、response
1)request:http.IncomingMessage的一个实例,获取请求的一些信息,如头信息,数据等
httpVession:使用的http协议的版本
headers:请求头信息中的数据
url:请求的地址
method:请求的方式
2)response:http.ServerResponse的一个实例,可以向请求的客户端输出返回响应
write(chunk,encoding):发送一个数据块到相应正文中
end(chunk,encoding):当所有的正文和头信息发送完成以后调用该方法告诉服务器数据已经全部发送完成了,这个方法在每次完成信息发送以后必须调用,并且是最后调用。
statusCode:该属性用来设置返回的状态码
setHeader(name,value):设置返回头信息
writeHead(statusCode,reasonPhrase,headers)这个方法只能在当前请求中使用一次,并且必须在response.end()之前调用
3、使用fs模块实现行为表现分离
var http = require('http');
var url = require('url');
var fs = require('fs');
var server = http.createServer();
//html文件的路径
var htmlDir = __dirname + '/html/';
server.on('request',function(request,response){
var urlStr = url.parse(request.url);
//根据pathname匹配对应的html文件
switch(urlStr.pathname){
case '/':
sendData(htmlDir + 'index.html',request,response);
break;
case '/user':
sendData(htmlDir + 'user.html',request,response);
break;
case '/login':
sendData(htmlDir + 'login.html',request,response);
break;
default:
//处理其他情况
sendData(htmlDir + 'err.html',request,response );
break;
}
});
function sendData(file,request,response){
//读取文件,存在则返回对应读取的内容,不存在则返回错误信息
fs.readFile(file,function(err,data){
if(err){
response.writeHead(404,{
'content-type':'text/html;charset=utf-8'
});
response.end('<h1>页面不存在</h1>')
}else{
response.writeHead(200,{
'content-type':'text/html;charset=utf-8'
});
response.end(data);
}
})
}
server.listen(8000,'localhost');
『柒』 开发中用nodejs做了哪些方面的工作
Node.js使用Mole模块去划分不同的功能,以简化应用的开发。Moles模块有点像C++语言中的类库。每一个Node.js的类库都包含了十分丰富的各类函数,比如http模块就包含了和http功能相关的很多函数,可以帮助开发者很容易地对比如http,tcp/udp等进行操作,还可以很容易的创建http和tcp/udp的服务器。
要在程序中使用模块是十分方便的,只需要如下:
在这里,引入了http类库,并且对http类库的引用存放在http变量中了。这个时候,node.js会在我们应用中搜索是否存在node_moles的目录,并且搜索这个目录中是否存在http的模块。如果node.js找不到这个目录,则会到全局模块缓存中去寻找,用户可以通过相对或者绝对路径,指定模块的位置,比如:
var myMole = require('./myMole.js');
模块中包含了很多功能代码片断,在模块中的代码大部分都是私有的,意思是在模块中定义的函数方法和变量,都只能在同一个模块中被调用。当然,可以将某些方法和变量暴露到模块外,这个时候可以使用exports对象去实现。
『捌』 nodejs怎么在指定文件夹下运行
一、挖坑 & 掉坑:
缘起一段这样的代码:
fs.readFile('./docs/use.md', function (err, buffer) {
if (err) {
return console.log('error: ', err);
}
console.log('OK');
});
本地运行时一切 OK,线上部署时却死活找不到 ./docs/use.md 这个文件,后来才发现是因为线上启动应用时不是从当前目录启动了,不过为什么启动脚本的位置也会影响这个路径呢,且往下看。
二、填坑:
Node 中的文件路径大概有 __dirname, __filename, process.cwd(), ./ 或者 ../,前三个都是绝对路径,为了便于比较,./ 和 ../ 我们通过 path.resolve(‘./’)来转换为绝对路径。
先看一个简单的栗子:
假如我们有这样的文件结构:
app/
-lib/
-common.js
-model
-task.js
-test.js
在 task.js 里编写如下的代码:
var path = require('path');console.log(__dirname);console.log(__filename);console.log(process.cwd());console.log(path.resolve('./'));
在 model 目录下运行 node task.js 得到的输出是:
/Users/guo/Sites/learn/app/model.js/Users/guo/Sites/learn/app/model.js/task.js/Users/guo/Sites/learn/app/model.js/Users/guo/Sites/learn/app/model.js
然后在 app 目录下运行 node model/task.js,得到的输出是:
/Users/guo/Sites/learn/app/model.js/Users/guo/Sites/learn/app/model.js/task.js/Users/guo/Sites/learn/app
/Users/guo/Sites/learn/app
那么,不好意思不是问题来了~T_T,我们可以得出一些肤浅的结论了:
__dirname: 总是返回被执行的 js 所在文件夹的绝对路径
__filename: 总是返回被执行的 js 的绝对路径
process.cwd(): 总是返回运行 node 命令时所在的文件夹的绝对路径
./: 跟 process.cwd() 一样、一样、一样的吗?
我明明记得在 require(‘../lib/common’) 里一直都是各种相对路径写,也没见报什么错啊,我们还在再来个栗子吧,还是上面的结构,’model/task.js’ 里的代码改成:
var fs = require('fs');var common = require('../lib/common');
fs.readFile('../lib/common.js', function (err, data) { if (err) return console.log(err);
console.log(data);
});
在 model 目录下运行 node task.js,一切 Ok,没有报错。然后在 app 目录下运行 node model/task.js,然后很果断滴报错了:
那么这下问题真的都是来了,按照上面的理论,在 app 下运行时,../lib/common.js 会被转成 /Users/guo/Sites/learn/lib/common.js,这个路径显然是不存在的,但是从运行结果可以看出 require(‘../lib/common’) 是 OK 的,只是 readFile 时报错了。
那么关于 ./ 正确的结论是:
在 require() 中使用是跟 __dirname 的效果相同,不会因为启动脚本的目录不一样而改变,在其他情况下跟 process.cwd() 效果相同,是相对于启动脚本所在目录的路径。
三、总结:
只有在 require() 时才使用相对路径(./, ../) 的写法,其他地方一律使用绝对路径,如下:
// 当前目录下
path.dirname(__filename) + ‘/test.js’;
// 相邻目录下
path.resolve(__dirname, ‘../lib/common.js’);
四、参考链接:
What is the difference between __dirname and ./ in node.js
nodejs API
以上:smile:。