服务器端开发要做的事情
- 实现网站的业务逻辑
- 数据的增删改查
为什么选择node
- 使用js语法开发后端应用
- 生态系统活跃,有大量的开源库可以使用
- 一些公司要求前端工程师掌握node开发
- 前端开发工具大多基于node
初识Node.js
node是基于chrome v8引擎的javascript代码运行环境
其实就是一个软件,这个软件可以运行javascript代码,我们就称它为JavaScript代码运行环境
既然是一个软件,那么我想要去使用它,就必须要先去安装一下这个软件
还有就是,基于node.js和第三方工具electron可以开发桌面应用程序
在浏览器的js运行环境中,有一个顶级对象window对象
但是node.js中不存在window对象
但是node.js中有一个类似于window对象的东西,就是Globals对象
Node运行环境搭建
安装
去官网下载安装包
目前node有两个主要的版本:
一个是10.13.0 LTS; LTS = Long Term Support 长期支持 稳定版。
一个是11.1.0 Current Current 拥有最新特性 实验版
下载稳定版进行安装即可
安装完成后,打开命令行工具,去验证一下是否安装成功。
在命令行输入 node -v 查看当前node的安装版本,如果可以正常返回值,就代表安装成功了
JavaScript本质上是什么?
是一门编程语言
浏览器的内核包括?
1、DOM渲染引擎 2、js解析器,js运行在浏览器张的内核的js引擎内部
是否js只能在浏览器中运行?
不是的,所有的js环境中都可以运行 比如在命令行窗口中输入node,就进入到js执行环境了,在这个环境中可以执行js语法的代码
实现动态网站的技术
Java,asp,.net ,node.js ,python
只有输入完node进入的那个环境才是repl环境吗? 是的
命令行窗口的运行环境,我们称之为REPL运行环境, read-eval-print-loop 也就是 读取代码-执行-打印结果-循环 这个过程
在REPL环境中,有一个特性 —> _
表示最后一次的执行结果
直接输入一个算术表达式,可以正常输出这个表达式的计算结果 第二次运算的时候,可以用 _ 直接代替上一个表达式的运算结果,参与到新的运算中去
如下图:
那么输入 node可以进入到REPL环境中,那怎么退出这个环境呢?
.exit
REPL环境可以可以执行js代码,那么自然也就可以执行js文件,在js代码比较多的时候,我们把代码放在一个js文件中,然后在命令行窗口输入 node 文件名
就可以运行了
全局对象、全局成员
node有一个全局对象,就是globals对象,等同于浏览器中的window对象,在用的时候可以省略。
全局成员都是直接隶属于globals全局对象就是不需要引用就可以直接使用的对象。
需要注意的是全局对象Globals区别于global关键字。nodejs全局对象分为以下几类:
1、为模块包装使用的全局对象
(1)exports
(2)module
(3)require
(4)filename:当前文件名称
(5)dirname:当前文件目录
2、process对象
process.argv**
argv是一个数组,默认情况下,前两项数据分别是:Node.js环境的路径,当前执行的js文件的全路径 从第三个参数开始,表示命令行参数
process.arch**
打印当前系统的架构(64位或32位)
3、控制台Console模块
4、EventLoop相关api
(1)setImmediate
(2)setInterval
(3)setTimeout
(4)相关clear
5、Buffer对象
6、global
global用于扩展变量和方法。
Node快速入门
JavaScript由三部分组成:
ECMAScript 是这门语言的核心,规则了这门语言的语法规则
DOM 浏览器这个运行环境,为js提供的API
BOM 浏览器这个运行环境,为js提供的API
Node是由
ECMAScript 是这门语言的核心
Node环境提供的一些附加的API组成的
Node.js基础语法
所有ECMAScript语法在Node环境中都可以用
JavaScript要运行代码的话,是引入到html页面中进行运行
node中没有html页面,所以要执行代码的话,要借助命令行工具
先新建一个js文件,写上node代码,然后打开命令行工具(命令行目录必须和工作目录处于同一个文件夹啊),然后在命令行中输入 node 文件名 ,回车,就可以运行当前文件了
Node.js模块化开发
JavaScript开发的两大弊端
1、文件依赖关系不明确
JavaScript文件的依赖关系是由文件引入的先后顺序决定的。
2、命名冲突
在一个js文件中命名了一个变量,之后又引入了其他的js文件,并且这个新文件中也有这个变量,那么后边的变量就会把前边的变量给覆盖了。文件与文件之间是全开放的状态
前端标准的模块化规范:
1、AMD - require.js
2、CMD - seajs(国产的,阿里巴巴的)
服务器端的模块化规范
1、CommonJs - Node.js
前端标准与后端标准的模块化的区别:
主要是文件加载的不同
1、前端模块化加载js文件的时候,需要从服务器经过网络传输到浏览器端,代码才能执行 2、在服务器端,加载文件的时候,只需要从磁盘加载到内存就可以了 所以说服务端的加载一般是同步的。前端的加载一般是异步的(因为传输过程需要时间)
文件与文件之间是一种半封闭的状态,在当前文件中有哪些代码我希望其他文件能够访问到,那么我就把这一部分代码给开放出去。不开放的那部分代码,其他文件是访问不到的。
软件中的模块化开发
一个功能就是一个模块,多个模块可以组成完整的应用,抽离一个模块不会影响其他功能的运行。
node.js中模块化开发的规范
- node.js规定一个JavaScript文件就是一个模块,模块内部定义的变量和函数在默认情况下外部是无法得到的。
- 在实际开发中,肯定会出现一个文件需要依赖另一个文件的情况,那么,模块内部可以使用exports对象进行成员导出(模块内部定义的变量或者函数,想要在模块外部被访问到,那么我们可以把它进行导出),再使用require方法导入其他模块。
怎么导出呢?实际上就是把这个函数变成exports的属性值就可以了。
在b中使用require方法进行导入。require方法有一个返回值,返回值就是导入的那个模块的exports对象
Node.js中模块成员导出的方式
1、exports和require
//a.js
const add = (n1, n2) => {
return n1 + n2;
}
exports.add = add;
// exports是一个对象,需要导出东西的话,就把要导出的东西当作exports对象的属性值就可以了
// 第一个add是exports的属性值,第二个add是我们定义的add方法
const a = require("./a");//导入模块时,后缀可以省略
// require是有返回值的,所以我定义了一个变量去接收它的返回值。
// 它的返回值其实就是exports对象
console.log(a);//这里的a就是a.js中的add方法,也就是exports对象的add属性的属性值
console.log(a.add(23,5)); //所以如果想要调用add,直接以对象的形式进行调用
系统模块
什么是系统模块?
Node运行环境提供的API,因为这些API都是以模块化的方式进行开发的,所以我们又称node运行环境提供的API为系统模块
node运行环境提供了很多系统模块,在每一个系统模块当中,它提供的都是具有相关性的功能。
比如说文件操作系统模块,提供了读取文件,写入文件,创建文件夹等模块
系统模块fs 文件操作
f:file, s:system系统 文件操作系统
我们要操作哪个模块,就要引入一下这个模块。系统模块也不例外。
所以在用系统模块的时候,我们要先引入一下这个模块
const fs = require('fs');
//require('fs')中的fs,指的就是fs系统模块
//const fs中的fs,就是fs系统模块中的module.exports的返回值
//这个操作暴露了一些与文件操作相关的API
读取文件内容
fs.reaFile('文件路径/文件名称',['文件编码'],callback)
//a.js
const add = (n1, n2) => {
return n1 + n2;
}
// exports.add = add;
// exports是一个对象,需要导出东西的话,就把要导出的东西当作exports对象的属性值就可以了
// 第一个add是exports的属性值,第二个add是我们定义的add方法
// module.exports也是对象类型,我们只需要把模块成员作为module.exports对象的属性值就可以了。
module.exports.add = add;
// exports对象和module.exports对象都可以导出成员,那么二者有什么关系呢?
// exports是module.exports的别名(地址引用关系),导出对象最终以module.exports为准
// 默认情况下,他俩指向的是同一块内存空间,所以默认情况下,这两种写法是等价的。如下
// module.exports.add = add;
// exports.add = add;
// 但是如果exports对象和module.exports对象指向的不是同一个对象时,以module.exports对象为准,
// 比如我们强制改变了module.exports对象指向
// exports.add = add;
//module.exports = {
// name:"zhangsan"
// }
// 这个时候二者指向的东西就不一样了,那么最终的导出结果,就是module.exports对象里边的东西咯
const a = require("./a");//导入模块时,后缀可以省略
// require是有返回值的,所以我定义了一个变量去接收它的返回值。
// 它的返回值其实就是exports对象
console.log(a);//这里的a就是a.js中的add方法,也就是exports对象的add属性的属性值
console.log(a.add(23,5)); //所以如果想要调用add,直接以对象的形式进行调用
// const a = require('./1');
// console.log(a.sum(12, 3))
// require里边的fs 指的是node提供的fs系统模块,fs是文件操作系统
const fs = require('fs');
// fs模块有一些相关的API,我们可以直接调用
// 客户端向服务器端请求浏览index.html的时候,
// 服务器端要先在自己的硬盘当中找到index.html,并读取出文件的内容,再将文件内容返回给客户端
// 这个过程就是由fs.readFile来完成的
// fs.readFile('文件路径/文件名称',['文件编码'],callback);
// 记住,以后在官方文档中看到某个参数是用[]包起来的,说明它是一个可选参数
// 实际上是硬盘在读取内容,读取内容这个过程需要时间,
// 所以我们不能通过这个API的返回值直接拿到内容
// 所以在这个地方我们需要定义一个函数,当文件内容读取完成后,硬盘会通知这个API说内容读取完了,我可以调用你的回调函数了
// 然后在调用回调函数的时候,把读取到的内容通过函数的参数的形式传递过来了
// 所以第三个参数callback 的作用,就是为了拿到读取的结果
// callback的第一个参数是err,第二个参数是doc
// 为什么第一个参数是err呢
// 因为读取的时候可能会出错,如果出错了就把信息存在err中,err是一个对象,里边包含着错误信息。如果err的值为空,说明读取成功了
// 第二个参数是doc,它里边是文件读取的结果
// node.js中的所有API,它们的回调函数第一个参数都是err,所以我们也称node.js为错误优先的回调函数
// 读取文件内容
// fs.readFile('./1.js', 'utf-8', (err, doc) => {
// if (err == null) {
// console.log(doc);
// }
// })
// 写入文件内容
// 应用场景:比如在网站的运行当中,要监控网站的运行情况。
// 例如在网站的运行过程中是否报错的情况,
// 那程序员也不能一直盯着电脑看啊,所以我们希望当程序运行报错的时候,我们把错误信息写入错误日志当中
// 程序员上班的时候,只需要查看错误日志就可以直接查看网站有没有报过错了
// 语法
// fs.writeFile('文件路径/文件名称', '数据', callback);
// 如果文件路径中不存在这个文件名称,系统会自动帮我们创建一个出来
// 写入内容这个过程可能会成功,也可能会失败,所以写入内容的结果就是这个成功或者失败,也就是函数的第一个参数err
// const content = '<h3>111233</h3>';
// fs.writeFile('./1.txt', content, err => {
// if (err != null) {
// console.log(err);
// return;
// }
// console.log('写入成功');
// })
// 系统模块path 路径操作
// 主要是针对硬盘的路径进行操作
// 路径拼接API
// 为什么会有路径拼接这种操作呢
// 1、不同操作系统的路径分隔符不统一
// 路径分隔符是啥,就是文件夹与文件夹之间的分隔符
// /public/uploads
// window中是 \ / 都可以
// Linux中是只有/才可以
// 为什么要考虑Linux呢,因为Linux系统通常作为我们的网站服务器,我们的项目以后很可能要运行在Linux下
// Path2D.join('路径','路径',...)
// const path = require('path');
// let finalPath = path.join('localhost', '1.html', '3');
// console.log(finalPath);
// 相对路径 绝对路径
// Node.js开发时,一般用的都是绝对路径
// 大多数情况下使用绝对路径,因为相对路径有时候相对的是命令行工具的当前工作目录
// 在读取文件或者设置文件路径时都会选择绝对路径
// 使用__dirname获取当前文件所在的绝对路径
// 用绝对路径还是相对路径,要取决于这个相对路径 相对的是否是当前的文件
// 但是大多情况下,相对路径相对的都不是当前文件,而是命令行窗口所在的文件目录
// 所以需要用path.join方法 将当前文件的绝对路径 和你想要读取的文件拼接在一起 形成一个完整的路径再去读取
// require方法中也有路径,它的路径本身就是相对于当前文件的,所以在用require方法的时候是可以写相对路径的
Node第三方模块
别人写好的,具有特定功能的,我们能直接使用的模块即第三方模块,由于第三方模块通常是有多个文件组成并且被放置在一个文件夹中,所以又名包 所以 包—第三方模块
第三方模块有两种存在形式:
以js文件的形式存在,提供实现项目具体功能的API接口
以命令行工具形式存在,辅助项目开发
获取第三方模块
第三方模块都是非官方的模块,是由千千万万的开发者提供的。 比如张三写了一个很厉害的模块,很多人都想去使用它,但是很多人都不认识张三,无法得到这个模块。 所以就需要一个平台来存储这些模块,于是npmjs.com就诞生了,它是第三方模块的存储和分发仓库。在这个网站中存储了非常多的模块
那我们怎么使用这个网站上的包呢?
npmjs.com提供了一个命令行工具npm
npm(node package manager)node的第三方模块管理工具
node安装好的时候,就已经集成了npm了
第三方模块npm
npm在使用过程中,只要没有看到红色的报错就没问题,出现warn也问题不大 npm详细使用写在另一篇笔记中了
一、下载 npm install 模块名称
模块下载到哪了?默认情况下是下载到了当前命令行窗口所在的文件夹的位置中。 执行完这句代码后,文件夹中会自动生成一个Nodemodules包,第三方模块就存在这个文件夹里边。
二、卸载某个模块 npm uninstall package 模块名称
三、npm安装中的本地安装和全局安装
本地安装 将模块下载到当前的项目当中,供当前的项目使用
全局安装 将模块安装到一个公共的目录当中,所有的项目都可以使用这个模块
一般我们将命令行工具进行全局安装;库文件进行本地安装
npm install 模块名 -g
, 全局安装npm install 模块名 --save-dev
安装依赖到开发环境
npm install 模块名 --save
安装依赖到生产环境
第三方模块nrm
npm下载地址切换工具
npm默认的下载地址在国外,我们在国内下载的速度慢。目前国内有人将国内的服务器与国外的服务器进行同步,我们可以直接访问国内服务器进行安装。
那么怎么切换到国内安装的地址呢
1.使用npm install nrm -g 下载它(全局安装)
2.查询可用下载地址列表nrm ls
3.切换npm下载地址 ,再使用 nrm use 下载地址名称 就可以了
第三方模块nodemon
nodemon是一个命令行工具,用来辅助项目开发
在node.js中,每次修改文件后都要在命令行工具中重新执行该文件,非常繁琐
使用步骤:
1、使用npm install nodemon -g 先安装
2、以后在执行node server.js的时候,用nodemon server.js来代替
第三方模块Gulp
基于node平台开发你前端构建工具 将机械化操作编写成任务,想要执行机械化操作时执行一个命令行命令任务就能自动执行了
一、Gulp能做什么
1.项目上线的时候,对html css js文件压缩合并
2.语法转换(es6 less)
3.公共文件抽离
4.修改文件浏览器自动刷新
我感觉这个功能有点类似于webpack
二、Gulp的使用
1.使用npm install gulp 下载gulp文件
2.在项目根目录下建立gulpfile.js文件
3.重构项目的文件夹结构
src目录放置源代码文件 dist目录放置构建后的文件
4.在gulpfile.js文件中编写任务
5.在命令行工具中执行gulp任务