Node.js 如何使用
引用
https://www.bilibili.com/video/BV1QT4y1A7NR?p=1
https://www.bilibili.com/video/BV17z4y1D7Yj?p=520&spm_id_from=pageDriver
一、了解Node.js
Node.js® is a JavaScript runtime built on Chrome’s V8 JavaScript engine.
Node.js 是一个开源和跨平台的 JavaScript 运行时环境,运行在服务器端。可以解析js代码,没有浏览器安全级别的限制,提供了很多系统级别的API。
简单的说Node.js 就是运行在服务端的JavaScript
- 文件读写 File System
- 进程的管理 process
- 网络通信 HTTP/HTTPS
二、安装Nodejs
1.安装nvm-nodejs版本管理工具
使用nvm网址
http://nvm.uihtm.com/
如果之前有node,且没有安装nvm,先卸载原来的nodejs,再安装nvm。
2.nvm命令
查看可安装版本
nvm list available
安装指定版本node
nvm install 版本号
安装完选择要使用的node 版本
nvm use 版本号
node 运行js文件
node 文件名
3.nvm常见问题
1.下载慢
如果下载node过慢,请更换国内镜像源, 在 nvm 的安装路径下,找到 settings.txt,设置node_mirro与npm_mirror为国内镜像地址。下载就飞快了~~
root: D:\nvm
path: D:\nodejs
注意npm淘宝镜像地址有更换,不好使记得更换最新
node_mirror: https://npmmirror.com/mirrors/node/
npm_mirror: https://npmmirror.com/mirrors/npm/
2.nvm安装node拒绝访问
使用 nvm use 版本号
,查看node -v
拒绝访问,需要注意安装路径,必须安装到D:/ 下,nvm 和nodejs 路径都要在D盘下。
3.nvm 运行node 报错exit 中文乱码
升级nvm版本后报错。1.1.7升级1.1.8
用管理员运行cmd。
或者卸载用1.1.7版本
4.安装nodemon -实时侦测文件
cnpm install nodemon -g
-g全局安装
启动文件:
nodemon 文件名
5.安装淘宝镜像 cnpm
cnpm 属于国内
npm install -g cnpm --registry=https://registry.npmmirror.com
-g 全局安装
三、Nodejs模块
nodejs 要使用自定义模块需要按照 CommonJs规范
。
1.使用内置模块
在官网查看API ,可以直接引用对应的内置模块
const os =require("os");
console.log(os.hostname());
2.使用第三方模块
先初始化文件夹 npm init
生成package.json 文件,安装第三方模块,引入模块即可。
初始化npm
npm init
加载package.json 文件下的包
npm install / npm i
3.使用自定义模块
一个js文件就是一个模块,先定义模块,再引用模块。
注意: 调用自定义模块在引用路径是加上 ./
告诉系统是引用本地,在本级也要加。因为不加上,系统会先从内置模块寻找,再到第三方寻找,再到自定义模块寻找,这样做会节约时间。
四、模块使用
1.fs - 文件读写
./ 的意思是本地,可以写可以不写
const fs =require("fs");
fs.writeFile("./log.txt","fs文件读写",(err,data) =>{
if(err){
}else{
console.log("文件写入成功")
}
})
2.process -进程操作
console.log(process.argv);
3.http -通信协议
可以通过node 创建个server
const http=require("http");
const server= http.createServer((request,response) =>{
let url= request.url
response.write(url)
response.end()
});
server.listen(8090,"localhost",()=>{
console.log("localhost:8090")
})
五、npm使用
1.npm版本号和命令
package.json 里面的版本号符号 npm管理版本号
npm清理缓存
npm cache clean --force
查看npm的下载源
npm config get registry
设置源
npm config set registry 网址
2.创建自己的包并发版到npm
发版publish 自己的包
3.给npm 换源
换到淘宝的,相当于安装了cnpm。
六、npm 脚本
npm脚本 写在package.json 文件中的 scripts 下面
运行npm脚本命令
npm run 自定义脚本名称
1.运行文件
一个 & 符号同时运行两个文件时,是并行运行, 有可能1先运行,有可能2先运行
"runjs":"node ./xxx1.js & node ./xxx2.js"
两个 & 符号 是串行,先执行前面的,再执行后面的文件
"runjs":"node ./xxx1.js && node ./xxx2.js"
2.简写命令 start、test
"start": "node ./xxx.js",
"test": "echo \"Error: no test specified\" && exit 1",
运行这两个简写命令不用加 run
npm start
npm test
3.npm 查看package.json 自定义内容
想要查看package.json 文件的 属性内容,需要固定的前缀 process.env.npm_package_
后面跟想要查看的对象和属性
console.log(process.env.npm_package_config_age);
注意:
要查看package.json 文件里的内容,运行查看的js文件,必须要用scripts运行。要在脚本环境访问变量
4.npm 安装github或gitee 包
5.cross-env 跨平台工具
6.nrm 管理npm的下载源
7.npx
npx的作用:
1.如果本地有安装的包,就会调用本地的包,不用全局安装
2.如果本地没有,会安装到一个虚拟环境,用一次之后就会删除,不占内存。
七、内置模块
log4js 日志包
npm install log4js -D
配置
const log4js = require("log4js");
log4js.configure({
appenders: { cheese: { type: "file", filename: "cheese.log" } },
categories: { default: { appenders: ["cheese"], level: "error" } }
});
const logger = log4js.getLogger("cheese");
logger.trace("Entering cheese testing");
logger.debug("Got cheese.");
logger.info("Cheese is Comté.");
logger.warn("Cheese is quite smelly.");
logger.error("Cheese is too ripe!");
logger.fatal("Cheese was breeding ground for listeria.");
1.url
const url=require("url");
const log4js = require("log4js");
// const logger = log4js.getLogger();
log4js.configure({
appenders: { cheese: { type: "file", filename: "cheese.log" } },
categories: { default: { appenders: ["cheese"], level: "error" } }
});
const logger = log4js.getLogger("cheese");
logger.level = "debug";
logger.debug("Some debug messages");
const urlString="https://www.baidu.com:445/path/index.xml?id=2#tag=3"
const urlObj={
protocol: 'https:',
slashes: true,
auth: null,
host: 'www.baidu.com:445',
port: '445',
hostname: 'www.baidu.com',
hash: '#tag=3',
search: '?id=2',
query: 'id=2',
pathname: '/path/index.xml',
path: '/path/index.xml?id=2',
href: 'https://www.baidu.com:445/path/index.xml?id=2#tag=3'
}
// logger.debug(url.parse(urlString));
logger.debug(url.format(urlObj))
logger.debug(url.resolve("https://www.baidu.com/a","/b"))
2.querystring 查询字符串
querystring 模块提供了用于解析和格式化网址查询字符串的实用工具
.stringify 用于格式化字符串
querystring.stringify({ foo: 'bar', baz: ['qux', 'quux'], corge: '' });
// Returns 'foo=bar&baz=qux&baz=quux&corge='
querystring.stringify({ foo: 'bar', baz: 'qux' }, ';', ':');
// Returns 'foo:bar;baz:qux'
querystring.unescape(str)方法在给定的 str 上执行网址百分比编码字符的解码
3.http
通过get在后面拉取接口
-https.request(options,()=>{})
https.request(options,(result)=>{})
第一个参数是options,是请求参数。第二个参数是返回值,可以用箭头函数进行操作。
request方法会返回一个request,需要接收
request可以做get post 等等
-http response
response.writeHead(statusCode[, statusMessage][, headers])
向请求发送响应头。 状态码是 3 位的 HTTP 状态码,如 404。 最后一个参数 headers 是响应头。 可选地给定人类可读的 statusMessage 作为第二个参数。
headers 可以是 Array,其中键和值在同一个列表中。 它不是元组列表。 因此,偶数偏移是键值,奇数偏移是关联的值。 该数组的格式与 request.rawHeaders 相同。
返回对 ServerResponse 的引用,以便可以链式调用。
response.writeHead(200, {
'Content-Length': Buffer.byteLength(body),
'Content-Type': 'text/plain'
})
response.end([data[, encoding]][, callback])
此方法向服务器发出信号,表明所有响应头和正文都已发送;该服务器应认为此消息已完成。 response.end() 方法必须在每个响应上调用。
5.跨域jsonp
跨域:浏览器请求其他域名的js、jpg等文件不会触发同源策略。如果通过ajax请求接口则会触发同源策略
6.跨域cors
const http = require('http')
const url = require('url')
const server= http.createServer((request,response)=>{
let urlStr=request.url
let urlObj=url.parse(urlStr,true)
switch (urlObj.pathname) {
case '/api/data':
response.writeHead(200,{
'content-type':'applicatio/json',
'Access-Control-Allow-Origin': '*'
})
response.write('{"ret":"true","data":"hellp"}')
break;
default:
response.write('page not find')
break;
}
response.end()
})
server.listen(8080,()=>{
console.log('localhost:8080')
})
7.跨域-通过代理去访问别人端口middleware http-proxy-middleware
const http =require('http');
const url=require('url')
const {createProxyMiddleware}=require('http-proxy-middleware')
const server= http.createServer((request,response)=>{
const urlStr =request.url
if(/\/ajax_new/.test(urlStr)){
// console.log(urlStr)
const proxy= createProxyMiddleware('/ajax_new',{
target:'http://www.jumeiglobal.com',
changeOrigin:true
})
proxy(request,response)
}else{
console.log('error')
}
})
server.listen(8080,()=>{
console.log('localhost:8080')
})
8.events
events 自定义事件
事件可以重名,就会触发两次
//调用events模块,返回一个类
const EventEmitter= require("events")
//编写一个类,继承返回的得到的类
class MyEventEmitter extends EventEmitter{
}
//实例化
const event =new MyEventEmitter()
//通过on绑定事件,自定义一个方法,命名为play,通过回调函数获取值
event.on('play',(value)=>{
console.log(value)
})
//用 emit 方法使用 play 事件
event.emit('play','history');
9.fs 文件操作
async:异步
sync:同步
有的方法后面加上这两个单词,表示此方法可以同步异步
//调用 fs 模块,进行文件读写操作
const fs =require("fs");
//使用 mkdir 创建文件夹.第一个参数是文件名,第二个参数是回调函数,里面可以传入error : err
fs.mkdir('logs',(err)=>{
if(err) throw err
console.log('文件夹创建成功')
})
//使用 fs.rename 修改文件名,fs.rename(oldPath, newPath, callback)
fs.rename('./logs','./log',()=>{
console.log('文件名修改成功')
})
//使用 fs.rmdir(path[, options], callback),删除文件夹,
fs.rmdir('./log',()=>{
console.log('done')
})
//使用 fs.readdir(path[, options], callback) 读取文件目录
fs.readdir('./log',(err,result)=>{
console.log(result)
})
//使用 fs.appendFile(path, data[, options], callback)
//异步地将数据追加到文件,如果该文件尚不存在,则创建该文件。 data 可以是字符串或 <Buffer>。
fs.appendFile('./log/log.txt',',后添加文字!!!',()=>{
console.log('添加成功');
})
//使用 fs.readFile(path[, options], callback),第二个参数可选:如果不设置字符格式,读取的是buffer。或者用toString()
fs.readFile('./log/log.txt',"utf-8",(err,content)=>{
console.log(content);
})
fs.readFile('./log/log.txt',(err,content)=>{
console.log(content.toString());
})
-fs/promise 异步API
promise:承诺
fs/promise API ,返回promise的异步操作
//使用 fs/promises 异步操作文件,返回promise
;(async ()=>{
let result = await fsPromises.readFile('./log/log.txt')
console.log(result.toString())
})()
-循环读取目录
//循环创建文件
// for(var i=0;i<=6;i++){
// fs.writeFile(`./log/log-${i}.txt`,`第${i}个log文件`,()=>{
// console.log("done.")
// })
// }
//读取目录下的文件
function readDir(dir){
fs.readdir(dir,(err,content)=>{
//循环遍历文件
content.forEach((value,index)=>{
let joinDir=`${dir}/${value}`;
fs.stat(joinDir,(err,stats)=>{
if(stats.isDirectory()){
readDir(joinDir)
}else{
fs.readFile(joinDir,'utf-8',(err,content)=>{
console.log(content)
})
}
})
})
})
}
readDir('./');
-fs.watch 监听某个文件
//观测文件 fs.watch
fs.watch('./log/log-0.txt',(err)=>{
console.log('file has changed')
})
-zlib 压缩、读取流和写入流
// 引入所需的包
const fs = require('fs')
const zlib = require('zlib')
const gzip = zlib.createGzip()
//创建流
const readStream = fs.createReadStream('./log.txt')
const writeStream = fs.createWriteStream('./log2.txt')
//复制文件
readStream //获取到内容
.pipe(gzip) //使用压缩
.pipe(writeStream) //写入文件
-readLine 逐行读取
输入功能
//引入模块
const readline=require('readline')
//创建读取接口
const rl =readline.createInterface({
input:process.stdin,
output:process.stdout
})
//输入
rl.question('输入内容',(answer)=>{
console.log(`你输入的是:${answer}`)
rl.close()
})
10.crypto 加密
const crypto =require('crypto')
const password='abc123'
const hash= crypto
.createHash('sha1') //定义加密算法,得到hash
.update(password) //定义加密对象,可选字符格式
.digest('hex') // 加密进制
console.log(hash)
11.路由
什么是路由:
Node.js 路由(router) 提供了 URL 请求路径到 Node.js 方法的一一映射机制
通过request从前端截取路径,从前拿数据用request。 想给前端发送数据,通过response 发送给前端
const fs =require('fs')
const mime = require('mime')
//http.createServer 创建服务
require('http').createServer((request,response)=>{
//获取请求路径
const urlString =request.url
console.log(urlString)
//通过mime 获取路径的后缀,写到请求头里
const type=mime.getType(urlString.split('.')[1])
response.writeHead(200,{
'content-type':type
})
//根据输入的路径 读取文件,注意填写的文件路径
const file= fs.readFileSync(`.${urlString}`)
//输入读取文件
response.end(file)
// switch (urlString) {
// case '/':
// response.end('hello')
// break
// case '/home':
// fs.readFile('./home.html',(err,content)=>{
// response.end(content)
// })
// break
// case '/app.js':
// fs.readFile('./app.js',(err,content)=>{
// response.end(content)
// })
// break
// case '/color_bg_3.jpeg':
// fs.readFile('./color_bg_3.jpeg',(err,content)=>{
// response.end(content)
// })
// break;
// default:
// console.log('page of 404')
// break
// }
}).listen(8080,()=>{
console.log('localhost:8080')
})
12.静态资源目录
13.path
-path.jion()
用途:拼接目录路径
path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');
// 返回: '/foo/bar/baz/asdf'
-path.parse()
解析路径返回 path 对象
path.parse('/home/user/dir/file.txt');
// 返回:
// { root: '/',
// dir: '/home/user/dir',
// base: 'file.txt',
// ext: '.txt',
// name: 'file' }
*练习静态资源目录
server.js
const http = require('http')
const path = require('path')
const readStaticFile = require('./readStaticFile');
http.createServer(async (req, res) => {
let urlString = req.url
const filePath = path.join(__dirname, '/public', urlString)
console.log(filePath);
let { mimeType, data } = await readStaticFile(filePath)
console.log(mimeType)
res.writeHead(200, {
'content-type': `${mimeType};charset=utf-8`
})
res.write(data)
res.end()
}).listen(8080, () => console.log('localhost:8080'))
readStaticFile.js
const path = require('path')
const mime = require('mime')
const fs = require('fs')
//根据获取的路径读取文件
function readGetFile(file) {
return new Promise((resolve, reject) => {
fs.readFile(file, (err, data) => {
if (err) {
resolve('你返回的是文件夹,且没有index.html文件')
} else {
resolve(data)
}
})
})
}
//读取文件返回流
async function readStaticFile(filePathName) {
let ext = path.parse(filePathName).ext
let mimeType = mime.getType(ext) || 'text/html'
let data
//判断文件是否存在
if (fs.existsSync(filePathName)) {
//判断是文件夹还是文件
if (ext) {
// readGetFile(filePathName)
// .then(result=> data=result)
// .catch(err => data=err)
data = await readGetFile(filePathName)
} else {
// readGetFile(path.join(filePathName,'/index.html'))
// .then(result=> data=result)
// .catch(err => data=err)
data = await readGetFile(path.join(filePathName, '/index.html'))
}
} else {
data = 'file not found'
}
return {
mimeType,
data
}
}
//抛出方法
module.exports = readStaticFile
八、第三方模块
1.mime
mime.getType() 获取文件的后缀 得到 content-type
mime.getExtension 通过content-type 得到文件名后缀
mime.getType('txt'); // ⇨ 'text/plain'
mime.getExtension('text/plain'); // ⇨ 'txt'
九、yarn
Yarn 是一个软件包管理器,还可以作为项目管理工具。
安装yarn需要先安装nodejs
初始化项目,创建package.json 文件
yarn init -y
查看yarn的源
yarn config get registry
设置源
yarn config set registry 网址