模块加载及第三方包:Node.js模块化开发、系统模块、第三方模块、package.json文件、Node.js中模块的加载机制、开发环境与生产环境、cookie与session

1、Node.js模块化开发

1.1 JavaScript开发弊端

JavaScript 在使用时存在两大问题,文件依赖命名冲突
在这里插入图片描述

1.2 软件中的模块化开发

一个功能就是一个模块,多个模块可以组成完整应用,抽离一个模块不会影响其他功能的运行。
在这里插入图片描述

相关用法说明
__filename当前模块的完整路径和文件名称
__dirname当前模块的完整路径
require()引入一个模块 (’./***.js’)
module指代当前的模块对象
module.exports当前模块导出的对象,包含供其它模块使用的属性和方法
exprots等价于module.exports

1.3 Node.js中模块化开发规范

  • Node.js 规定一个 JavaScript 文件就是一个模块,模块内部定义的变量和函数默认情况下在外部无法得到
  • 模块内部可以使用 exports 对象进行成员导出使用 require 方法导入其他模块
    在这里插入图片描述

1.4 模块成员导出和模块成员的导入

(1)模块成员导出

// a.js
  // 在模块内部定义变量
 let version = 1.0;
 // 在模块内部定义方法
 const sayHi = name => `您好, ${name}`;
 // 向模块外部导出数据 
 exports.version = version;
 exports.sayHi = sayHi;

(2)模块成员的导入

// b.js
  // 在b.js模块中导入模块a
 let a = require('./b.js');
  // 输出b模块中的version变量
 console.log(a.version);
  // 调用b模块中的sayHi方法 并输出其返回值
 console.log(a.sayHi('黑马讲师')); 

导入模块时后缀可以省略。

(3)模块成员导出的另一种方式

module.exports.version = version;
module.exports.sayHi = sayHi;

exportsmodule.exports 的别名(地址引用关系),导出对象最终以 module.exports 为准

1.5 模块导出两种方式的联系与区别

exports.version = version;
module.exports.version = version;

在这里插入图片描述

module.exports = { 
    name: 'zhangsan',
}

在这里插入图片描述

2、系统模块

2.1 什么是系统模块

Node 运行环境提供的 API 。 因为这些 API 都是以模块化的方式进行开发的,所以我们又称 Node 运行环境提供的 API 为系统模块。
在这里插入图片描述

2.2 系统模块 fs 文件操作

f:file 文件 ,s:system 系统,文件操作系统。

const fs = require('fs');

(1)读取文件内容:

fs.reaFile('文件路径/文件名称'[,'文件编码'], callback);

fs.readFile('./01.helloworld.js', 'utf8', (err, doc) => {
	// 如果文件读取出错 err 是一个对象 包含错误信息
	// 如果文件读取正确 err是 null
	// doc 是文件读取的结果
	console.log(err);
	console.log(doc);
});

(2)写入文件内容:

fs.writeFile('文件路径/文件名称', '数据', callback);

// 即将要写入的内容
const content = '<h3>正在使用fs.writeFile写入文件内容</h3>';
fs.writeFile('../index.html', content, err => {
   if (err != null) { 
       console.log(err);
       return;
   }
   console.log('文件写入成功');
 });

2.3 系统模块 path 路径操作

(1)为什么要进行路径拼接?

  • 不同操作系统的路径分隔符不统一。
  • /public/uploads/avatar
  • Windows 上是 \ /
  • Linux 上是 /

(2)路径拼接语法:

path.join('路径', '路径', ...)
  // 导入path模块
 const path = require('path');
  // 路径拼接
 let finialPath = path.join('itcast', 'a', 'b', 'c.css');
  // 输出结果 itcast\a\b\c.css
 console.log(finialPath);

(3)相对路径和绝对路径

  • 大多数情况下使用绝对路径,因为相对路径有时候相对的是命令行工具的当前工作目录。
  • 在读取文件或者设置文件路径时都会选择绝对路径。
  • 使用 __dirname 获取当前文件所在的绝对路径。

2.3 系统模块 HTTP

创建 web 服务器

// 引用系统模块
const http = require('http');

// 创建web服务器
const app = http.createServer();

// 当客户端发送请求的时候(监听客户端发送过来的请求)
app.on('request', (req, res) => {
     //  响应
     res.end('<h1>hi, user</h1>');
});
 
// 监听3000端口
app.listen(3000);
console.log('服务器已启动,监听3000端口,请访问 localhost:3000')

2.4 系统模块 url(处理请求路径)

作用:专门用来处理请求路径相关。

const url = require('url');

第二个参数(可省):
如果设为 true,则返回的 URL 对象的 query 属性会是一个使用 querystring 模块的 parse() 生成的对象。 
如果设为 false,则 query 会是一个未解析未解码的字符串。 默认为 false。
 
第三个参数(可省):如果设为 true,则 // 之后至下一个 / 之前的字符串会解析作为 host。 例如, //foo/bar 会解析为 {host: 'foo', pathname: '/bar'} 而不是 {pathname: '//foo/bar'}。 默认为 false
url.parse(urlString,boolean,boolean)
// parse这个方法可以将一个url的字符串解析并返回一个url的对象
url.parse(req.url)

url.format(urlObj)

format 这个方法是将传入的 url 对象编程一个 url 字符串并返回。

url.format({
    protocol:"http:",
    host:"182.163.0:60",
    port:"60"
});
/*
返回值:
'http://182.163.0:60'
*/

url.resolve(from, to)

resolve 这个方法返回一个格式为 “from/to” 的字符串,把参数进行一个拼接,然后返回。


const url = require('url');
url.resolve('/one/two/three', 'four');         // '/one/two/four'
url.resolve('http://example.com/', '/one');    // 'http://example.com/one'
url.resolve('http://example.com/one', '/two'); // 'http://example.com/two'

2.5 系统模块 querystring

官网地址:http://nodejs.cn/api/querystring.html
querystring 从字面上的意思就是查询字符串,一般是对 http 请求所带的数据进行解析。querystring 模块只提供 4 个方法,在我看来,这 4 个方法是相对应的。

一般是对 http 请求所带的数据进行解析(post)

这4个方法分别是:

  • querystring.parse(反序列化)
  • querystring.stringify(序列化)
  • querystring.escape(编码)
  • querystring.unescape(解码)

首先,使用 querystring 模块之前,需要 require 进来,接着,就可以使用模块下的方法了。

const querystring = require('querystring');

(1)querystring.parse(str,separator,eq,options)

parse 这个方法是将一个字符串反序列化为一个对象

querystring.parser(服务端接受的参数);
querystring.parse(str,separator,eq,options);

参数:

  • str:指需要反序列化的字符串;
  • separator(可省):指用于分割 str 这个字符串的字符或字符串,默认值为"&";
  • eq(可省):指用于划分键和值的字符或字符串,默认值为"=";
  • options(可省):该参数是一个对象,里面可设置 maxKeys 和 decodeURIComponent 这两个属性:
    • maxKeys:传入一个 number 类型,指定解析键值对的最大值,默认值为1000,如果设置为 0 时,则取消解析的数量限制;
    • decodeURIComponent:传入一个 function,用于对含有%的字符串进行解码,默认值为 querystring.unescape,默认是 utf-8 的编码,如果不是需要进行定义。
querystring.parse("name=whitemu&sex=man&sex=women");
/*
return:
{ name: 'whitemu', sex: [ 'man', 'women' ] }
*/
querystring.parse("name=whitemu#sex=man#sex=women","#",null,{maxKeys:2});
/*
return:
{ name: 'whitemu', sex: 'man' }
*/

(2)querystring.stringify(obj,separator,eq,options)

stringify 这个方法是将一个对象序列化成一个字符串,与 querystring.parse 相对。

querystring.stringify(obj,separator,eq,options);

参数:

  • obj:指需要序列化的对象。
  • separator(可省):用于连接键值对的字符或字符串,默认值为"&";
  • eq(可省):用于连接键和值的字符或字符串,默认值为"=";
  • options(可省):传入一个对象,该对象可设置 encodeURIComponent 这个属性:
    • encodeURIComponent:值的类型为 function,可以将一个不安全的 url 字符串转换成百分比的形式,默认值为querystring.escape() 。
querystring.stringify({name: 'whitemu', sex: [ 'man', 'women' ] });
/*
return:
'name=whitemu&sex=man&sex=women'
*/
querystring.stringify({name: 'whitemu', sex: [ 'man', 'women' ] },"*","$");
/*
return:
'name$whitemu*sex$man*sex$women'
*/

(3)querystring.escape(str)

escape 可使传入的字符串进行编码。

querystring.escape(str);

querystring.escape("name=慕白");
/*
return:
'name%3D%E6%85%95%E7%99%BD'
*/

(4)querystring.unescape(str)

unescape 方法可将含有%的字符串进行解码。

querystring.unescape(str);

querystring.unescape('name%3D%E6%85%95%E7%99%BD');
/*
return:
'name=慕白'
*/

3、第三方模块

3.1 什么是第三方模块

别人写好的、具有特定功能的、我们能直接使用的模块即第三方模块,由于第三方模块通常都是由多个文件组成并且被放置在一个文件夹中,所以又名包。

第三方模块有两种存在形式:

  • 以 js 文件的形式存在,提供实现项目具体功能的API接口。
  • 以命令行工具形式存在,辅助项目开发。

3.2 获取第三方模块

npmjs.com:第三方模块的存储和分发仓库。

npm (node package manager) : node 的第三方模块管理工具。

  • 下载:npm install 模块名称
  • 卸载:npm unintall package 模块名称

全局安装与本地安装:

  • 命令行工具:全局安装
  • 库文件:本地安装

3.3 第三方模块 nodemon

nodemon是一个命令行工具,用以辅助项目开发。

在 Node.js 中,每次修改文件都要在命令行工具中重新执行该文件,非常繁琐。

使用步骤:

  1. 使用 npm install nodemon –g 下载它。
  2. 在命令行工具中用 nodemon 命令替代 node 命令执行文件。
    在这里插入图片描述

3.4 第三方模块 nrm

nrm ( npm registry manager ):npm 下载地址切换工具。

npm 默认的下载地址在国外,国内下载速度慢。
在这里插入图片描述

使用步骤:

  1. 使用 npm install nrm –g 下载它
  2. 查询可用下载地址列表: nrm ls
  3. 切换 npm下载地址: nrm use 下载地址名称

3.4 第三方模块 Gulp

  • 基于 node 平台开发的前端构建工具。
  • 将机械化操作编写成任务,想要执行机械化操作时执行一个命令行命令任务就能自动执行了。
  • 用机器代替手工,提高开发效率。

(1)Gulp 能做什么

  • 项目上线,HTML、CSS、JS文件压缩合并。

  • 语法转换(es6、less …)。

  • 公共文件抽离。

  • 修改文件浏览器自动刷新。

(2)Gulp 使用

  • 使用 npm install gulp下载 gulp 库文件。
  • 在项目根目录下建立 gulpfile.js 文件。
  • 重构项目的文件夹结构: src 目录放置源代码文件,dist 目录放置构建后文件。
  • gulpfile.js 文件中编写任务。
  • 在命令行工具中执行 gulp 任务。

(3)Gulp 中提供的方法

  • gulp.src():获取任务要处理的文件
  • gulp.dest():输出文件
  • gulp.task():建立 gulp 任务
  • gulp.watch():监控文件的变化
const gulp = require('gulp');
// 使用gulp.task()方法建立任务
gulp.task('first', () => {
    // 获取要处理的文件
    gulp.src('./src/css/base.css') 
    // 将处理后的文件输出到dist目录
    .pipe(gulp.dest('./dist/css'));
});

(4)Gulp 插件

  • gulp-htmlmin :html 文件压缩
  • gulp-csso :压缩 css
  • gulp-babel :JavaScript 语法转化
  • gulp-less:less 语法转化
  • gulp-uglify :压缩混淆 JavaScript
  • gulp-file-include:公共文件包含
  • browsersync: 浏览器实时同步

3.5 第三方模块 router

功能: 实现路由。

安装: npm install router

使用步骤:

  1. 获取路由对象。
  2. 调用路由对象提供的方法创建路由。
  3. 启用路由,使路由生效。
// 引入路由模块,返回的是一个方法
const getRouter = require('router');
// 调用方法,返回路由对象
const router = getRouter();

router.get('/add', (req, res) => {
    res.end('Hello World!')
});
router.get('/index', (req, res) => {
    res.end('index请求成功');
});

// 在我们监听的请求函数里面开启路由功能
// 监听服务
server.on('request', (err, doc) => {
    //启用路由功能第三个参数回调函数必须带上
    router(req, res, () => {
        //路由分发完毕后,再调用此函数
    });
});

3.6 第三方模块 serve-static(引入静态资源)

功能: 实现静态资源访问服务。

安装: npm install serve-static

步骤:

  1. 引入 serve-static 模块获取创建静态资源服务功能的方法。
  2. 调用方法创建静态资源服务并指定静态资源服务目录。
  3. 启用静态资源服务功能。
// 1.引入静态资源加载的模块 
const serveStatic = require('serve-static');
// 2.得到静态资源加载对象 传递静态资源的路径,方便后续使用
const static = serveStatic(path.join(__dirname, 'public'));
 
server.on('request', (req, res) => {
    ...
    //3.开启静态资源
    static(req, res, () => {});
});

server.listen(3000)

3.7 第三方模块 config

作用: 允许开发人员将不同运行环境下的应用配置信息抽离到单独的文件中,模块内部自动判断当前应用的运行环境,并读取对应的配置信息,极大提供应用配置信息的维护成本,避免了当运行环境重复的多次切换时,手动到项目代码中修改配置信息。

使用步骤:

  1. 使用 npm install config 命令下载模块。
  2. 在项目的根目录下新建 config 文件夹。
  3. 在 config 文件夹下面新建 default.json、development.json、production.json文件。
  4. 在项目中通过 require 方法,将模块进行导入。
  5. 使用模块内部提供的 get 方法获取配置信息。

将敏感配置信息存储在环境变量中

  1. 在 config 文件夹中建立 custom-environment-variables.json文件。
  2. 配置项属性的值填写系统环境变量的名字。
  3. 项目运行时 config 模块查找系统环境变量,并读取其值作为当前配置项属于的值。

在这里插入图片描述

3.8 第三方模块 bcrypt(密码加密)

哈希加密是单程加密方式:1234 => abcd

在加密的密码中加入随机字符串可以增加密码被破解的难度。

// 导入bcrypt模块
const bcrypt = require('bcrypt');	
// 生成随机字符串 gen => generate 生成 salt 盐
// genSalt方法接收一个数值作为参数,
// 数值越大 生成的随机字符串复杂度越高,数值越小 生成的随机字符串复杂度越低
// 默认值是 10, 返回生成的随机字符串
let salt = await bcrypt.genSalt(10);
// 使用随机字符串对密码进行加密
let pass = await bcrypt.hash('明文密码', salt);
// 密码比对
// 数据库中的密码进行了加密后不能直接用用户输入的密码与数据库的密码比对,需要把用户传递过来的密码进行加密,然后再和数据库中的比对
// true 比对成功 false 对比失败
let isEqual = await bcrypt.compare('明文密码', '加密密码');

bcrypt 依赖的其他环境

  1. python 2.x
  2. node-gyp
    npm install -g node-gyp
  3. windows-build-tools
    npm install --global --production windows-build-tools

3.9 第三方模块 Joi

JavaScript 对象的规则描述语言和验证器。

// 引入joi模块
const Joi = require('joi');
// 定义对象的验证规则
const schema = {
    username: Joi.string().alphanum().min(3).max(30).required().error(new Error(‘错误信息’)),
    password: Joi.string().regex(/^[a-zA-Z0-9]{3,30}$/),
    access_token: [Joi.string(), Joi.number()],
    birthyear: Joi.number().integer().min(1900).max(2013),
    email: Joi.string().email()
};
// 验证对象是否符合规则
Joi.validate({ username: 'abc', birthyear: 1994 }, schema);

3.10 第三方模块 formidable

作用:解析表单,支持 get 请求参数,post 请求参数、文件上传。

安装: npm install formidable

 // 引入formidable模块
 const formidable = require('formidable');
 // 创建表单解析对象
 const form = new formidable.IncomingForm();
 // 设置文件上传路径
 form.uploadDir = "/my/dir";
 // 是否保留表单上传文件的扩展名
 form.keepExtensions = false;
 // 对表单进行解析
 form.parse(req, (err, fields, files) => {
     // fields 存储普通请求参数
     // files 存储上传的文件信息
 });
// 引入formidable第三方模块
const formidable = require('formidable');
const path = require('path');
const { Article } = require('../../model/article')
 
module.exports = (req, res) => {
	// 1.创建表单解析对象
	const form = new formidable.IncomingForm();
	// 2.配置上传文件的存放位置
	form.uploadDir = path.join(__dirname, '../', '../', 'public', 'uploads');
	// 3.保留上传文件的后缀
	form.keepExtensions = true;
	// 4.解析表单
	form.parse(req, async (err, fields, files) => {
		// 1.err错误对象 如果表单解析失败 err里面存储错误信息 如果表单解析成功 err将会是null
		// 2.fields 对象类型 保存普通表单数据
		// 3.files 对象类型 保存了和上传文件相关的数据
		res.send(files.cover.path.split('public')[1])
	})
	// res.send('ok');
}

3.11 文件读取 FileReader

上传图片实时预览功能

 // 创建文件读取对象
 var reader = new FileReader();
 // 读取文件,this.files是上传时选择的文件列表
 reader.readAsDataURL(this.files[0]);
 // reader.readAsDataURL('文件');
 // readAsDataURL不会直接返回结果,需要监听onload事件
 reader.onload = function () {
     // console.log(reader.result);
     preview.src = reader.result; 
 }

3.12 数据分页 mongoose-sex-page

const pagination = require('mongoose-sex-page');
pagination(集合构造函数).page(1) .size(20) .display(8) .exec();

3.13 第三方模块 art-template(模板引擎)

作用:使用模板引擎提供的模板语法,可以将数据和 HTML 拼接起来。

下载:npm install art-template

// 导入模板引擎,返回的是一个方法
const template = require('art-template');
// 返回的是拼接好的字符串
const html = template('模板路径',插入模板中的数据(对象类型));

3.14 第三方模块 express-session

安装: npm install express-session

//导入express-session模块
const session = require('express-session');
//配置session模块
app.use(session({
    secret: 'secret key',
    //saveUninitialized: false 用到session时才会去初始化 
  //saveUninitialized: true 不管用不用到session都会初始化 
    saveUninitialized: false,
    cookie: {
        maxAge: 24 * 60 * 60 * 1000
    }
}));

 if (isValid) {
            //登录成功时将用户名存储到req.session对象中
            req.session.username = user.username;
            res.redirect('/admin/user');
        } else {
            res.status(400).render('admin/error', { msg: '邮件地址或者密码错误' });
     }
 
admin.get('/loginOut', (req, res) => {
    //退出时删除session
    req.session.destroy(function() {
        //清楚cookie
        res.clearCookie('connect.sid');
        res.redirect('/admin/login');
    });
});

3.15 第三方模块 dateformat

作用: 日期格式处理模块。

安装: npm install dateformat

var dateFormat = require('dateformat');
var now = new Date();
 
// Basic usage
dateFormat(now, "dddd, mmmm dS, yyyy, h:MM:ss TT");

4、package.json文件

4.1 node_modules文件夹的问题

  1. 文件夹以及文件过多过碎,当我们将项目整体拷贝给别人的时候,,传输速度会很慢很慢。
  2. 复杂的模块依赖关系需要被记录,确保模块的版本和当前保持一致,否则会导致当前项目运行报错。

4.2 package.json文件的作用

package.json项目描述文件,记录了当前项目信息,例如项目名称、版本、作者、github 地址、当前项目依赖了哪些第三方模块等。

使用 npm init -y 命令生成。

{
    "name": "description", // 项目名称
    "version": "1.0.0", // 版本号
    "description": "", // 项目描述
    "main": "index.js", // 项目主入口
    "scripts": { // 命名的别名
        "test": "echo \"Error: no test specified\" && exit 1",
        "build": "nodemon app.js" // 取了别名后,只需要输入命令 npm run build
    },
    "keywords": [],// 关键字
    "author": "", // 作者
    "license": "ISC",// 项目遵循协议 ISC 是开放源代码协议
    "dependencies": { // 项目依赖
        "formidable": "^1.2.1",
        "mime": "^2.3.1"
    },
    "devDependencies": { // 开发依赖
        "gulp": "^3.9.1"
    }
}

4.3 项目依赖

  • 在项目的开发阶段和线上运营阶段,都需要依赖的第三方包,称为项目依赖。
  • 使用 npm install 包名命令下载的文件会默认被添加到 package.json 文件的 dependencies 字段中。
{
    "dependencies": {
        "jquery": "^3.3.1}
}

4.4 开发依赖

  • 在项目的开发阶段需要依赖,线上运营阶段不需要依赖的第三方包,称为开发依赖。
  • 使用 npm install 包名 --save-dev命令将包添加到 package.json文件的 devDependencies 字段中。
 {
    "devDependencies": {
        "gulp": "^3.9.1}
 } 

4.5 package-lock.json文件的作用

  • 锁定包的版本,确保再次下载时不会因为包版本不同而产生问题。
  • 加快下载速度,因为该文件中已经记录了项目所依赖第三方包的树状结构和包的下载地址,重新安装时只需下载即可,不需要做额外的工作。

5、Node.js中模块的加载机制

5.1 模块查找规则-当模块拥有路径但没有后缀时

require('./find.js');
require('./find');
  1. require 方法根据模块路径查找模块,如果是完整路径,直接引入模块。
  2. 如果模块后缀省略,先找同名 JS 文件再找同名 JS 文件夹。
  3. 如果找到了同名文件夹,找文件夹中的 index.js。
  4. 如果文件夹中没有 index.js 就会去当前文件夹中的package.json 文件中查找 main 选项中的入口文件。
  5. 如果找指定的入口文件不存在或者没有指定入口文件就会报错,模块没有被找到。

5.2 模块查找规则-当模块没有路径且没有后缀时

require('find');
  1. Node.js 会假设它是系统模块。
  2. Node.js 会去 node_modules 文件夹中。
  3. 首先看是否有该名字的 JS 文件。
  4. 再看是否有该名字的文件夹。
  5. 如果是文件夹看里面是否有 index.js。
  6. 如果没有 index.js 查看该文件夹中的 package.json 中的 main 选项确定模块入口文件。
  7. 否则找不到报错。

6、开发环境与生产环境

(1)什么是开发环境与生产环境

环境,就是指项目运行的地方,当项目处于开发阶段,项目运行在开发人员的电脑上,项目所处的环境就是开发环境。当项目开发完成以后,要将项目放到真实的网站服务器电脑中运行,项目所处的环境就是生产环境

(2)为什么要区分开发环境与生产环境

因为在不同的环境中,项目的配置是不一样的,需要在项目代码中判断当前项目运行的环境,根据不同的环境应用不同的项目配置。

(3)如何区分开发环境与生产环境

通过电脑操作系统中的系统环境变量区分当前是开发环境还是生产环境。

在这里插入图片描述
在这里插入图片描述

 if (process.env.NODE_ENV == 'development') {
     // 开发环境
 } else {
     // 生产环境
 }

7、cookie与session

cookie 浏览器在电脑硬盘中开辟的一块空间,主要供服务器端存储数据。

  • cookie 中的数据是以域名的形式进行区分的。
  • cookie 中的数据是有过期时间的,超过时间数据会被浏览器自动删除。
  • cookie 中的数据会随着请求被自动发送到服务器端。

在这里插入图片描述
session 实际上就是一个对象,存储在服务器端的内存中,在 session 对象中也可以存储多条数据,每一条数据都有一个 sessionid 做为唯一标识。

在这里插入图片描述
在 node.js中 需要借助 express-session 实现 session 功能。

const session = require('express-session');
app.use(session({ secret: 'secret key' }));
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值