目录导航
这是慕课网上的一个视频,这个视频很全面,对于入门学习而言非常友好,谢谢这位老师
第1章 课程内容介绍
导学
章节
- Nodejs核心API
- 静态资源服务器
- 项目代码构建
- 单元测试&UI测试
- headless爬虫
- 回顾总结
基础
- 了解Javascript,ES6语法
- 了解基本的命令行工具
- 基本的HTTP知识
效果
- 了解NodeJS特性和基本使用
- 学习静态资源服务器原理和开发
- 掌握本地代码构建技巧
- 了解常用的测试工具
课程介绍
- NodeJS介绍
- 调试&项目初始化
- 基础API
- 简单的Web Server
- 单元测试&发布
- NodeJS爬虫示例
第2章 NodeJS 是什么,为什么偏爱NodeJS?
NodeJS是什么
阻塞和非阻塞
Nodejs is a Javvscript runtime built on Chrome's V8
Nodejs uses an event-driven,non-blocking I/O model
阻塞:I/O时进程休眠等待I/O完成后进行下一步
非阻塞:I/O时函数立即返回,进程不等待I/O完成
事件驱动
非阻塞
CPU密集 vs I/O密集
CPU密集: 压缩、解压、加密、解密
I/O密集: 文件操作、网络操作、数据库进程:是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位
线程:进程内一个相对独立的,可调度的执行单元,与同属一个进程的线程共享进程的资源
Nodejs工作模型
第3章 环境& 调试
环境
- CommonJS
- Global
- process
调试
node --inspect-brk filename
chrome://inspect
CommonJS
- 每个文件是一个模块,有自己的作用域
- 在模块内部module变量代表模块本身
- module.exports属性代表模块对外接口
创建自己的模块
const testvar = 100;
function test(){
console.log(testvar);
}
module.exports.testvar = testvar;
module.exports.test = test;
require规则
- / 表示绝对路径, ./ 表示相对于当前文件
- 支持js、json、node扩展名,不写依次尝试
- 不屑路径则认为是build-in模块或者各级node-modules内的第三方模块
const mod = require('./02_commonjs')
console.log(mod.testvar)
mod.test();
require特性
- module被加载的时候执行,加载后缓存
- 一旦出现某个模块被循环加载,就只输出已经执行的部分,还未执行的部分不会输出
引用系统内置模块
const fs = require('fs');
const result = fs.readFile('filename',(err,data)=>{
if(err){
console.log(err);
}else{
console.log(data.toString());
}
});
引用第三方模块
- npm install modulename
- require('modulename')
npm root -g 查看根目录
module.exports与exports的区别
const exports = module.exports
但是不能改变exports的指向
global
- CommonJS
- Buffer、process、console
- timer
process
- argv
- argv0
- execArgv
- execPath
const {argv,argv0,execArgv,execPath,env} = process;
argv.forEach(item=>{
console.log(item);
});
console.log(env);
console.log(process.cwd());
process.nextTick() > setTimeout() > setImmediate()
调试
- Inspector
- vs code
node --inspect-brk filename
IDE debug
第4章 NodeJS 基础 API
基础API
path
normalize join resolve
basename extname dirname
parse format
sep delimiter win32 posix
demo
const {normalize,join,resolve,basename,dirname,extname} = require('path');
console.log(normalize('/usr/local'));
console.log(join('/usr','/local','/bin'));
console.log(resolve('./'));
__dirname,__filename 返回文件绝对路径
process.cwd() 返回执行node命令所在文件夹
./ 在require方法中总是相对于当前文件所在的文件夹
path.resolve()
Buffer
- 用来处理二进制数据流
- 实例类似整数数组,大小固定
- C++代码在V8堆外分配物理内存
Buffer.byteLength()
Buffer.isBuffer()
Buffer.concat([])
buf.length
buf.toString('base64'/'utf8') encode
buf.fill()
buf.equals()
buf.indexOf()
buf.copy()
console.log(Buffer.alloc(10,0x1))
console.log(Buffer.from([1,2,3]))
console.log(Buffer.form('test','base64'));
中文处理
const {stringDecoder} = require('string_decode');
console.log(stringDecoder.write(buf));
event(事件)
eventEmitter.on()方法用于注册监听器,eventEmitter.emit()方法用于触发事件
当EventEmitter对象触发一个事件时,所有绑定在该事件上的函数都被同步地调用,监听器的返回值会被丢弃
const EventEmitter = require('events');
class CustomEvent extend EventEmitter{
}
const ce = new CutomEvent();
// 移除 removeListener removeAllListener
ce.on('test',(err,data)=>{
console.log('this is a event',err,data);
});
setInterval(()=>{
ce.emit('test',err,data);
},500);
fs 文件系统
文件系统的所有方法都有同步和异步两种形式
异步方法的最后一个参数都是回调函数,传给回调函数的参数取决于具体方法,但回调函数的第一个参数都会保留给异常,操作成功后,则第一个参数会是 null 或 undefined
当使用同步方法时,任何异常都会被立即抛出,可以使用try/catch来处理异常,或让异常向上冒泡
示例:
const fs = require('fs');
// 读取某个文件
fs.readFile('filename','utf8',(err,data)=>{
if(err) throw err;
console.log(data);
});
// 文件的情况
fs.stat('filename',(err,stats)=>{
if(err) throw err;
console.log(stats.isDirectory());
console.log(stats.isFile());
});
// 重命名某个文件
fs.rename('filename','rename_name',(err,stats)=>{
if(err) throw err;
console.log('done');
})
// 删除某个文件
fs.unlink('filename',(err,stats)=>{
if(err) throw err;
console.log('done');
});
// 读取文件夹下所有文件
fs.readdir('dirname',(err,files)=>{
if(err) throw err;
console.log(files);
});
// 创建目录
fs.mkdir('dirpath',(err)=>{
if(err) throw err;
console.log('done');
});
// 删除目录
fs.rmdir('dirpath',(err)=>{
if(err) throw err;
console.log('done');
});
// 监听文件
fs.watch('dirpath',{
recursive: true
},(eventType,filename)=>{
console.log(eventType,filename);
});
文件系统高级函数
// readstream
const rs = fs.createReadStream('./filename');
rs.pipe(process.stdout);
// writestream
const ws = fs.createWriteStream('./filename');
const tid = setInterval(()=>{
const num = Math.random() * 10;
if (num < 7){
ws.write(num);
}else{
clearInterval(tid);
ws.end();
}
},200);
ws.on('finish',()=>{
console.log('done!');
});
// promisify
const promisfy = require('util').promisify;
const read = promisify(fs.readFile);
read('filename').then((data)=>{
console.log(data.toString());
}).catch(ex=>{
console.log(ex);
});
async function test(){
try{
const content = await read('filename');
console.log(content.toString())
}catch(ex){
console.log(ex);
}
}
test();
第5章 项目初始化
.gitignore
规则
匹配模式前 / 代表项目根目录
匹配模式最后加 / 代表是目录
匹配模式前加 ! 代表取反
* 代表任意个字符
? 匹配任意一个字符
** 匹配多级目录
示例
logs
*.log
npm-debug.log*
node_modules/
*.swp
.idea/
.DS_Store
build/
dist/
.npmignore
自定义忽略一些格式
node_modules
src
test
npm 默认会忽略一些格式
.git
.svn
.*.swp
._*
config.gypi
CVS
npm-debug.log
不会被忽略的文件
package.json
README
CHANGELOG
LICENSE/LICENCE
Readme.md
项目和软件使用说明
.editorconfig
协作编辑规则,保持持续的代码风格
具体规则访问: www.editorconfig.org
ESLint
.eslintrc.js .eslintignore
具体规则参考: www.eslint.cn视频给到的示例参考,具体规则建议自行制定
module.exports = {
"extends": ["eslint:recommended"],
"parser": "babel-eslint",
"rules":{
"no-console":["error",{
"allow":["warn","error","info"]
}]
},
"parseOptions":{
"ecmaVersion" : 6,
"sourceType":"script"
},
"globals":{
"window": true
},
"env":{
"browser":false,
"node":true,
"es6",true,
"mocha":true
}
}
初始化 eslint --init,建议通过问答式来进行配置
.eslintignore
有些文件是没有必要进行eslint校验的,所以需要忽略
npm pre-commit
安装: npm install --save-dev pre-commit
在package.json的scripts添加
"scripts":{
"lint":"eslint .",
"fix":"eslint --fix ."
},
"pre-commit":[
"fix",
"lint"
]
第6章 案例项目--静态资源服务器
建立一个http server
const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req,res)=>{
res.statusCode = 200;
res.setHeader('Content-Type','text/plain');
res.end('Hello World!\n')
});
server.listen(port,hostname,()=>{
console.log('Server running at http://${hostname}:${port}/');
});
自动重启
npm install -g supervisor
supervisor app.js
handlebarsjs
www.handlebarsjs.com
range
- range: bytes = [start] - [end]
- Accept-Ranges: bytes
- Content-Range:bytes start - end / total
缓存
header
- Expires, Cache-Control
- If-Modified-Since / Last-Modified
- If-None-Match / ETag
cli
commander
yargs
版本号
x.y.z
z: 小问题升级
y: 新增功能,兼容的
x: 大版本更新,不保证兼容
自动打开网页
const {exec} = require('child_process');
module.exports = url => {
switch(process.platform) {
case 'darwin':
exec(`open ${url}`);
break;
case 'win32':
exec(`start ${url}`);
break;
}
}
发布到npm
- 登录npmjs.com
- npm login
- npm publish
第7章 本地构建
gulp.js
automate and enhance your workflow
npm install gulp-cli -g
npm install gulp -D
touch gulpfile.js
gulp --help
1. npm install --save-dev gulp
2. var gulp = require('gulp')
3. gulp.task('default',()=>{
gulp.src(['src/**/*'])
.pip(gulp.dest('build'));
})
4. npm run gulp // 在package.json中的script添加对应的执行
gulp-autoprefixer 自动识别less前缀
gulp-clean-css css压缩
babel
Babel is a Javascript compiler
Use next generation Javascript, todaynpm install --save-dev babel-cli babel-preset-env
.babelrc
webpack
webpack module bundler
tree shaking
uglifyjs-webpack-plugin
webpack-plugins
第8章 单元测试 &UI 测试
断言 assert / chai
BDD/TDD
chai
Mocha
istanbul 覆盖率
持续集成
图标 repo-badges
travis CI
.travis.yml
codevoc.io
benchmark.js / jsperf.com
第9章 UI 测试常用工具
UI测试
Jest 测试 react
selenium-webdriver
第10章 案例项目--headless 爬虫
反爬虫
User-Agent, Referer, 验证码
单位事件访问次数、访问量
关键信息图片混淆
异步加载
爬虫
cheerio
puppeteer
第11章 课程总结
总结全部内容
NodeJS关键技术
Stream
动态Web framework
clild_process & cluster
深入学习
through2
Express koa egg
SSR & 同构
NodeJS源码