nodejs学习笔记1
nodejs本质上其实就是js,只不过是运行的环境不同,当它运行在本地chrome时,它就是客户端文件;当它运行在服务端的时候,它就是nodejs
安装
官网安装(有手就行,不再介绍),检查是否安装,查看版本号:node -v
一个简易的nodejs服务器服务
在命令行启动:node nodetest.js
访问localhost:3000,就可以看到hello world
// nodetest.js
const http = require("http")
const server = http.createServer((req, res) => {
res.write("hello world")
res.end()
})
server.listen(3000) // 设置在哪个端口监听
但是当改变nodetest.js时,就要重新运行启动才可以,这样有点麻烦,这里推荐nodemon模块,可以帮我们自动重启服务,启动命令改成nodemon即可:
安装:npm i -g nodemon
nodemon nodetest.js
[nodemon] 2.0.7
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node nodetest.js`
模块化
// 通过文件引用
// moduleA.js
console.log("moduleA.js")
let a = 10;
let b = 2;
// 1. 使用module.exports导出一个默认的对象
// module.exports = {
// a,
// b
// }
// 2. exports是对module.exports的引用,但不能直接使用exports = {},这种是无效的,只能用下面这种
exports.a = 10;
exports.b = 2;
exports.c = 9;
// index.js
let Ma = require("./moduleA.js")
let { a, b } = require("./moduleA")
console.log(Ma.a)
// 还可以通过目录的方式引用,require会默认查找目录下index.js文件
// ./home/a.js
console.log("a.js")
// ./home/b.js
console.log("b.js")
// ./home/index.js
console.log("index.js")
require("./a")
require("./b")
// ./index.js
require("./home")
第三方模块管理
nodejs会默认有个第三方模块管理的文件夹,node_modules,放在这里的模块,可以直接使用require("模块名")引入
第三方模块一般由npm包管理,官网:npmjs.com
包发布
// 进入自己写的包所在根目录, 运行npm publish,发布之前需要注意的是:
// 1. 注册一个自己的账号;
// 2. npm 包源必需改回为官网:npm config set registry https://registry.npmjs.org/, 查看源: npm config list
npm publish
// 如果要卸载
npm unpublish --fource
常见的内置模块
fs模块
1. 文件操作
const fs = require("fs")
// 一、文件操作
// 所有的文件操作,如果加了Sync就是异步的,如果没加就是同步的
// 1. 读文件
fs.readFile("index.js", "utf8", (err, data) => {
if(err) {
console.log(err)
}else{
console.log(data) // 会发现读出来是二进制文件
console.log(data.toString()) // 1. 使用toString()可以转化成字符串; 2. 在readFile文件里添加第二个参数“utf8”,效果和toString是一样的 fs.readFile("index.js", "utf8",callback)
}
})
// 2. 写文件,第三个参数,可写可不写,用于配置写入的模式: a追加,w写入,r读取
fs.writeFile("test.txt", "我是写入的内容", { flag: "a"}, (err, data) => {
if(err) {
console.log(err)
}
console.log("写入成功")
})
// 3. 重命名
fs.rename("test.txt", "test2.txt", err => {
if(err){
return console.log(err)
}
console.log("修改名称成功")
})
// 4. 删除
fs.unlink("test2.txt", err => {
if(err){
return console.log(err)
}
console.log("删除成功")
})
// 5. 复制
fs.copyFile("test2.txt", "text.txt", err => {
if(err){
return console.log(err)
}
console.log("复制成功")
})
2. 目录操作
const fs = require("fs")
// // 1. 创建目录
fs.mkdir("11", err => {
if(err) {
return console.log(err)
}
console.log("创建目录成功")
})
// // 2. 重命名目录
fs.rename("11", "22", err => {
if(err) {
return console.log(err)
}
console.log("修改目录成功")
})
// 3. 读取目录
fs.readdir("22", (err, data) => {
if(err) {
return console.log(err)
}
console.log("读取目录成功:", data) // 读取目录成功: [ 'index.js', 'moduleA.js', 'nodetest.js' ]
})
// 4. 删除目录(空目录), 删除非空目录,会报错directory not empty
fs.rmdir("11", err => {
if(err) {
return console.log(err)
}
console.log("删除目录成功")
})
3. 判断文件或目录操作
// 如果没有后缀是判断目录,有后缀是判断文件
fs.exists("22", res => {
console.log(res) // true为存在,false为不存在
})
// 判断是文件还是目录
fs.stat("text.txt", (err, stat) => {
if(err) {
return console.log(err)
}
console.log(stat) // 文件或目录的详细信息
// Stats {
// dev: 2087857684,
// mode: 33206,
// nlink: 1,
// uid: 0,
// gid: 0,
// rdev: 0,
// blksize: undefined,
// ino: 39687971716387310,
// size: 21,
// blocks: undefined,
// atimeMs: 1611843826799.901,
// mtimeMs: 1611843756915.7473,
// ctimeMs: 1611843810930.6248,
// birthtimeMs: 1611843826799.901,
// atime: 2021-01-28T14:23:46.800Z,
// mtime: 2021-01-28T14:22:36.916Z,
// ctime: 2021-01-28T14:23:30.931Z,
// birthtime: 2021-01-28T14:23:46.800Z }
console.log(stat.isFile()) // true
console.log(stat.isDirectory()) // false
})
封装一个删除非空目录的方法
function removeDir(path) {
let stat = fs.statSync(path)
if(stat.isDirectory()) {
let data = fs.readdirSync(path) // 返回目录下的文件或目录的数组
for(let i = 0; i < data.length; i++) {
let url = path + '/' + data[i]
// 判断是目录还是文件,如果是文件,直接删除,如果是目录,继续递归处理
let stat = fs.statSync(url)
if(stat.isFile()) {
fs.unlink(url)
}else {
removeDir(url)
}
}
fs.rmdirSync(path)
}else {
console.error("路径:"+ path + "不是文件夹")
}
}
removeDir("text.txt") // 路径:test2.txt不是文件夹
removeDir("11") // 删除成功
buffer类
buffer是js的类,相当于是一个缓冲区,用于创建存储二进制文件,因为二进制在底层运行是相当快的,所以我们往往使用二进制来操作文件
// let buffer = new Buffer() // es6以前的创建方式
// 1. 现在的创建方式,里面的Number是字节为单位
let buffer = Buffer.alloc(10)
console.log(buffer) // <Buffer 00 00 00 00 00 00 00 00 00 00>
// 2. 通过字符串方式去创建
let buffer1 = Buffer.from("大家好") // <Buffer e5 a4 a7 e5 ae b6 e5 a5 bd>, buffer其实是用2进制存储的,只是打印时是以16进制形式展示
buffer1.toString()
// 3. 通过16制度创建
let buffer2 = Buffer.from([0xe5, 0xa4, 0xa7, 0xe5, 0xae, 0xb6, 0xe5, 0xa5, 0xbd])
console.log(buffer2.toString()) // 大家好
// 4. 通过concat拼接
let buffer3 = Buffer.from([0xe5, 0xa4, 0xa7, 0xe5]) // 一般三个16进度代表一个中文字符串
console.log(buffer3.toString()) // 乱码: 大�
let buffer4 = Buffer.from([0xae, 0xb6, 0xe5, 0xa5, 0xbd])
console.log(buffer4.toString()) // 乱码: ��好
let newBuffer = Buffer.concat([buffer3, buffer4])
console.log(newBuffer.toString()) // 大家好
// 5. 使用StringDecoder去解码buffer
let { StringDecoder } = require("string_decoder");
let decoder = new StringDecoder()
let res1 = decoder.write(buffer3)
let res2 = decoder.write(buffer4)
console.log(res1, res2) // 大 家好
// 如果我们读取文件时,不指定编码,实际上返回的就是一个buffer的数据
const fs = require("fs")
const res = fs.readFileSync("1.txt")
console.log(res) // <Buffer 61 61 61 62 62 62>
stream流
如果文件比较小,那么直接读取整个文件是没问题的;但是如果很大,比如说2g,这时一次性去读取,很容易直接内存挂掉,所以就有了分流的出现,流会把文件分成64kb的小文件传输
const fs = require("fs")
const res = fs.createReadStream("1.txt")
res.on("data", chunk => {
console.log(chunk.toString()) // aaabbb
})
// 文件小时看出不出效果,也没必要;创建一个大一点的试验
// 创建一个65kb的文件
let buffer = Buffer.alloc(65 * 1024) // 65kB
fs.writeFile("65kb", buffer, err => {
if(err) return console.log(err)
console.log("写入成功")
})
// 创建完后,再运行读取的操作,会发现将文件分成两个stream,每个64kb,因为如果使用64kb文件,就只会分一个;65就会分两个
let res1 = fs.createReadStream("65kb")
res1.on("data", chunk => {
console.log(chunk)
// <Buffer 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... >
// <Buffer 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... >
})
let res1 = fs.createReadStream("1.txt")
let str = ''
// data是监听传输过程
res1.on("data", chunk => {
console.log(chunk)
str += chunk.toString()
// <Buffer 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... >
// <Buffer 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... >
})
// end是监听传输结束
res1.on("end", () => {
console.log(str)
})
使用nodejs原生写法实现一个服务器
// 最简单版
const http = require("http");
const server = http.createServer((req, res) => {
res.write("hello world")
res.end()
})
server.listen(3000)
改写,针对不同的路由,请求不同的页面
- 使用url.parse解析url地址的pathname和query
- 对不同的pathname,返回不同的文件
- 如果要对query进行什么处理,都可以在判断里做处理
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>我是主页</h1>
</body>
</html>
<!-- detail.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>我是详情页</h1>
</body>
</html>
const http = require("http")
const fs = require("fs")
const url = require('url')
const server = http.createServer((req, res) => {
console.log(req.url)
// 1. /
// 2. /favicon.ico 这个是title的那个图标地址
res.setHeader('content-type', 'text/html;charset=utf8') // 设置头信息
// res.write("hello world1111")
let urlPath = url.parse(req.url, true) // 带true会将query以对象形式返回
// console.log(urlPath); // 会发现 pathname是真正的地址,query中会存放参数
let pathname = urlPath.pathname // /detail
let query = urlPath.query // { name: 'hahah' }
// 改为写入特定的页面内容,如果使用全等的方式(req.url === '/detial'),会发现实际带参的路由(http://localhost:3000/detail?name=hahah)是不能识别的,所以要借助url模块解析下路由地址
if(pathname === '/') {
let home = fs.readFileSync("./index.html")
res.write(home)
}else if(pathname === '/detail') {
if(query.name) {
res.write(fs.readFileSync('./detail.html'))
}else {
res.write("缺少想要查看的用户名,无法展示详情页")
}
// 实现接口返回数据
}else if(pathname === '/getData') {
let obj = {
name: "hahaha",
age: 18
}
res.write(JSON.stringify(obj))
}
res.end()
})
server.listen(3000) // 设置在哪个端口监听
加载外部的资源文件
在主页中加入外部资源,.css和.js文件,在浏览器的network中,选择全部资源all,可以查看到请求的css和js、图片等资源。在引入资源时,头部要设置成相应的类型,否则文件是不生效的;
- mime文件类型文件,可百度查询mime,然后copy下来,整理成json文件,并引入
- 使用path模块,解析路由url中的文件后缀名,只要不是/favicon.ico,就判断后缀,并添加对应的头部类型
- 与html页面一样,外部资源文件同样要通过res.write的方式写入
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>我是主页</h1>
</body>
</html>
/* ./assets/home.css */
body {
background: yellow;
}
// ./assets/home.js
console.log("我是主页引入的js文件")
// nodejs服务器
const http = require("http")
const fs = require("fs")
const url = require('url')
const path = require("path") // 这里用于解析文件后缀
const mime = require("./assets/mime.json") // 注意,这里json引入会自动将其转化成对象,不需要再次进行转换
const server = http.createServer((req, res) => {
console.log(req.url)
// 1. /
// 2. /favicon.ico 这个是title的那个图标地址
res.setHeader('content-type', 'text/html;charset=utf8') // 设置头信息
// res.write("hello world1111")
let urlPath = url.parse(req.url, true) // 带true会将query以对象形式返回
// console.log(urlPath); // 会发现 pathname是真正的地址,query中会存放参数
let pathname = urlPath.pathname
let query = urlPath.query
// console.log(pathname) // /detail
// console.log(query) // { name: 'hahah' }
// 改为写入特定的页面内容,如果使用全等的方式(req.url === '/detial'),会发现实际带参的路由(http://localhost:3000/detail?name=hahah)是不能识别的,所以要借助url模块解析下路由地址
if(pathname === '/') {
let home = fs.readFileSync("./index.html")
res.write(home)
}else if(pathname === '/detail') {
console.log(query.name)
if(query.name) {
res.write(fs.readFileSync('./detail.html'))
}else {
res.write("缺少想要查看的用户名,无法展示详情页")
}
// 实现接口
}else if(pathname === '/getData') {
let obj = {
name: "hahaha",
age: 18
}
res.write(JSON.stringify(obj))
}else {
// 只要不是图标,就可以初步判断为外部资源
if(pathname !== "/favicon.ico") {
let ext = path.extname(pathname)
console.log(ext);
res.setHeader('content-type', mime[ext]) // 根据不同后缀,设置了对应头部类型
let viewData = fs.readFileSync("." + pathname) // 写入资源文件,注意要加./,不能直接写文件名,这是commonjs的规范
res.write(viewData)
}
}
res.end()
})
server.listen(3000) // 设置在哪个端口监听
mine.json文件
{
".323": "text/h323",
".3gp": "video/3gpp",
".aab": "application/x-authoware-bin",
".aam": "application/x-authoware-map",
".aas": "application/x-authoware-seg",
".acx": "application/internet-property-stream",
".ai": "application/postscript",
".aif": "audio/x-aiff",
".aifc": "audio/x-aiff",
".aiff": "audio/x-aiff",
".als": "audio/X-Alpha5",
".amc": "application/x-mpeg",
".ani": "application/octet-stream",
".apk": "application/vnd.android.package-archive",
".asc": "text/plain",
".asd": "application/astound",
".asf": "video/x-ms-asf",
".asn": "application/astound",
".asp": "application/x-asap",
".asr": "video/x-ms-asf",
".asx": "video/x-ms-asf",
".au": "audio/basic",
".avb": "application/octet-stream",
".avi": "video/x-msvideo",
".awb": "audio/amr-wb",
".axs": "application/olescript",
".bas": "text/plain",
".bcpio": "application/x-bcpio",
".bin ": "application/octet-stream",
".bld": "application/bld",
".bld2": "application/bld2",
".bmp": "image/bmp",
".bpk": "application/octet-stream",
".bz2": "application/x-bzip2",
".c": "text/plain",
".cal": "image/x-cals",
".cat": "application/vnd.ms-pkiseccat",
".ccn": "application/x-cnc",
".cco": "application/x-cocoa",
".cdf": "application/x-cdf",
".cer": "application/x-x509-ca-cert",
".cgi": "magnus-internal/cgi",
".chat": "application/x-chat",
".class": "application/octet-stream",
".clp": "application/x-msclip",
".cmx": "image/x-cmx",
".co": "application/x-cult3d-object",
".cod": "image/cis-cod",
".conf": "text/plain",
".cpio": "application/x-cpio",
".cpp": "text/plain",
".cpt": "application/mac-compactpro",
".crd": "application/x-mscardfile",
".crl": "application/pkix-crl",
".crt": "application/x-x509-ca-cert",
".csh": "application/x-csh",
".csm": "chemical/x-csml",
".csml": "chemical/x-csml",
".css": "text/css",
".cur": "application/octet-stream",
".dcm": "x-lml/x-evm",
".dcr": "application/x-director",
".dcx": "image/x-dcx",
".der": "application/x-x509-ca-cert",
".dhtml": "text/html",
".dir": "application/x-director",
".dll": "application/x-msdownload",
".dmg": "application/octet-stream",
".dms": "application/octet-stream",
".doc": "application/msword",
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
".dot": "application/msword",
".dvi": "application/x-dvi",
".dwf": "drawing/x-dwf",
".dwg": "application/x-autocad",
".dxf": "application/x-autocad",
".dxr": "application/x-director",
".ebk": "application/x-expandedbook",
".emb": "chemical/x-embl-dl-nucleotide",
".embl": "chemical/x-embl-dl-nucleotide",
".eps": "application/postscript",
".epub": "application/epub+zip",
".eri": "image/x-eri",
".es": "audio/echospeech",
".esl": "audio/echospeech",
".etc": "application/x-earthtime",
".etx": "text/x-setext",
".evm": "x-lml/x-evm",
".evy": "application/envoy",
".exe": "application/octet-stream",
".fh4": "image/x-freehand",
".fh5": "image/x-freehand",
".fhc": "image/x-freehand",
".fif": "application/fractals",
".flr": "x-world/x-vrml",
".flv": "flv-application/octet-stream",
".fm": "application/x-maker",
".fpx": "image/x-fpx",
".fvi": "video/isivideo",
".gau": "chemical/x-gaussian-input",
".gca": "application/x-gca-compressed",
".gdb": "x-lml/x-gdb",
".gif": "image/gif",
".gps": "application/x-gps",
".gtar": "application/x-gtar",
".gz": "application/x-gzip",
".h": "text/plain",
".hdf": "application/x-hdf",
".hdm": "text/x-hdml",
".hdml": "text/x-hdml",
".hlp": "application/winhlp",
".hqx": "application/mac-binhex40",
".hta": "application/hta",
".htc": "text/x-component",
".htm": "text/html",
".html": "text/html",
".hts": "text/html",
".htt": "text/webviewhtml",
".ice": "x-conference/x-cooltalk",
".ico": "image/x-icon",
".ief": "image/ief",
".ifm": "image/gif",
".ifs": "image/ifs",
".iii": "application/x-iphone",
".imy": "audio/melody",
".ins": "application/x-internet-signup",
".ips": "application/x-ipscript",
".ipx": "application/x-ipix",
".isp": "application/x-internet-signup",
".it": "audio/x-mod",
".itz": "audio/x-mod",
".ivr": "i-world/i-vrml",
".j2k": "image/j2k",
".jad": "text/vnd.sun.j2me.app-descriptor",
".jam": "application/x-jam",
".jar": "application/java-archive",
".java": "text/plain",
".jfif": "image/pipeg",
".jnlp": "application/x-java-jnlp-file",
".jpe": "image/jpeg",
".jpeg": "image/jpeg",
".jpg": "image/jpeg",
".jpz": "image/jpeg",
".js": "application/x-javascript",
".jwc": "application/jwc",
".kjx": "application/x-kjx",
".lak": "x-lml/x-lak",
".latex": "application/x-latex",
".lcc": "application/fastman",
".lcl": "application/x-digitalloca",
".lcr": "application/x-digitalloca",
".lgh": "application/lgh",
".lha": "application/octet-stream",
".lml": "x-lml/x-lml",
".lmlpack": "x-lml/x-lmlpack",
".log": "text/plain",
".lsf": "video/x-la-asf",
".lsx": "video/x-la-asf",
".lzh": "application/octet-stream",
".m13": "application/x-msmediaview",
".m14": "application/x-msmediaview",
".m15": "audio/x-mod",
".m3u": "audio/x-mpegurl",
".m3url": "audio/x-mpegurl",
".m4a": "audio/mp4a-latm",
".m4b": "audio/mp4a-latm",
".m4p": "audio/mp4a-latm",
".m4u": "video/vnd.mpegurl",
".m4v": "video/x-m4v",
".ma1": "audio/ma1",
".ma2": "audio/ma2",
".ma3": "audio/ma3",
".ma5": "audio/ma5",
".man": "application/x-troff-man",
".map": "magnus-internal/imagemap",
".mbd": "application/mbedlet",
".mct": "application/x-mascot",
".mdb": "application/x-msaccess",
".mdz": "audio/x-mod",
".me": "application/x-troff-me",
".mel": "text/x-vmel",
".mht": "message/rfc822",
".mhtml": "message/rfc822",
".mi": "application/x-mif",
".mid": "audio/mid",
".midi": "audio/midi",
".mif": "application/x-mif",
".mil": "image/x-cals",
".mio": "audio/x-mio",
".mmf": "application/x-skt-lbs",
".mng": "video/x-mng",
".mny": "application/x-msmoney",
".moc": "application/x-mocha",
".mocha": "application/x-mocha",
".mod": "audio/x-mod",
".mof": "application/x-yumekara",
".mol": "chemical/x-mdl-molfile",
".mop": "chemical/x-mopac-input",
".mov": "video/quicktime",
".movie": "video/x-sgi-movie",
".mp2": "video/mpeg",
".mp3": "audio/mpeg",
".mp4": "video/mp4",
".mpa": "video/mpeg",
".mpc": "application/vnd.mpohun.certificate",
".mpe": "video/mpeg",
".mpeg": "video/mpeg",
".mpg": "video/mpeg",
".mpg4": "video/mp4",
".mpga": "audio/mpeg",
".mpn": "application/vnd.mophun.application",
".mpp": "application/vnd.ms-project",
".mps": "application/x-mapserver",
".mpv2": "video/mpeg",
".mrl": "text/x-mrml",
".mrm": "application/x-mrm",
".ms": "application/x-troff-ms",
".msg": "application/vnd.ms-outlook",
".mts": "application/metastream",
".mtx": "application/metastream",
".mtz": "application/metastream",
".mvb": "application/x-msmediaview",
".mzv": "application/metastream",
".nar": "application/zip",
".nbmp": "image/nbmp",
".nc": "application/x-netcdf",
".ndb": "x-lml/x-ndb",
".ndwn": "application/ndwn",
".nif": "application/x-nif",
".nmz": "application/x-scream",
".nokia-op-logo": "image/vnd.nok-oplogo-color",
".npx": "application/x-netfpx",
".nsnd": "audio/nsnd",
".nva": "application/x-neva1",
".nws": "message/rfc822",
".oda": "application/oda",
".ogg": "audio/ogg",
".oom": "application/x-AtlasMate-Plugin",
".p10": "application/pkcs10",
".p12": "application/x-pkcs12",
".p7b": "application/x-pkcs7-certificates",
".p7c": "application/x-pkcs7-mime",
".p7m": "application/x-pkcs7-mime",
".p7r": "application/x-pkcs7-certreqresp",
".p7s": "application/x-pkcs7-signature",
".pac": "audio/x-pac",
".pae": "audio/x-epac",
".pan": "application/x-pan",
".pbm": "image/x-portable-bitmap",
".pcx": "image/x-pcx",
".pda": "image/x-pda",
".pdb": "chemical/x-pdb",
".pdf": "application/pdf",
".pfr": "application/font-tdpfr",
".pfx": "application/x-pkcs12",
".pgm": "image/x-portable-graymap",
".pict": "image/x-pict",
".pko": "application/ynd.ms-pkipko",
".pm": "application/x-perl",
".pma": "application/x-perfmon",
".pmc": "application/x-perfmon",
".pmd": "application/x-pmd",
".pml": "application/x-perfmon",
".pmr": "application/x-perfmon",
".pmw": "application/x-perfmon",
".png": "image/png",
".pnm": "image/x-portable-anymap",
".pnz": "image/png",
".pot,": "application/vnd.ms-powerpoint",
".ppm": "image/x-portable-pixmap",
".pps": "application/vnd.ms-powerpoint",
".ppt": "application/vnd.ms-powerpoint",
".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
".pqf": "application/x-cprplayer",
".pqi": "application/cprplayer",
".prc": "application/x-prc",
".prf": "application/pics-rules",
".prop": "text/plain",
".proxy": "application/x-ns-proxy-autoconfig",
".ps": "application/postscript",
".ptlk": "application/listenup",
".pub": "application/x-mspublisher",
".pvx": "video/x-pv-pvx",
".qcp": "audio/vnd.qcelp",
".qt": "video/quicktime",
".qti": "image/x-quicktime",
".qtif": "image/x-quicktime",
".r3t": "text/vnd.rn-realtext3d",
".ra": "audio/x-pn-realaudio",
".ram": "audio/x-pn-realaudio",
".rar": "application/octet-stream",
".ras": "image/x-cmu-raster",
".rc": "text/plain",
".rdf": "application/rdf+xml",
".rf": "image/vnd.rn-realflash",
".rgb": "image/x-rgb",
".rlf": "application/x-richlink",
".rm": "audio/x-pn-realaudio",
".rmf": "audio/x-rmf",
".rmi": "audio/mid",
".rmm": "audio/x-pn-realaudio",
".rmvb": "audio/x-pn-realaudio",
".rnx": "application/vnd.rn-realplayer",
".roff": "application/x-troff",
".rp": "image/vnd.rn-realpix",
".rpm": "audio/x-pn-realaudio-plugin",
".rt": "text/vnd.rn-realtext",
".rte": "x-lml/x-gps",
".rtf": "application/rtf",
".rtg": "application/metastream",
".rtx": "text/richtext",
".rv": "video/vnd.rn-realvideo",
".rwc": "application/x-rogerwilco",
".s3m": "audio/x-mod",
".s3z": "audio/x-mod",
".sca": "application/x-supercard",
".scd": "application/x-msschedule",
".sct": "text/scriptlet",
".sdf": "application/e-score",
".sea": "application/x-stuffit",
".setpay": "application/set-payment-initiation",
".setreg": "application/set-registration-initiation",
".sgm": "text/x-sgml",
".sgml": "text/x-sgml",
".sh": "application/x-sh",
".shar": "application/x-shar",
".shtml": "magnus-internal/parsed-html",
".shw": "application/presentations",
".si6": "image/si6",
".si7": "image/vnd.stiwap.sis",
".si9": "image/vnd.lgtwap.sis",
".sis": "application/vnd.symbian.install",
".sit": "application/x-stuffit",
".skd": "application/x-Koan",
".skm": "application/x-Koan",
".skp": "application/x-Koan",
".skt": "application/x-Koan",
".slc": "application/x-salsa",
".smd": "audio/x-smd",
".smi": "application/smil",
".smil": "application/smil",
".smp": "application/studiom",
".smz": "audio/x-smd",
".snd": "audio/basic",
".spc": "application/x-pkcs7-certificates",
".spl": "application/futuresplash",
".spr": "application/x-sprite",
".sprite": "application/x-sprite",
".sdp": "application/sdp",
".spt": "application/x-spt",
".src": "application/x-wais-source",
".sst": "application/vnd.ms-pkicertstore",
".stk": "application/hyperstudio",
".stl": "application/vnd.ms-pkistl",
".stm": "text/html",
".svg": "image/svg+xml",
".sv4cpio": "application/x-sv4cpio",
".sv4crc": "application/x-sv4crc",
".svf": "image/vnd",
".svh": "image/svh",
".svr": "x-world/x-svr",
".swf": "application/x-shockwave-flash",
".swfl": "application/x-shockwave-flash",
".t": "application/x-troff",
".tad": "application/octet-stream",
".talk": "text/x-speech",
".tar": "application/x-tar",
".taz": "application/x-tar",
".tbp": "application/x-timbuktu",
".tbt": "application/x-timbuktu",
".tcl": "application/x-tcl",
".tex": "application/x-tex",
".texi": "application/x-texinfo",
".texinfo": "application/x-texinfo",
".tgz": "application/x-compressed",
".thm": "application/vnd.eri.thm",
".tif": "image/tiff",
".tiff": "image/tiff",
".tki": "application/x-tkined",
".tkined": "application/x-tkined",
".toc": "application/toc",
".toy": "image/toy",
".tr": "application/x-troff",
".trk": "x-lml/x-gps",
".trm": "application/x-msterminal",
".tsi": "audio/tsplayer",
".tsp": "application/dsptype",
".tsv": "text/tab-separated-values",
".ttf": "application/octet-stream",
".ttz": "application/t-time",
".txt": "text/plain",
".uls": "text/iuls",
".ult": "audio/x-mod",
".ustar": "application/x-ustar",
".uu": "application/x-uuencode",
".uue": "application/x-uuencode",
".vcd": "application/x-cdlink",
".vcf": "text/x-vcard",
".vdo": "video/vdo",
".vib": "audio/vib",
".viv": "video/vivo",
".vivo": "video/vivo",
".vmd": "application/vocaltec-media-desc",
".vmf": "application/vocaltec-media-file",
".vmi": "application/x-dreamcast-vms-info",
".vms": "application/x-dreamcast-vms",
".vox": "audio/voxware",
".vqe": "audio/x-twinvq-plugin",
".vqf": "audio/x-twinvq",
".vql": "audio/x-twinvq",
".vre": "x-world/x-vream",
".vrml": "x-world/x-vrml",
".vrt": "x-world/x-vrt",
".vrw": "x-world/x-vream",
".vts": "workbook/formulaone",
".wav": "audio/x-wav",
".wax": "audio/x-ms-wax",
".wbmp": "image/vnd.wap.wbmp",
".wcm": "application/vnd.ms-works",
".wdb": "application/vnd.ms-works",
".web": "application/vnd.xara",
".wi": "image/wavelet",
".wis": "application/x-InstallShield",
".wks": "application/vnd.ms-works",
".wm": "video/x-ms-wm",
".wma": "audio/x-ms-wma",
".wmd": "application/x-ms-wmd",
".wmf": "application/x-msmetafile",
".wml": "text/vnd.wap.wml",
".wmlc": "application/vnd.wap.wmlc",
".wmls": "text/vnd.wap.wmlscript",
".wmlsc": "application/vnd.wap.wmlscriptc",
".wmlscript": "text/vnd.wap.wmlscript",
".wmv": "audio/x-ms-wmv",
".wmx": "video/x-ms-wmx",
".wmz": "application/x-ms-wmz",
".wpng": "image/x-up-wpng",
".wps": "application/vnd.ms-works",
".wpt": "x-lml/x-gps",
".wri": "application/x-mswrite",
".wrl": "x-world/x-vrml",
".wrz": "x-world/x-vrml",
".ws": "text/vnd.wap.wmlscript",
".wsc": "application/vnd.wap.wmlscriptc",
".wv": "video/wavelet",
".wvx": "video/x-ms-wvx",
".wxl": "application/x-wxl",
".x-gzip": "application/x-gzip",
".xaf": "x-world/x-vrml",
".xar": "application/vnd.xara",
".xbm": "image/x-xbitmap",
".xdm": "application/x-xdma",
".xdma": "application/x-xdma",
".xdw": "application/vnd.fujixerox.docuworks",
".xht": "application/xhtml+xml",
".xhtm": "application/xhtml+xml",
".xhtml": "application/xhtml+xml",
".xla": "application/vnd.ms-excel",
".xlc": "application/vnd.ms-excel",
".xll": "application/x-excel",
".xlm": "application/vnd.ms-excel",
".xls": "application/vnd.ms-excel",
".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
".xlt": "application/vnd.ms-excel",
".xlw": "application/vnd.ms-excel",
".xm": "audio/x-mod",
".xml":"application/xml",
".xmz": "audio/x-mod",
".xof": "x-world/x-vrml",
".xpi": "application/x-xpinstall",
".xpm": "image/x-xpixmap",
".xsit": "text/xml",
".xsl": "text/xml",
".xul": "text/xul",
".xwd": "image/x-xwindowdump",
".xyz": "chemical/x-pdb",
".yz1": "application/x-yz1",
".z": "application/x-compress",
".zac": "application/x-zaurus-zac",
".zip": "application/zip",
".json": "application/json"
}
通过流方式加载资源
注意,使用流方式加载资源性能会更优一点,但是就不需要res.end()这个语句了,所以其它页面的res.end()就要写在对应的判断上
if(...) {
....
res.end()
}else if(pathname !== "/favicon.ico") {
let ext = path.extname(pathname)
console.log(ext);
res.setHeader('content-type', mime[ext])
// let viewData = fs.readFileSync("." + pathname)
// res.write(viewData)
let rs = fs.createReadStream("." + pathname) // 注意,使用流方式后,res.end()就不需要了,但是其它页面还是需要的
rs.pipe(res)
}
// ...
// res.end()
restful规范
- 程序或应用的事物都应该被抽象为资源
- 每个资源对应唯一的URI
- 使用统一接口对资源进行操作
- 对资源的各种操作不会改变资源标识
- 所有操作都是无状态的
错误的用法:
// localhost:8000/getUser
// localhost:8000/addUser
// localhost:8000/deleteUser
// localhost:8000/updateUser
正确的用法:
// localhost:8000/user // get请求
// localhost:8000/user // post
// localhost:8000/user // delete
// localhost:8000/user // put
模板引擎
模板引擎就是web应用中动态生成html的工具,常见的模板引擎有:ejs、jade(现更名为pug)、handlebars、nunjucks、swig等,使用模板引擎可以使项目结构更加清晰,结构更加合理,让项目维护变得简单
// index.js
const Koa = require("koa")
const Router = require("koa-router")
const views = require("koa-views")
let app = new Koa()
let router = new Router()
// __dirname是内置的属性,表示当前目录的路径
app.use(views(__dirname+"/views"), {
map: {
html: "pug"
}
})
router.get("/", async ctx => {
// ctx.body = "hello"
// 注意,要写上async和await,因为渲染是异步的,需要时间显示的,如果不写await,可能会报Not Found错误
await ctx.render('index.pug')
})
app.use(router.routes())
app.listen(4000)
//- views/index.pug
doctype html
html(lang='en')
head
title pug测试
style.
.mydiv{
width: 200px;
height: 50px;
background: yellow;
}
body
h1 我是标题
p 我是标签,使用缩进方式来表示层级,这里p和h1是同一级元素
div 我是div
div(class="mydiv") 我是类名为mydiv的div
.mydiv2(style={width:"100px", height:"100px", background:"red"}) 我是类名为mydiv2的简写div,带有行内样式
#myid 我是有id的div
//- 这是单行注释,在网页源码中不可见,如果是纯文本,前面需要加|表示原样输出,不然会渲染成标签来显示或是不显示
| Jade is a terse and simple
//-
这是多行注释
多行注释
多行注释
// 这是html注释,在网页源码中可见
- let str = "定义变量"
p #{str}
p 要获取data的数据:#{data}
//- 1. 使用each循环
ul
each item,index in list
li 姓名是:#{item.name},年龄是:#{item.age},下标是:#{index}
//- 2. 使用for循环
div
- for(let i = 0; i < list.length; i ++)
p 姓名是:#{list[i].name},年龄是:#{list[i].age},下标是:#{i}
//- 复用样式
mixin useDiv
div 我是非常常用的div
+useDiv
+useDiv
//- 复用方法
mixin pet(name,hobby)
p 这是一只#{name},爱#{hobby}
- for(let i = 0; i< 3; i++)
+pet("狗狗","飞球")
//- script标签
script(type='text/javascript').
console.log(1111)
console.log(2222)
//- 调用公共模板
include common.pug
//- views/index.pug
h1 我是公共的尾部模板