NodeJs入门知识

****************************************************************************************************************************************************************************

复制代码
1、配置Node.js与npm下载(精力所致,必有精品)          链接:https://pan.baidu.com/s/1k_AgwkMRCSsY1YQrW7Pp3Q 提取码:gb2o 
【1】第一步 下载指定位置安装NodeJs
【2】第二步 在安装目录下创文件夹:node_global、node_cache
【3】第三步(查看所有npm 配置 npm config list)
npm config set prefix "C://Program Files//nodejs//node_global"   查看 npm config get prefix
npm config set cache "C://Program Files//nodejs//node_cache"   查看 npm config get cache 
【4】第四步Path里添加C://Program Files//nodejs   与   C://Program Files//nodejs//node_global(这里可以让所有全局安装包,都能以CMD命令查看node_global)
【5】第五步
npm get registry
*******************************切换成淘宝镜像
npm config set registry=https://registry.npmmirror.com/ 
*******************************配置国内下载镜像地址
npm install -g cnpm
【6】第六步
npm install vue -g  检查是否安装成功:npm info vue
npm install vue-cli -g 检查是否安装成功:vue -V
【7】第七步   “用管理员运行命令窗口”   cd到对应项目执行npm install             npm run serve

****************************************************************************************************************************************************************************

复制代码
2、解决下载包慢的问题
【1】因为默认是从国外https://registry.npmjs.org进行下载的,数据传输需要还低光缆,因此下载包速度很慢。
【2】淘宝npm镜像服务器。把国外的包克隆到淘宝服务器(镜像Mirror),然后从淘宝服务器下载。一些文章还是写着旧的淘宝 NPM 镜像 registry.npm.taobao.org,
但它已于 2022 年 05 月 31 日 废弃,读者需要更换为新的 registry.npmmirror.com 源。
*******************************查看当前从哪里下载
npm get registry
*******************************切换成淘宝镜像
npm config set registry=https://registry.npmmirror.com/
*******************************检查是否设置成功。
npm get registry
【3】npm i nrm -g 安装nrm小工具。注意配置node.js的安装路径添加到环境变量path
nrm ls
nrm use taobao

****************************************************************************************************************************************************************************

复制代码
3、前端服务器部署
【1】npm run build打包出来dist
【2】npm install anywhere -g 安装前端静态服务器插件
【3】把dist上传到自己的服务器,配置nginx反向代理vue      cd /usr/local/nginx/conf  。        vim nginx.conf         配置如下
  location / {
              root /root/site/UserInterface/dist;
              index index.html index.htm;
              try_files $uri $uri/ /index.html;
        }
开头加:  user root;
【4】切换目录,重启nginx      cd /usr/local/nginx/sbin。          ./nginx -s reload 重启nginx
【5】注意上线后,原来本地传的头像地址会仍是localhost,需要改成对应的服务器地址的
【6】配置gzip报错nginx: [emerg] unknown directive "gzip_static" in /usr/local/nginx/conf/nginx.conf:52
【7】cd /opt/nginx/nginx-1.13.7
【8】./configure --prefix=/usr/local/nginx --with-http_gzip_static_module(过程如果报错参照Nginx安装那节,配置对应文件即可)
【9】make && make install
【10】cd /usr/local/nginx/sbin 完成后通过./nginx -s reload重新加载nginx即可

****************************************************************************************************************************************************************************

复制代码
4、Nginx配置VUE快速访问
【1】npm install --save-dev compression-webpack-plugin
【2】配置压缩打包vue.config.js
const {serverPort} = require("./public/config");
const path = require('path');
const webpack = require('webpack');
const CompressionPlugin = require('compression-webpack-plugin');
const zlib = require('zlib');

module.exports = {
    devServer: {
        port: serverPort, // 端口
    },
    configureWebpack: {
        resolve: {
            alias: {
                '@': path.resolve(__dirname, './src'),
                '@i': path.resolve(__dirname, './src/assets'),
            }
        },
        plugins: [
            new webpack.IgnorePlugin(/^./locale$/, /moment$/),
            // 下面两项配置才是 compression-webpack-plugin 压缩配置
            // 压缩成 .gz 文件
            new CompressionPlugin({
                filename: '[path][base].gz',
                algorithm: 'gzip',
                test: /.js$|.css$|.html$/,
                threshold: 10240,
                minRatio: 0.8
            }),
            // 压缩成 .br 文件,如果 zlib 报错无法解决,可以注释这段使用代码,一般本地没问题,需要注意线上服务器会可能发生找不到 zlib 的情况。
            new CompressionPlugin({
                filename: '[path][base].br',
                algorithm: 'brotliCompress',
                test: /.(js|css|html|svg)$/,
                compressionOptions: {
                    params: {
                        [zlib.constants.BROTLI_PARAM_QUALITY]: 11
                    }
                },
                threshold: 10240,
                minRatio: 0.8
            })
        ]
    }
}
【3】配置Nginx
server{
    listen 8088;
    server_name localhost;
    # compression-webpack-plugin 配置
    gzip on;
    gzip_min_length 1k;
    gzip_comp_level 9;
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
    gzip_vary on;
    # 配置禁用 gzip 条件,支持正则,此处表示 ie6 及以下不启用 gzip(因为ie低版本不支持)
    gzip_disable "MSIE [1-6].";
}
【4】最后首次访问可以提升到3秒

****************************************************************************************************************************************************************************

复制代码
学习目标
【1】是什么。可以干什么。Node.js中js的组成部分。使用fs模块读写操作文件。使用path模块处理路径。使用http写一个基本的web服务器。
【2】学习目录:认识node.js。fs path http三个模块的学习。

****************************************************************************************************************************************************************************

复制代码
1、整体概述
【1】已有基础HTML CSS JS。
【2】浏览器中JS的组成部分。JS核心语法+WebAPI(DOM BOM AJAX...)
【3】为什么JS可以在浏览器中执行?因为JS解析引擎的存在,不同浏览器解析引擎也不同,而Chrome的V8解析引擎性能最好。
【4】为什么JS可以操作DOM与BOM呢?因为浏览器“内置”了DOM与BOM的API,因此才可以调用。
【5】浏览器中JS的运行环境是什么呢?类似于JAVA的JDK。JS的是V8引擎+内置API(DOM BOM AJAX Canvas API等等)。API类似JAVA的基础包。
【6】JS能否做后端开发?答案是肯定的,但是需要借助Node.js。

****************************************************************************************************************************************************************************

复制代码
2、Node.js概述
【1】Node.js是基于Chrome V8引擎的js运行环境。官方网站https://nodejs.org/zh-cn
【2】Node.js中的js运行环境。V8引擎+内置API。Node.js是js的后端运行环境。Node.js无法调用DOM与BOM等浏览器内置API。
【3】Node.js可以干什么?Node.js提供的是基础,而强大的框架雨后春笋。可以构建Web应用、构建跨平台桌面应用。敢说是后端大宝剑?
【4】主要会js一定可以学会node。学习路径:js基础语法+node.js内置API模块+第三方API模块。类比与js学习 js基础语法+浏览器内置API(DOM+BOM)+三方库(JQuery)

****************************************************************************************************************************************************************************

复制代码
3、Node.js环境的安装
【1】https://nodejs.org/zh-cn/官网下载安装包。
【2】下载长期维护版我的哥。这个老师是真的细。一般不更改默认目录(不谋而合)。
【3】查看安装的版本号 node -v。

****************************************************************************************************************************************************************************

复制代码
4、用node运行js代码
【1】终端:用于人机交互的一种方式。辅助我们更好的操作与使用计算机。
【2】打开终端-node xxx.js。
E:A计算机IT0001项目3.VUE学习day1js>node 1.js
hello js
【3】他说的快捷键还没有我的切换到文件夹直接cmd直接。↑↓可以执行上下的命令。使用tab键能快速补全文件名。这不都是我知道的吗...。ESC可以快速清空当前输入未执行的内容。cls清空当前终端。

****************************************************************************************************************************************************************************

复制代码
6、fs文件系统模块
【1】安装了node,就会自动带fs模块。读取文件。
*******************************************************************
const fs = require("fs");
const res = fs.readFile("day.txt", "utf-8", function (err, data) {
    console.log(err); // 如果文件不存在,则是一个错误对象。
    console.log(data);
})
【2】判断是否读取成功
const fs = require("fs");
const res = fs.readFile("day.txt", "utf-8", function (err, data) {
    if (err) {
        return console.log("读取文件失败");
    }
    console.log(data);
})

****************************************************************************************************************************************************************************

复制代码
7、写入文件内容
【1】写入的用法
const fs = require("fs");
fs.writeFile("dayOut.txt", "这是我写的", function (err) {
    if (err) {
        console.log("写入失败");
    } else {
        console.log("写入成功");
    }
});

****************************************************************************************************************************************************************************

复制代码
8、整理成绩案例
【1】主要看循环+lambda表达式
let scoreArray = ["小明-98", "小红-97"];
let newArray = [];
scoreArray.forEach(item => {
    newArray.push(item.replace("-", ":"));
});
newArray = newArray.join("
");
console.log(newArray);

****************************************************************************************************************************************************************************

复制代码
9、处理路径问题
【1】处理与jar包一样。解决方案使用绝对完整路径。带来了移植性差的问题。使用console.log(__dirname);类似于java的System.getProperty("user.dir");

****************************************************************************************************************************************************************************

复制代码
10、path路径模块
【1】路径拼接的新方式
let path = require("path");
let finalPath = path.join("/a", "/b/c", "../", "./d", "e");
console.log(finalPath);
【2】改版后的读文件
let path = require("path");
let fs = require("fs");
fs.readFile(path.join(__dirname, "day.txt"), "utf-8", function (err, data) {
    console.log(data);
})
【3】获取路径最后的参数名。
let path = require("path");
let tempPath = "a/b/index.html"
console.log(path.basename(tempPath))
console.log(path.basename(tempPath, ".html"))
console.log(path.extname(tempPath))
console.log(path.basename(tempPath, path.extname(tempPath)))

****************************************************************************************************************************************************************************

复制代码
10、时钟案例-分析需求与读取文件内容
【1】用node.js拆分一个整合文件为css/js/html。感觉就是用js的方式做后端该做的事情。
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>info.html</title>
</head>
<body>
<div>主体部分</div>
</body>
<script>
    console.log("执行了函数");
</script>
</html>
<style>
    .red {
        background-color: red;
    }
</style>
****************************************************
const fs = require("fs");
const path = require("path");
// 正则表达式 s表示空白字符 S表示非空白字符 *表示匹配任意次
const regStyle = /<style>[sS]*</style>/;
const regScript = /<script>[sS]*</script>/;
// 2.1读文件
fs.readFile(path.join(__dirname, "info.html"), "utf-8", function (err, data) {
    if (err) {
        return console.log("读取html失败");
    }
    // 读取成功 进行拆解
    resolveCSS(data);
    resolveJS(data);
    resolveHTML(data);
})

// 定义方法
function resolveCSS(htmlStr) {
    const res = regStyle.exec(htmlStr);
    const finalRes = res[0].replace("<style>", "").replace("</style>", "");
    console.log(finalRes);
    // 提取的样式写入到文件
    fs.writeFile(path.join(__dirname, "clock/index.css"), finalRes, function (err) {
        if (err) {
            return console.log("写入失败");
        }
        console.log("写入样式成功");
    })
}

// js解析方法
function resolveJS(htmlStr) {
    const res = regScript.exec(htmlStr);
    const finalRes = res[0].replace("<script>", "").replace("</script>", "");
    console.log(finalRes);
    // 提取的样式写入到文件
    fs.writeFile(path.join(__dirname, "clock/index.js"), finalRes, function (err) {
        if (err) {
            return console.log("写入失败");
        }
        console.log("写入JS成功");
    })
}

// html解析方法
function resolveHTML(htmlStr) {
    const res = htmlStr.replace(regStyle, '<link rel="stylesheet" href="./index.css"/>')
        .replace(regScript, '<script src="./index.js"></script>');
    fs.writeFile(path.join(__dirname, "clock/index.html"), res, function (err) {
        if (err) {
            return console.log("写入失败");
        }
        console.log("写入HTML成功");
    })
}

****************************************************************************************************************************************************************************

复制代码
HTTP模块知识...

****************************************************************************************************************************************************************************

复制代码
1、http模块概念与作用
【1】负责对外提供网络资源的电脑,叫服务器。负责消费资源的电脑叫做客户端。这个定义对于新手不好理解吧?
【2】常见web服务器软件。IIS、Apache等。能把普通的电脑变成web服务器。tomcat我们走。
【3】http模块可以自己写一个tomcat....

****************************************************************************************************************************************************************************

复制代码
2、服务器相关的概念
【1】IP地址:唯一性。在0-255之间。互联网中每一台web服务器都有自己的IP地址。自己的电脑可以启动本地服务。127.0.0.1(本地IP)与localhost(本地域名)
【2】域名与域名服务器。IP是身份证号码,而域名相当于人的名字。IP与域名是一一对应关系。存放这份关系的电脑叫做域名服务器(DNS)Domain name server。
【3】端口号。就是现实中的房间号,比如你住酒店,外卖怎么送到你的手里,就需要房间号。服务器可以运行多个服务,每一个服务都住在一个房间。一个端口同时只能一个服务,80/443端口可以省略。

****************************************************************************************************************************************************************************

复制代码
3、http创建基本web服务
【1】创建与启动web服务器,这玩意让我更懂java了,卧槽。
const http = require("http");
const server = http.createServer();
server.on("request", function (req, res) {
    console.log("有人访问服务");
})
server.listen(80, () => {
    console.log("服务器运行在localhost");
})
***********************************************
const http = require("http");
const server = http.createServer();
server.on("request", (req, res) => {  //  function (req, res)  VS   (req, res) =>是一样的效果
    console.log("有人访问服务");
})
server.listen(80, () => {
    console.log("服务器运行在localhost");
})
【2】req请求对象携带数据。
const http = require("http");
const server = http.createServer();
server.on("request", (req, res) => {
    console.log(req.url + " VS " + req.method);
    console.log("有人访问服务");
})
server.listen(80, () => {
    console.log("服务器运行在localhost");
})
【3】res响应请求
const http = require("http");
const server = http.createServer();
server.on("request", (req, res) => {
    console.log(req.url + " VS " + req.method);
    console.log("有人访问服务");
    res.end("return data");
})
server.listen(80, () => {
    console.log("服务器运行在localhost");
})
【4】解决返回中文乱码问题
const http = require("http");
const server = http.createServer();
server.on("request", (req, res) => {
    console.log(req.url + " VS " + req.method);
    console.log("有人访问服务");
    res.setHeader("Content-type", "text/html; charset=utf-8"); // 这里
    res.end("return data 返回了");
})
server.listen(80, () => {
    console.log("服务器运行在localhost");
})

****************************************************************************************************************************************************************************

复制代码
4、http根据url不同响应对应html内容
【1】判定404与对应网页
const http = require("http");
const server = http.createServer();
server.on("request", (req, res) => {
    const url = req.url;
    let content = '<h1>404 not found</h1>';
    if (url === "/" || url === "/index.html") {
        content = '<h1>首页</h1>';
    } else if (url === "/about.html") {
        content = '<h1>关于我们</h1>';
    }
    res.setHeader("Content-type", "text/html; charset=utf-8");
    res.end(content);
});
server.listen(80, () => {
    console.log("服务器运行在localhost");
})

****************************************************************************************************************************************************************************

复制代码
5、web服务器案例
【1】res.end()这个方法很关键。用到了fs+path模块
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<h1 style="color: red">欢迎大家访问~~~</h1>
</body>
</html>
*************************************************************
const http = require("http");
const server = http.createServer();
server.on("request", (req, res) => {
    res.setHeader("Content-type", "text/html; charset=utf-8");
    const url = req.url;
    let content = '<h1>404 not found</h1>';
    if (url === "/" || url === "/index.html") {
        let fs = require("fs"); //!!!!!!!!!!
        let path = require("path"); //!!!!!!!!!!
        fs.readFile(path.join(__dirname, url), "utf-8", (err, data) => {
            if (err) {
                console.log("返回失败");
                res.end('<h1>返回失败</h1>');
            }
            res.end(data);
        });
    } else if (url === "/about.html") {
        content = '<h1>关于我们</h1>';
        res.end(content);
    }

});
server.listen(80, () => {
    console.log("服务器运行在localhost");
})
**************************************************************优化不加后缀,也可以加在index.html
const http = require("http");
const server = http.createServer();
server.on("request", (req, res) => {
    res.setHeader("Content-type", "text/html; charset=utf-8");
    const url = req.url;
    let content = '<h1>404 not found</h1>';
    if (url === "/" || url === "/index.html") {
        let fs = require("fs");
        let path = require("path");
        fs.readFile(path.join(__dirname, "/index.html"), "utf-8", (err, data) => {
            if (err) {
                console.log("返回失败");
                res.end('<h1>返回失败</h1>');
            }
            res.end(data);
        });
    } else if (url === "/about.html") {
        content = '<h1>关于我们</h1>';
        res.end(content);
    }

});
server.listen(80, () => {
    console.log("服务器运行在localhost");
})

****************************************************************************************************************************************************************************

复制代码
6、模块化概述
【1】目标:好处。CommonJS规范。Node.js中模块的三大分类。能够使用npm。规范的结构包。模块的加载机制
【2】解决复杂问题,而拆解成多个模块。小霸王游戏机:游戏机+游戏卡。把大文件拆分成多个独立、相互依赖的小文件
【3】好处:复用性、可维护性、按需加载。
【4】模块化规范:引入模块、暴露成员。约定大于配置。

****************************************************************************************************************************************************************************

复制代码
7、模块的分类与require的使用
【1】分类(和java好像呀):内置模块:fs path http
【2】自定义模块:用户创建的每一个js文件,都是一个自定义模块。
【3】第三方模块:第三方开发出来的模块,类似jar包。需要先下载才能使用。
【4】使用require()方法加载。require("fs")  require("./day.js")  require("moment");
console.log("加载了用户自定义模块...");
********************************
const day = require("./day.js"); // require他会执行引用模块的代码。
console.log(day);
*********************************  说明可以省略js的后缀名。
const day = require("./day");
console.log(day);

****************************************************************************************************************************************************************************

复制代码
8、模块作用域与module对象
【1】模块作用域。函数作用域。模块内的变量、方法,只能在模块内访问。出了模块就访问不到了。从打印的对象是{}空对象可以得出结论。
【2】好处:防止全局变量污染问题。
const name = "陈翔";

function say() {
    console.log("我是 " + name);
}
*************************************打印是空的
const day = require("./day");
console.log(day);
【3】如何向外共享模块作用域中的成员。module对象,每个js自定义模块都有一个module对象,它存储了当前模块的有关信息。
****************************************require拿到的对象,就是导入模块module.exports指向的对象,默认是{}
const name = "陈翔";

function say() {
    console.log("我是 " + name);
}

module.exports.name = "蘑菇头";
module.exports.say = function () {
    console.log("我是 球球");
};
**************************************************
const day = require("./day");
console.log(day);
day.say();
【4】如果module.exports指向新对象,就以新的为准。
const name = "陈翔";

function say() {
    console.log("我是 " + name);
}

module.exports.name = name;
module.exports.say = function () {
    console.log("我是 球球");
};
module.exports = {   // 以新的为准
    "newName": "闰土",
    sayHi() {
        console.log("Hi");
    }
}
******************************************
let day = require("./day");
console.log(day);

****************************************************************************************************************************************************************************

复制代码
10、exports对象
【1】说明exports与module.exports是一致的。
console.log(exports === module.exports);
***********************************************************
const name = "陈翔";
module.exports = {
    "name": name,
    "say": function () {
        console.log("大家好");
    }
}
*********************************************************
const day = require("./day");
console.log(day.name);
day.say();

****************************************************************************************************************************************************************************

复制代码
11、module.exports使用的误区
【1】都是以module.exports指向的对象为准。module.exports的优先级最高,那就直接用它好了,搞的花里胡哨的。
【2】使用两个反而会搞乱,就用module.exports={...}。时刻谨记require()模块时,得到的永远是module.exports指向的对象。

****************************************************************************************************************************************************************************

复制代码
12、模块化-CommonJS模块化规范
【1】module变量代表当前模块。module.exports是对外的接口。加载某个模块就是require()方法。

****************************************************************************************************************************************************************************

复制代码
13、npm包
【1】Node.js中第三方模块又叫包。jar包噗嗤。
【2】包的来源:第三方团队或个人开发者出来的,开源的提供所有人免费使用。
【3】包是基于内置模块API封装出来的,极大的提高了开发效率。类似于JQuery和浏览器内置API之间的关系。
【4】从哪里下载包?https://www.npmjs.com全球最大的包共享平台。下载包https://registry.npmjs.org
【5】npm包管理工具随着node一起安装的。cmd -> npm -v

****************************************************************************************************************************************************************************

复制代码
14、格式化时间两种方式比对
【1】传统方法VS npm包格式化。
// 格式化时间的方法
function dataF(dataStr) {
    const dt = padZero(new Date(dataStr));
    const y = padZero(dt.getFullYear());
    const m = padZero(dt.getMonth() + 1);
    const d = padZero(dt.getDate());
    const hh = padZero(dt.getHours());
    const mm = padZero(dt.getMinutes());
    const ss = padZero(dt.getSeconds());
    return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
}

// 补0函数
function padZero(n) {
    return n > 9 ? n : '0' + n;
}

module.exports = {
    dataF,
}
****************************************************************
const dateF = require("./day");
const dt = new Date();
console.log(dt);
console.log(dateF.dataF(dt));
【2】格式化时间的高级做法(npm)。安装moment包-导入-使用。
npm install 或者npm i
****************************************************************导入的名称就是安装时候的名称
const moment = require("moment");
const dt = moment().format("YYYY-MM-DD HH:mm:ss");  // 怎么用去NPM中心去查
console.log(dt);

****************************************************************************************************************************************************************************

复制代码
15、使用npm的注意点
【1】node_modules用来存放所有已安装到项目中的包。package-lock.json记录node_modules每个包的下载信息。
【2】千万不要手动修改node_modules或package-lock.json。
【3】指定版本号安装:npm i moment@2.22.2。执行完毕package-lock.json可以看到版本号变成了 "version": "2.22.2"。
【4】2.22.2。第一位数字代表大版本。第二位是功能版本。第三位是bug修复版本。规则:只要前面的版本号增长了,则后面的版本号归零。

****************************************************************************************************************************************************************************

复制代码
1、包管理配置文件
【1】npm规定在项目根目录中,必须提供一个叫做package.json的包管理配置文件。里面包号了:名称、版本号、指定开发与部署用到的包。
【2】在git上传共享代码时,就比如maven如果把jar包也上传太大了,有个package.json标记需要哪些jar包就可以了。所以一定要把node_modules文件夹添加到.gitignore忽略文件中。
【3】npm init -y 就可以快速创建package.json文件。这个命令只能在英文目录下运行,npm安装时,npm会自动记录包名+版本号。
【4】dependencies节点。专门用来记录npm命令安装了哪些包。npm i jquery art-template同时安装两个包。
{
  "name": "day1",
  "version": "1.0.0",
  "dependencies": {
    "art-template": "^4.13.2",
    "jquery": "^3.6.3",
    "moment": "^2.22.2"
  }
}
【5】如何一次安装所有包。只需要npm i或者npm install就可以全部安装。
【6】卸载包。npm uninstall 这个没有简写。npm uninstall moment。 npm i moment
【7】只在开发阶段用到,项目上线后不会用到,建议把包记录到devDependencies。如果开发与项目上线都需要记录到dependencies。
npm install 包名 -D 简写
npm install 包名 --save-dev 完整的

****************************************************************************************************************************************************************************

复制代码
2、解决下载包慢的问题
【1】因为默认是从国外https://registry.npmjs.org进行下载的,数据传输需要还低光缆,因此下载包速度很慢。
【2】淘宝npm镜像服务器。把国外的包克隆到淘宝服务器(镜像Mirror),然后从淘宝服务器下载。一些文章还是写着旧的淘宝 NPM 镜像 registry.npm.taobao.org,
但它已于 2022 年 05 月 31 日 废弃,读者需要更换为新的 registry.npmmirror.com 源。
*******************************查看当前从哪里下载
npm get registry
*******************************切换成淘宝镜像
npm config set registry=https://registry.npmmirror.com/
*******************************检查是否设置成功。
npm get registry
【3】npm i nrm -g 安装nrm小工具。注意配置node.js的安装路径添加到环境变量path
nrm ls
nrm use taobao

****************************************************************************************************************************************************************************

复制代码
3、npm与包
【1】项目包,被安装到node_modules目录中的包,都是项目包。开发依赖包devDependencies。核心依赖包dependencies。
npm -i 包名 -D开发依赖包。npm i 包名 核心依赖包。
【2】全局包,npm i 包名 -g,就是全局包。会放到自己配置的node_global里面,但是我以前配置错了,日尼玛。配置到node_cache里了,卧槽!!!
npm uninstall 包名 -g。卸载全局包。只有工具性的包,才会会使用全局安装,不然就没有必要。也可以参考文档的使用说明。
【3】i5ting_toc可以把md文档转换为html的小工具。
***********************************全局安装
npm install -g i5ting_toc
***********************************转换命令,把md转换为html
i5ting_toc -f 1.md -o
【4】包必须以单独的目录而存在。在包的顶级目录必须包含package.json包管理配置文件。package.json必须包含name/version/main三个属性。

****************************************************************************************************************************************************************************

复制代码
4、发布包-开发自己的包
【1】创建my_tool,创建package.json、index.js、README.md
****************************************初始化package.json
{
  "name": "my_tool",
  "version": "1.0.0",
  "main": "index.js",
  "description": "格式化时间",
  "keywords": [
    "my",
    "tool"
  ],
  "license": "ISC"
}
****************************************定义格式化时间方法
// 格式化时间的方法
function dataF(dataStr) {
    const dt = padZero(new Date(dataStr));
    const y = padZero(dt.getFullYear());
    const m = padZero(dt.getMonth() + 1);
    const d = padZero(dt.getDate());
    const hh = padZero(dt.getHours());
    const mm = padZero(dt.getMinutes());
    const ss = padZero(dt.getSeconds());
    return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
}

// 补0函数
function padZero(n) {
    return n > 9 ? n : '0' + n;
}

module.exports = {
    dataF,
}
*****************************************没有指定index.js,还可以通过package的"main": "index.js",来检索到。
const dt = require("./my_tool");
const dtStr = dt.dataF(new Date());
console.log(dtStr);
【2】不同js的暴露与引用!!!!!!!!!!!!!!!!!
**************************************************************************
// ./src/say.js  进一步拆分为更细的模块(模块的拆分)
function say() {
    console.log("我叫...");
}

module.exports = {
    say,
}
**************************************************************************
// 格式化时间的方法
function dataF(dataStr) {
    const dt = padZero(new Date(dataStr));
    const y = padZero(dt.getFullYear());
    const m = padZero(dt.getMonth() + 1);
    const d = padZero(dt.getDate());
    const hh = padZero(dt.getHours());
    const mm = padZero(dt.getMinutes());
    const ss = padZero(dt.getSeconds());
    return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
}

// 补0函数
function padZero(n) {
    return n > 9 ? n : '0' + n;
}

const say = require("./src/say"); // !!!!!!!!!!!!!!!!!注意

module.exports = {
    dataF,
    ...say,// !!!!!!!!!!!!!!!!!注意
}
【3】编写包的说明文档
##安装方式
```
npm i my_tool
```
##导入方式
```js
const my_tool=require("my_tool");
```
##格式化时间
```js
const dt = require("./my_tool");
const dtStr = dt.dataF(new Date());
console.log(dtStr);
```
##说话
```js
dt.say();
```

****************************************************************************************************************************************************************************

复制代码
8、发布包
【1】注册npm账号。访问https://www.npmjs.com 注册。邮箱账号密码很重要。账号验证通过就可以发布包了。
【2】npm login注意不要登录到淘宝服务器了。nrm use npm(切换到官方服务器)。
【3】把包发布到npm上。终端切换到包的根目录之后(my_tool目录下),运行npm publish即可发布到npm上(注意不能重名)
【4】删除已经发布的包。npm unpublish 包名 --force命令。只能删除72个小时内的包。通过此命令删除的24小时内不能重复发布。尽量不要往npm上发布没有意义的包。

****************************************************************************************************************************************************************************

复制代码
9、模块的加载机制
【1】模块会被缓存,就意味着多次调用require()不会导致模块代码的多次执行(这个自己注意到过)。
【2】无论自带、自定义、三方都会有限从缓存中加载。从而提高模块的加载效率。
【3】内置模块加载优先级最高。自定义的重名想被加载,需要使用./或../开头。如果require()导入自定义模块,如果省略了扩展名。node.js会分别尝试一下文件。
确切文件名-补全.js-补全.json-补全.node扩展名依次进行加载。
【4】第三方模块的加载机制:如果没有以./或../开头。会从当前模块的父目录开始,常识从./node_modules文件夹中加载第三方模块。
【5】目录作为模块的加载方式:首先查找package.json文件,或者main入口不存在或无法解析,则node.js试图加载目录下index.js文件。

****************************************************************************************************************************************************************************

复制代码
10、express概述并创建Web服务器
【1】目标:express.static托管资源。express路由精简项目结构。express中间件。express API接口。express中启用跨域资源共享。
【2】express概述:和node.js内置的http类似。是一个npm上的三方包。快速、开放、极简的Web服务器框架。(类似于浏览器中API与JQuery的关系)
【3】express能干什么?干了java干的活,Web网站服务器或API接口服务器。
【4】基本使用
*******************************************************安装
npm i express@4.17.1
******************************************************导入+启动
const express = require("express");
const app = express();
app.listen(80, () => {
    console.log("服务在localhost启动了...")
})

****************************************************************************************************************************************************************************

复制代码
11、监听get与post请求&参数处理
【1】如果访问localhost,根据get还是post返回不同内容。
const express = require("express");
const app = express();
app.listen(80, () => {
    console.log("服务在 http://127.0.0.1 启动了...");
});
app.get("/", function (req, res) {
    res.send({
        name: "陈翔",
        age: 26
    });
});
app.post("/", function (req, res) {
    res.send("请求成功"); //!!!!!!!!!!!!!!
});
【2】获取url中携带的参数。http://localhost/?name=zs&age=20  能把{"name":"zs","age":"20"}显示在页面。
const express = require("express");
const app = express();
app.listen(80, () => {
    console.log("服务在 http://127.0.0.1 启动了...");
});
app.get("/", function (req, res) {
    res.send(req.query);
});
app.post("/", function (req, res) {
    res.send("请求成功");
});
【3】获取URL中的动态参数,完全没必要,我用java 哈哈哈
********************************************************************req.params
const express = require("express");
const app = express();
app.listen(80, () => {
    console.log("服务在 http://127.0.0.1 启动了...");
});
app.get("/:id", function (req, res) { // !!!!!!!!!!!!!!!/:id/:name
    res.send(req.params);// !!!!!!!!!!!!!!!
});
app.post("/", function (req, res) {
    res.send("请求成功");
});
********************************************************************请求
http://localhost/:6

****************************************************************************************************************************************************************************

复制代码
12、express-静态资源处理
【1】express.static()的使用
***********************************************
const express = require("express");
const app = express();
app.listen(80, () => {
    console.log("服务在 http://127.0.0.1 启动了...");
});
app.use(express.static("../day1")); // 好用呀
***********************************************访问,能看到Main.js的内容
http://localhost/Main.js
【2】托管多个静态资源路径。多次调用app.use(express.static("../day1"));   app.use(express.static("../day2"));如果文件相同,会优先展示day1下面的文件。
【3】挂载路径前缀。没必要的操作...
app.use("/public",express.static("../day1"));  // 访问 http://localhost/public/Main.js

****************************************************************************************************************************************************************************

复制代码
13、express-安装使用nodemon
【1】能够热加载,重启项目。
npm install -g nodemon
【2】nodemon的使用,在WebStorm打开终端。执行
********************************************************************************!!!!!!!!!
nodemon Main.js
********************************************************************************
const express = require("express");
const app = express();
app.listen(80, () => {
    console.log("服务在 http://127.0.0.1 启动了...");
});
app.use("/public", express.static("../day1"));
********************************************************************************
只要Ctrl+s就可以了。重新启动了!!!

****************************************************************************************************************************************************************************

复制代码
1、Express路由
【1】概念:现实中的路由,拨号码对应每个人之间的映射关系。客户端的请求与服务器处理函数之间的映射关系。
【2】其实就是路径对应Controller函数。哪有java牛批???
【3】使用案例
const express = require("express");
const app = express();
//挂载路由
app.get("/", (req, res) => {
    res.send("客户端发起的get请求")  //!!!!!!!!!!!
});
app.post("/", (req, res) => {
    res.send("客户端发起了post请求") //!!!!!!!!!!!
})
app.listen(80, () => {
    console.log("服务在 http://127.0.0.1 启动了...");
});
app.use("/public", express.static("../day1"));

****************************************************************************************************************************************************************************

复制代码
2、路由的模块化
【1】都挂载app太多了,需要抽离为单独的模块。创建路由模块的.js文件,调用express.Router()函数创建路由对象。
***********************************************************router.js创建
// 1.导入express
const express = require("express");
// 2.创建路由对象
const router = express.Router();
// 3.挂载具体路由
router.get("/user/list", (req, res) => {
    res.send("客户端发起了get /user/list")
})
router.post("/user/add", (req, res) => {
    res.send("发起添加用户post请求")
})
// 4.向外导出对象
module.exports = router;
***********************************************************app.use(router)注册路由模块
const express = require("express");
const app = express();
const router = require("./router");
app.use(router);
app.listen(80, () => {
    console.log("服务在 http://127.0.0.1 启动了...");
});
【2】为路由模块添加前缀,请求就会变成 localhost/before/user/list
const express = require("express");
const app = express();
const router = require("./router");
app.use("/before", router); //!!!!!!!!!!!!!!!!!!!!!!!!
app.listen(80, () => {
    console.log("服务在 http://127.0.0.1 启动了...");
});

****************************************************************************************************************************************************************************

复制代码
3、中间件的概念
【1】中间件特指业务流程中的处理环节。处理污水,达到可排放。中间可能有三个处理环节。1 2 3级处理环节就是中间件。
【2】express中间件的调用流程,可以连续调用多个中间件,对这次请求进行预处理。
【3】express中间件本质上是一个function处理函数。他必须包含next()参数。不包含就是路由处理函数。
【4】next函数是多个中间件连续调用的关键。他表示把流转关系交给下一个中间件或路由。

****************************************************************************************************************************************************************************

复制代码
4、定义中间件函数
【1】中间件函数
const express = require("express");
const app = express();
// 定义中间件函数
const mw = function (req, res, next) {
    console.log("最简单的中间件函数")
    // 流转关系给下一个中间件或路由
    next()
}
app.listen(80, () => {
    console.log("服务在 http://127.0.0.1 启动了...");
});
【2】定义全局中间件函数
const express = require("express");
const app = express();
// 定义中间件函数
const mw = function (req, res, next) {
    console.log("最简单的中间件函数")
    // 流转关系给下一个中间件或路由
    next()
}
app.use(mw); //!!!!!!!!!!!!!!
app.get("/", (req, res) => {
    res.send("客户端发起get请求");
})
app.get("/1", (req, res) => {
    res.send("客户端发起get1请求");
})
app.listen(80, () => {
    console.log("服务在 http://127.0.0.1 启动了...");
});
【3】全局中间件的简化形式
const express = require("express");
const app = express();
// 定义中间件函数
/*const mw = function (req, res, next) {
    console.log("最简单的中间件函数")
    // 流转关系给下一个中间件或路由
    next()
}*/
app.use((req, res, next) => {  //!!!!!!!!!!!!!!
    console.log("最简单的中间件函数")
    // 流转关系给下一个中间件或路由
    next()
});
app.get("/", (req, res) => {
    res.send("客户端发起get请求");
})
app.get("/1", (req, res) => {
    res.send("客户端发起get1请求");
})
app.listen(80, () => {
    console.log("服务在 http://127.0.0.1 启动了...");
});
【4】中间件的作用。多个中间件可以共享一份req和res的。比如记录请求到达服务器的时间。
const express = require("express");
const app = express();
// 定义中间件函数
/*const mw = function (req, res, next) {
    console.log("最简单的中间件函数")
    // 流转关系给下一个中间件或路由
    next()
}*/
app.use((req, res, next) => {
    // 获取当前到达服务器时间
    req.startTime = Date.now();
    req.msg = "中间件先消费..."
    console.log("最简单的中间件函数")
    // 流转关系给下一个中间件或路由
    next()
});//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
app.get("/", (req, res) => {
    res.send(req.msg + "客户端发起get请求" + req.startTime);
})
app.get("/1", (req, res) => {
    res.send(req.msg + "客户端发起get1请求" + req.startTime);
})
app.listen(80, () => {
    console.log("服务在 http://127.0.0.1 启动了...");
});
【5】定义多个中间件
const express = require("express");
const app = express();
// 定义中间件函数
/*const mw = function (req, res, next) {
    console.log("最简单的中间件函数")
    // 流转关系给下一个中间件或路由
    next()
}*/
app.use((req, res, next) => { //!!!!!!!!!!!!!!!
    // 获取当前到达服务器时间
    req.startTime = Date.now();
    req.msg = "中间件先消费..."
    console.log("最简单的中间件函数")
    // 流转关系给下一个中间件或路由
    next()
});
app.use((req, res, next) => {//!!!!!!!!!!!!!!!
    // 获取当前到达服务器时间
    req.msg2 = "第二个中间件再消费..."
    // 流转关系给下一个中间件或路由
    next()
});
app.get("/", (req, res) => {
    res.send(req.msg + req.msg2 + "客户端发起get请求" + req.startTime);
})
app.get("/1", (req, res) => {
    res.send(req.msg + req.msg2 + "客户端发起get1请求" + req.startTime);
})
app.listen(80, () => {
    console.log("服务在 http://127.0.0.1 启动了...");
});

****************************************************************************************************************************************************************************

复制代码
5、局部生效中间件
【1】局部中间件函数
const express = require("express");
const app = express();
// 定义中间件函数
const mw = function (req, res, next) {
    req.msg = "我是中间件函数"
    // 流转关系给下一个中间件或路由
    next()
}
app.get("/", mw, (req, res) => { // !!!!!!!只有这个生效,因为三个参数,多了mw
    res.send(req.msg + "客户端发起get请求" + req.startTime);
})
app.get("/1", (req, res) => {
    res.send(req.msg + "客户端发起get1请求" + req.startTime);
})
app.listen(80, () => {
    console.log("服务在 http://127.0.0.1 启动了...");
});
【2】使用多个局部中间件
const express = require("express");
const app = express();
// 定义中间件函数
const mw = function (req, res, next) {
    req.msg = "我是中间件函数..."
    // 流转关系给下一个中间件或路由
    next()
}
const mw1 = function (req, res, next) {
    req.msg1 = "我是中间件函数2..."
    // 流转关系给下一个中间件或路由
    next()
}
app.get("/", mw, mw1, (req, res) => {
        res.send(req.msg + req.msg1 + "客户端发起get请求");
    }
)
app.get("/1", (req, res) => {
    res.send(req.msg + "客户端发起get1请求");
})
app.listen(80, () => {
    console.log("服务在 http://127.0.0.1 启动了...");
});

****************************************************************************************************************************************************************************

复制代码
6、中间件的使用注意点
【1】一定要在路由之前定义中间件。可以连续调用多个中间件。不要忘记使用next()函数。在使用next()后不要再写代码了。多中间件共享req res的,可以挂载属性。

****************************************************************************************************************************************************************************

复制代码
7、中间件的分类
【1】应用级别中间件。路由级别中间件。错误级别中间件。express内置中间件。第三方的中间件。
【2】应用级别绑定在app.use上。express.Router()绑定的叫做路由级别的。
【3】错误级别的中间件是绑定项目中专门捕获发生的异常错误。从而防止崩溃。app.use(function(err,req,res,next))...
***************************************************************************错误级别中间件放在所有的路由之后
const express = require("express");
const app = express();

app.get("/", (req, res) => {
        throw new Error("服务器错误");
        res.send("get请求");
    }
)
// 定义错误中间件 捕获错误 防止崩溃(全局)
app.use((err, req, res, next) => {
    console.log("发生错误" + err.message);
    res.send("错误信息:" + err.message)
})

app.listen(80, () => {
    console.log("服务在 http://127.0.0.1 启动了...");
});
【4】Express内置中间件。解析客户端发起请求参数用的,不用深入掌握。
【5】第三方中间件。body-parser三方中间件。

****************************************************************************************************************************************************************************

复制代码
8、自定义中间件
【1】模拟express.urlencoded中间件。

****************************************************************************************************************************************************************************

复制代码
9、编写接口?API路由模块
【1】怎么又来了一遍?
// 1.导入express
const express = require("express");
// 2.创建路由对象
const router = express.Router();
// 3.挂载具体路由
router.get("/user/list", (req, res) => {
    res.send("客户端发起了get /user/list")
})
router.post("/user/add", (req, res) => {
    res.send("发起添加用户post请求")
})
// 4.向外导出对象
module.exports = router;
************************************************************
const express = require("express");
const app = express();
// 导入模块
const router = require("./router")
app.use(router);

app.listen(80, () => {
    console.log("服务在 http://127.0.0.1 启动了...");
});

****************************************************************************************************************************************************************************

复制代码
12、编写接口跨域问题
【1】CORS,主流解决方法,一定要在路由之前配置。也是一个中间件。
npm install cors
*******************************************
const cors=require("cors");
*******************************************
app.use(cors())
【2】什么是CORS,跨域资源共享。同源安全策略,配置CORS的的相关HTTP影响头,可以解决浏览器端的跨域访问限制。
【3】注意点:CORS主要在服务端配置,客户端不用。

****************************************************************************************************************************************************************************

复制代码
13、跨域三个响应头
【1】Access-Control-Allow-Origin。可以指定特定网址,也可以指定*
【2】Access-Control-Allow-Headers。
【3】Access-Control-Allow-Methods。默认支持GET POST HEAD请求,如果需要PUT DELETE请求,需要配置这个。

****************************************************************************************************************************************************************************

复制代码
14、CORS的请求分类
【1】简单请求:请求方式是GET POST HEAD之一  & HTTP头部信息是常用的字段
【2】预检请求:GET POST HEAD || 包含自定义头部字段 || 向服务器发送了application/json格式的数据。请求后服务器返回允许后,才会发送真正请求。
【3】简单请求与预检请求的区别:

****************************************************************************************************************************************************************************

复制代码
数据库与身份认证:
【1】配置mysql
【2】认识sql语句
【3】express操作数据库
【4】Session的实现原理
【5】JWT的实现原理

****************************************************************************************************************************************************************************

复制代码
1、Web开发模式
【1】基于服务端渲染的传统Web开发模式。
*******************************************************优点
前端耗时少、有利于SEO
*******************************************************缺点
占用服务端资源、不利于前后端分离,开发效率低
【2】基于前后端分离的新型Web开发模式,依赖于Ajax技术的广泛引用。后端只负责API接口,前端使用ajax调用接口的开发模式
*******************************************************优点
开发体验好、用户体验好、减轻了服务器端的渲染压力
*******************************************************缺点
不利于SEO
【3】如何选择Web开发模式?需要结合业务场景。

****************************************************************************************************************************************************************************

复制代码
2、身份认证、身份验证、鉴权
【1】通过一定手段完成对用户身份的确认。保证业务的安全性。
【2】服务端渲染推荐使用Session认证机制。使用前后端分离推荐使用JWT认证机制

****************************************************************************************************************************************************************************

复制代码
3、Session原理
【1】HTTP协议的无状态性。每次http请求是独立的,多次请求,服务器不会主动保留每次http请求的状态。
【2】如何突破http无状态的限制。超市办法VIP会员卡,绑定你的手机号为会员。3分
【3】Cookie 是存储在用户浏览器的一段不超过4KB的字符串。有效期、安全性、使用范围。特性:自动发送、域名独立、过期时限、4KB限制。
【4】Cookie在身份认证中的作用,客户端登录)—>服务器发Cookie给浏览器—>浏览器存本地,通过请求头发送给服务器,完成身份标记—>交互。
【5】Cookie不具有安全性。因为客户端的Cookie很容易被伪造。重要的隐私数据不要存储重要的隐私信息。
【6】提高身份认证的安全性。客户出示会员卡+刷卡认证或输入手机号查询。这就是Session认证机制的精髓。
【7】客户端登录—>服务器验证通过后,开辟内存将对应账号密码生成Cookie字符串发给浏览器—>浏览器存Cookie到本地—>请求的时候发送给服务器。

****************************************************************************************************************************************************************************

复制代码
5、JWT
【1】Session认证机制需要配合Cookie才能实现,由于它不支持跨域访问,所以当前后端分离开发的时候,需要做额外的配置,才能实现跨域Session认证。
【2】所以不存在跨域直接使用Session认证即可。但是存在跨域就要使用JWT跨域认证解决方案。
【3】JWT的工作原理。客户端发起请求—>服务端验证账号密码后,经过加密生成token,发送给浏览器。—>浏览器存到LocalStorage或SessionStorage中—>请求是通过Authorization发送给服务器
—>服务器把token字符串还原成信息“对象”。
【4】JWT组成部分:Header+Payload+Signature。使用英文的.分割。Payload才是真正的用户信息。
{id:3,username:"admin"}—>Payload,而Header、Signature是为了保证token的安全性。
【5】JWT的使用方式,通常放在localStorage或者sessionStorage中。推荐做法是把JWT放在HTTP请求头的Authorization字段中。
相关推荐
水w1 天前
Node.js windows版本 下载和安装(详细步骤)
开发语言·前端·windows·npm·node
getaxiosluo6 天前
node对接ChatGpt的流式输出的配置
人工智能·ai·chatgpt·状态模式·node·数据流
程楠楠&M7 天前
mongoDB的安装及使用
前端·数据库·mongodb·node
fukaiit9 天前
vue项目npm run serve出现【- Network: unavailable】(从排查到放弃)
npm·vue·node·win11
胡西风_foxww19 天前
nodejs爬虫系统
爬虫·nodejs·node·系统·express·request·cheerio
你不讲 wood24 天前
预览 PDF 文档
开发语言·前端·javascript·pdf·html·node·文件预览
27669582921 个月前
大众点评 web mtgsig 1.2分析
java·python·node·美团·大众点评·mtgsig
mez_Blog1 个月前
前端学习笔记(2.0)
前端·笔记·学习·node·nvm
杰哥的技术杂货铺2 个月前
Linux 系统 nvm 管理node无法使用
linux·node·nvm·libstdc++.so.6·libm.so.6
itas1092 个月前
Electron获取nodejs和chrome版本信息
javascript·chrome·electron·nodejs·node