nodejs官网
nodejs中文文档1
nodejs中文文档2
node是一个基于v8引擎渲染js的工具
把js运行在node环境下 项目中,我们会在服务器端安装一个node,然后用js去编写后台程序
node 给js提供操作I/O的能力,浏览器不允许js操作I/O
node是事件驱动的 event-based system,js是单线程的,v8是多线程的,只是分配执行js是单线程的,
java是线程驱动的 thread-based system 线程系统提高并发量 多线程,服务器群组,增加线程的管理难度和成本。
哪些时候用到node
- npm模块化管理
- webpack导入导出
- webpack的process.env.NODE_ENV 设置NODE的全局环境变量
- commonjs模块导入导出
- webpack-dev-server 启的服务
- 全栈开发
- 服务器端渲染
脚本设置 process.env.NODE_ENV = “dev”
"scripts":{
"start":"set NODE_ENV = dev & node index.js"
}
服务器端渲染 VS 浏览器端渲染
- 服务器端渲染 优点是 前端渲染耗时少,有利于SEO,所有代码内容都可以看到,有利于爬虫
- 服务器端渲染 缺点是 前端后配合不好,后台压力大,页面需要局部更新,也需要后台重新渲染,
返回最新的结构数据(客户端需要刷新才能看到最新的数据),性能体验不好。
完全的服务器渲染是不能做到局部刷新的
淘宝京东解决性能问题方案是:骨架屏解决方案
第一屏内容是服务器渲染的(只要服务器足够给力,能够提高页面第一次打开渲染速度)
其余屏幕内容都是前后端分离(客户端渲染)
内置的events,发布-订阅者
const EventEmitter = require('events')
const myEmitter = new EventEmitter()
myEmitter.on('A', function f1(...args) {console.log(args)})//[1,2]
myEmitter.on('A', function f2(...args) {console.log(args)})//[1,2]
console.log(myEmitter.listeners('A'))// [ [Function: f1], [Function: f2] ]
myEmitter.emit('A', 1, 2)
node异步执行 常用方法
process.nextTick > setTimeout0 > setImmediate 大说明先执行
setTimeout(() => {
console.log(5)
}, n) // n > 0
setTimeout(() => {
console.log(3)
}, 0)
setImmediate(() => {
console.log(4)
})
process.nextTick(() => { // 主任务完成 立马执行nextTick ,然后再去找event queue任务 这是node内置方法
console.log(2)
})
console.log(1)
// n足够大时 输出 1 2 3 4 5
// n值 较小时,可能每次输出的顺序不太一样 输出 1 2 3 4 是大方向,因为n值较小,输出的5会穿插在2 ~ 3 ~ 4之间
诡异的事情 n值较小 且相同 每次输出的顺序却不一样
CommonJS
想啥时候用 就啥时候用 ,类似cmd
CommonJS是服务器端模块的规范,由Node推广使用,webpack也采用这种规范编写。
CommonJS模块规范主要分为三部分:模块定义、模块标识、模块引用。
优点:模块化思想,每个文件是一个独立的模块,文件之间互相不干扰。
缺点:CommonJS 是同步加载的,在服务器端,文件都是保存在硬盘上,所以同步加载没有问题,但是对于浏览器端,需要将文件从服务器端请求过来,那么同步加载就不适用了,所以浏览器不适合CommonJs,出现另一种规范AMD
exports.foo = function () {console.log(1)}
require('./index').foo() // 1
module.exports = function() {console.log(2)}
require('./index2') //2
AMD ( asynchronous module definition)
require.js
AMD 是运行在浏览器环境的一个异步模块定义规范
适合在浏览器环境中异步加载模块。可以并行加载多个模块,但依赖前置,必须提前加载所有的依赖。
html文件加上这个
<script src="./require.js" data-main='./main.js'></script>
main.js
require.config({
paths: {
dataService: './dataService',
math: './math'
}
})
require(['dataService', 'math'], function (dataService, math) {});
dataService.js
define(['math'], function (math) {
function doSomething() {
let result = math.add(2, 9);
console.log(result);
}
return {
doSomething
};
});
math.js
define(function () {
var add = function (x, y) {
return x + y;
};
return {
add: add
};
});
CMD ( common module definition)
需要用到某个模块时,再加载对应依赖require,依赖就近
<script src="./sea.js"></script>
<script>seajs.use('./main.js')</script>
main.js
define(function (require, exports, module) {
require('./index').four()// '444'
})
module1.js
define(function(require,exports,module){
function one(){
console.log('这是module 1');
}
module.exports = {one}
})
index.js
define(function (require, exports, module) {
let module1 = require('./module1')
function four() {
console.log('444');
}
exports.four = four
})
ES6
导入依赖前置,类似amd
export default {}
import xxx from './xxx'
node内置模块方法
fs
require('fs').readFile('./test.txt', 'utf-8',(err,v)=>{console.log(v)})
require('fs/promises').readFile('./test.txt', 'utf-8').then(v => {console.log(v)})
require('fs').readFileSync('./test.txt', 'utf-8')//默认是buffer流格式,需要加utf-8转化一下
require('fs').writeFile('./test.txt','你是谁','utf-8',(err,v)=>{console.log(v)})
require('fs').appendFile('./test.txt','你是谁','utf-8',(err,v)=>{console.log(v)})
__dirname
console.log(__dirname)// E:\html\vue-element-ui\html-s\node 当前代码文件所在文件夹绝对路径
path
const path = require('path')
console.log(path.resolve('../'))// E:\html\vue-element-ui\html-s
console.log(path.basename('/1/qwer.html','.html'))// qwer
console.log(path.join('1','/2','3')) // '1\2\3'
console.log(path.parse('/home/user/dir/file.txt'))
/*
{
root:'/',
dir:'/home/user/dir',
base:'file.txt',
ext:'.txt',
name:'file'
}
*/
path.resolve('/foo/bar', './baz');
// 返回: '/foo/bar/baz'
path.resolve('/foo/bar', '/tmp/file/'); 第二个绝对路径覆盖了第一个
// 返回: '/tmp/file'
path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif');
// 如果当前工作目录是 /home/myself/node,
// 则返回 '/home/myself/node/wwwroot/static_files/gif/image.gif'
http
const http = require('http')
const url = require('url')
const server = http.createServer((req, res) => {
console.log(Object.keys(req))
console.log(Object.keys(res))
const {
pathname,
query
} = url.parse(req.url, true)
res.writeHead(201, {})
res.end(JSON.stringify({ s: 1, fd: 'fsadfasd' }))
/* 返回的可以是 readFile读取的buffer(图片) 也可以是html文件(utf-8) */
})
server.listen(4000, (v) => {
console.log('localhost:4000')
})
express
cnpm i express cors
post请求头种类
- application/x-www-form-urlencoded
- multipart/form-data
- application/json
原生 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据
表单上传文件时,必须让 表单的 enctype 等于 multipart/form-data
const express = require("express");
const app = express();
const path = require("path")
var cors = require("cors");
var bodyParser = require("body-parser");
const port = 3001;
//cors解决跨域问题 方法1:
var cors = require("cors");
app.use(cors());
//手写解决跨域问题 方法2:
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "http://www.baidu.com:80");
res.header("Access-Control-Allow-Credentials", true);
res.header(
"Access-Control-Allow-Headers",
"Content-Type,Content-Length,Authorization,Accept,X-Requested-With"
);
res.header(
"Access-Control-Allow-Methods",
"PUT,POST,GET,DELETE,OPTIONS,HEAD"
);
req.method === "OPTIONS" ? res.send("ok") : next(); //解决浏览器发送的预请求过程
});
//访问http://localhost:3001/index.json 其实是访问http://localhost:3001/public/index.json
app.use(express.static("public"));
//访问http://localhost:3001/static/bindex.json 其实是访问 http://localhost:3001/files/bindex.json
app.use("/static", express.static("files"));
//比上面一个设置要更加安全 目前不清楚有啥子区别
app.use("/static", express.static(path.join(__dirname, "files")));
//解析post请求方式传递的参数 传参方式不同 解析的方法也不同
app.use(bodyParser.urlencoded({ extended: true })); //application/x-www-form-urlencoded
app.use(bodyParser.json()); //application/json
app.get("/", (req, res) => {
res.send("Hello World!");
});
app.post("/urlencode", function (req, res) {
console.log(req.body); //通过了bodyParser解析后,就可以打印出来前端传递的值
res.json(req.body);
});
app.listen(port, () => {
console.log(`listening at http://localhost:${port}`);
});