Node.js学习(三)----- 实战(vue-cli插件)
1、mongoDB
- 下载地址:http://dl.mongodb.org/dl/win32/x86_64
- 安装教程:https://www.cnblogs.com/zhoulifeng/p/9429597.html
- 数据库基础
- 关系型数据库:mysql、sql、oracle 非关系型数据库:MongoDB
- 常用命令
1、show dbs ----- 查看所有数据库 2、use dbName ----- 使用或者创建数据库 3、db.dropDatebase() ---- 删除当前所在的数据库 4、show collections ----- 查看当前数据库的所有表格(集合) 5、添加数据的同时创建表 添加一条:db.表名.insert/save({"name":"wxh","age":"24"}) 添加多条:db.表名.insert/save([{},{}...]) 6.db.表名.drop() ----- 删除指定的表 7.db.表名.remove({条件}) ----- 删除符合条件的文档,当条件为空时,清空所有数据 8、db.表名.update({条件}).{$set{键值对},false,true} 第二个参数表示是否新增,第三个参数表示是否修改多条 9、db.表名.find().sort({age:1}) ----- 排序:升序 db.表名.find().sort({age:-1}) ----- 排序:降序 10、分页 db.表名.find().skip().limit() ----- limit的参数表示页的大小,skip可以设置为(page - 1)*pageSize 11、条件查询 大于22:db.表名.find({age:{$gt:22}}) 小于等于22:db.表名.find({age:{$lte:22}}) (且关系)>=23<=26:db.表名.find({age:{$gte:23,$lte:26}}) (或关系)name=wxh 或者 age > 20:db.表名.find({$or,[{name:"wxh"},{age:{$gt:20}}]})
- 数据库的操作命令(用管理员身份打开)
net start MongoDB ----- 数据库启动 net stop MongoDB ----- 数据库的停止
- 连接数据库(在安装的bin目录下打开命令行)
mongo
-
- mongo 使用权限认证
1>mongo use admin 2>添加用户(超级用户): db.createUser({user:"wangxh",pwd:"wangxh123456",roles:[{"role":"userAdmin","db":"admin"},{"role":"root","db":"admin"},{“role":"userAdminAnyDatabase","db":"admin"}]}) 3>show users db.dropAllUsers()可以删除所有用户 4>删除无auth登陆的服务:sc delete MongoDB WIN+R 输入:SERVICES.MSC,找到MongoDB服务进行右键停止; 5>与bin同级新建配置文件mongod.cfg # Where and how to store data. 数据库路径 dbpath = D:\c-wangxh\software\MongoDB\Server\3.6\data\db # Where to write logging data. 日志输出文件路径 logpath = D:\c-wangxh\software\MongoDB\Server\3.6\data\log\mongo.log # 错误日志采用追加模式 logappend = true # 启用日志文件,默认启用 journal = true # 这个选项可以过滤掉一些无用的日志信息,若需要调试使用请设置false quiet = true # 端口号 port = 27017 bind_ip = 0.0.0.0 # 开启身份认证 auth = true 6>管理员身份重新注册需要auth的服务:
mongod -dbpath "D:\c-wangxh\software\MongoDB\Server\3.6\data\db" -logpath "D:\c-wangxh\software\MongoDB\Server\3.6\data\log\mongo.log" --auth --config "D:\c-wangxh\software\MongoDB\Server\3.6\mongod.cfg" -install -serviceName "MongoDB" 注意:有的电脑报错error reading config file:No such file or directory
解决方法:与bin同级的配置文件mongod.cfg改为mongo.config文件
7> 输入mongo show dbs 无权限 进行认证 use admin 然后db.auth("wangxh","wangxh123456"),输出1表示认证成功 第二种直接使用mongo localhost:27017/admin --username admin --password admin 在bin目录下权限认证操作数据库 8>打开控制面板 windows防火墙 高级设置 新建入站规则(端口-TCP/特定本地端口-允许连接-域/专用/公用) 9>express中连接权限数据库
const mongoose =require("mongoose"); url = 'mongodb://wangxh:wangxh123456@127.0.0.1:27017/wxh0929?authSource=admin
mongoose.connect(url);
- mongo 使用权限认证
2、Express框架
- Express是一个基于Node.js的平台,快速、开放、极简的web开发框架;
- Express框架是后台的Node框架,所以和jquery、zepto、bootstrap等都不是一个东西,Express在后台的受欢迎程序类似前端的jquery,都是企业的事实上的标准;
- 安装
npm/cnpm install -g express
Express的脚手架:npm/cnpm install -g express-generator express自动生成项目 安装成功的标志:express --version - 启动
//使用 express-generator 快速生成项目 1、express 文件夹名 ----- 生成一个文件夹 2、cd 文件夹 3、cnpm i 4、npm start
- 全局设置允许跨域,在app.js中引入代码
app.all("*", (req, res, next) => { res.header( "Access-Control-Allow-Origin", req.headers.origin || req.headers.referer || "*" ); res.header( "Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With" ); res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS"); res.header("Access-Control-Allow-Credentials", true); //可以带cookies res.header("X-Powered-By", "Express"); if (req.method == "OPTIONS") { res.sendStatus(200); } else { next(); } });
- 项目中引入eslint
- 编辑器安装eslint插件,保证可用,并且安装依赖
1、全局安装eslint cnpm i eslint babel-eslint -g 2、安装插件 cnpm i eslint eslint-config-prettier eslint-config standard eslint-loader eslint-plugin-import eslint-plugin-node eslint-plugin-prettier eslint-plugin-promise prettier --save-dev
- eslint --init创建.eslintrc.js文件
module.exports = { env: { node: true, commonjs: true }, extends: [ 'standard' ], parserOptions: { ecmaVersion: 12 }, rules: { 'no-unused-vars': [ 2, { vars: 'all', args: 'after-used' } ], // 不能有声明后未被使用的变量或参数 semi: [ 2, 'always' ], // 语句强制分号结尾 quotes: [1, 'single'], // 建议使用单引号 'no-redeclare': [ 2, { builtinGlobals: true } ] // 不允许重复声明 } };
- 创建.eslintignore文件
/node_modules/
- 编辑器安装eslint插件,保证可用,并且安装依赖
- 项目热加载部署
- 安装:npm i -g nodemon
- 项目目录下创建nodemon.json文件
{ "restartable": "rs",//restartable-设置重启模式 "ignore": [".git", ".svn", "node_modules/**/node_modules"],//ignore-设置忽略文件 "verbose": true,//verbose-设置日志输出模式,true 详细模式 "execMap": {//execMap-设置运行服务的后缀名与对应的命令 "js": "node --harmony"//表示使用 nodemon 代替 node }, "watch": [],//watch-监听哪些文件的变化,当变化的时候自动重启 "env": { "NODE_ENV": "development" }, "ext": "ejs js json css html"//监控指定的后缀文件名 }
- app.js文件:
var debug = require('debug')('my-application'); // debug模块 app.set('port', process.env.PORT || 3000); // 设定监听端口 //启动监听 var server = app.listen(app.get('port'), function() { debug(chalk.cyan(
'Express server listening on port ' + server.address().port
)); }); //module.exports = app;//这是 4.x 默认的配置,分离了 app 模块,将它注释即可,上线时可以重新改回来
- 启动:nodemon app.js
- 项目中使用debug模式
app.js中 // debug模块 const debug = require('debug')('vue-cli-plugin-generate:server'); app.set('port', process.env.PORT || 3000); // 设定监听端口 // 启动监听 const server = app.listen(app.get('port'), function () { console.log(); console.log(); debug(chalk.cyan('Express server listening on port ' + server.address().port)); console.log(); }); //启动命令: $env:DEBUG="vue-cli-plugin-generate:server";nodemon app.js
- 项目中引入日志中间件(仅仅4.0版本以上的express支持)
- 安装
cnpm i morgan --save
- 引入 ,在app.js中
//express的默认日志中间件 const logger = require('morgan'); const fs = require('fs'); const path = require('path') //当然,一个线上应用,如果所有的日志都落地到一个本地文件,时间久了,,文件非常大会影响性能,使用日志分割插件,可以进行日志分割 const FileStreamRotator = require('file-stream-rotator'); //建立日志目录,如果不存在则创建目录 const logDir = path.join(__dirname,'logs'); fs.existsSync(logDir) || fs.mkdirSync(logDir); //自定义token,即日志的时间 logger.token('localDate',function getDate(){ return new Date().toLocalString() }) const accessLogStream = FileStreamRotator.getStream({ data_format: 'YYYYMMDDhh',//日志文件按小时记录 filename: path.join(logDir, 'access_%DATE%.log), frequency: 'daily, verbose: false }) //对日志进行格式化 logger.format('combined' , ':remote-addr - :remote-user [:localDate] ":method :url HTTP/:http-version " :status ":referrer" ":user-agent" ); //运用中间件,‘combined’是日志显示的格式 app.use(logger('combined' ,{stream : accessLogStream}))
- 安装
- 对项目中的数据进行加密
- MD5以及SHA
const crypto = require('crypto'); //createHash的参数可以是md5 sha1 sha256 sha512 const cryptoSignature = crypto.createHash('sha1').update(signature).digest('hex').toUpperCase();
- MD5以及SHA
3、KOA框架
- 简介
koa是Express的下一代基于Node.js的web开发框架,目前有1.x和2.0两个版本。
- Express与koa1、koa2的区别
1 express ----- 使用回调函数实现异步; 2 koa1 ----- generator实现异步,但是generator的本意并不是异步。Promise才是为异步设计的,但是Promise的写法……想想就复杂。为了简化异步代码,ES7(目前是草案,还没有发布)引入了新的关键字async和await,可以轻松地把一个function变为异步模式: 3 koa2 ----- 使用Promise并配合async来实现异步
- 安装
npm/cnpm install -g koa koa的脚手架:npm/cnpm install -g koa-generator koa自动生成项目 安装成功的标志:express --version
- 启动
//使用 koa-generator 快速生成项目 1、koa2 文件夹名 ----- 生成一个文件夹 2、cd 文件夹 3、cnpm i 4、npm start
- vs启动过程中报错
解决方法:使用管理员身份打开命令行,执行命令行 set-ExecutionPolicy RemoteSigned,输入Y后,解决问题;
再次在vs中输入koa,显示
文件目录:
- 使用插件koa-log4,管理Node.js的访问日志与系统日志
- 建立一个配置文件log4.js
const path = require('path'); /** * 管理nodeJs访问日志、系统日志 */ const koaLog4 = require('koa-log4'); koaLog4.configure({ appenders: { // 访问日志 access: { type: 'dateFile', pattern: '-yyyy-MM-dd.log', // 通过日期来生成文件 alwaysIncludePattern: true, // 文件名始终以日期区分 encoding: 'utf-8', filename: path.join('logs/access', 'access.log') // 生成文件路径和文件名 }, // 系统日志 application: { type: 'dateFile', pattern: '-yyyy-MM-dd.log', // 通过日期来生成文件 alwaysIncludePattern: true, // 文件名始终以日期区分 encoding: 'utf-8', filename: path.join('logs/application', 'application.log') // 生成文件路径和文件名 }, out: { type: 'console' } }, categories: { default: { appenders: ['out'], level: 'info' }, access: { appenders: ['access'], level: 'info' }, application: { appenders: ['application'], level: 'WARN' } } }); exports.accessLogger = () => koaLog4.koaLogger(koaLog4.getLogger('access')); // 记录所有访问级别的日志 exports.systemLogger = koaLog4.getLogger('application'); // 记录所有应用级别的日志
- app.js中引入
const logger = require('koa-logger'); /** * 管理nodeJs访问日志、系统日志 */ const koaRouter = require('koa-router'); const router = new koaRouter(); const { accessLogger, systemLogger } = require('./config/log4'); // 捕获全局状态下的error app.on('error', err => { systemLogger.error(err); }); app.use(accessLogger());
- 将自动生成logs目录文件
- 建立一个配置文件log4.js
- 模板引擎Nunjucks
- 安装
cnpm i koa-nunjucks-2 --save
- app.js文件进行引入
/** * 接入模板引擎koa-nunjucks-2 */ const koaNunjucks = require('koa-nunjucks-2'); const path = require('path'); /** * 配置好 koa-nunjucks-2 中间件之后,它默认会在请求上下文ctx上增加 render()方法,通过调用 ctx.render('模板名', 数据) 就可以渲染页面, * 放在使用路由前面,否则报错:ctx.render() 不是一个 function */ app.use(koaNunjucks({ ext: 'html', // 使用HTML后缀的模板 path: path.join(__dirname, 'views'), // 模板所在路径 nunjucksConfig: { // nunjucks的配置 trimBlocks: true// 开启转义,xss漏洞 } }));
- 模板渲染示例:views下新建index.html文件夹
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{{title}}</title> </head> <body> <h1>{{content}}</h1> </body> </html>
- routers下面的index.js
/** * koa-router这个middleware,负责处理URL映射 */ const router = require('koa-router')(); router.get('/', async (ctx, next) => { await ctx.render('index', { title: '自动化生成vue模板', content: 'welcome' }); });
- 浏览器输入localhost:3000
- 安装
4、mySQL + sequelize
- 安装
1、cnpm i mysql mysql2 sequelize sequelize-cli --save //sequelize sequelize-cli安装成全局的,这样就可以在任意的 Node.js项目中都直接运行 sequelize 命令,而不用每一个项目都单独安装 2、sequelize init //初始化,通过命令创建 sequelize需要的目录和相关代码的。
- sequlize初始化生成的文件
5、开发插件基本步骤
- 创建一个vue-cli-plugin-generate目录;
- 执行命令npm init,进行npm初始化,执行上述命令的时候,可以使用默认值,也可以自定义,此时此目录下会生成一个package.json文件,存储项目信息。
{ "name": "vue-cli-plugin-generate", "version": "1.0.0", "description": "A cli tool for auto-generating vue template component", "private": false, "author": { "email": "m1660133XXXX@163.com", "name": "北栀女孩儿" }, "bin": { "generate": "bin/www" }, "keywords": [ "vue", "cli", "generate", "vue-cli-generate", "node", "koa" ], "scripts": { "start": "node bin/www", "dev": "./node_modules/.bin/nodemon bin/www", "prd": "pm2 start bin/www", "test": "echo \"Error: no test specified\" && exit 1", "lint": "eslint --ext .js src --fix" }, "dependencies": { "chalk": "^4.1.0", "debug": "^4.1.1", "jquery": "^3.6.0", "koa": "^2.7.0", "koa-bodyparser": "^4.2.1", "koa-convert": "^1.2.0", "koa-json": "^2.0.2", "koa-log4": "^2.3.2", "koa-logger": "^3.2.0", "koa-nunjucks-2": "^3.0.2", "koa-onerror": "^4.1.0", "koa-router": "^7.4.0", "koa-static": "^5.0.0", "koa-views": "^6.2.0", "nunjucks": "^3.2.3", "pug": "^2.0.3" }, "devDependencies": { "eslint": "^7.23.0", "eslint-config": "^0.3.0", "eslint-config-prettier": "^8.1.0", "eslint-loader": "^4.0.2", "eslint-plugin-import": "^2.22.1", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^3.3.1", "eslint-plugin-promise": "^4.3.1", "nodemon": "^1.19.1", "prettier": "^2.2.1", "standard": "^16.0.3" }, "repository": { "type": "git", "url": "" }, "publishConfig": { "registry": "" }, "license": "ISC" }
- 基本项目搭建完成,最终的项目目录为:
utils文件
- app.js文件
const Koa = require('koa'); /** * Koa 导入的是一个类 */ const app = new Koa(); /** * 模板引擎 */ const views = require('koa-views'); const json = require('koa-json'); const onerror = require('koa-onerror'); /** * middlewares 用来处理post请求 */ const bodyparser = require('koa-bodyparser'); const logger = require('koa-logger'); /** * 管理nodeJs访问日志、系统日志 */ const { accessLogger, systemLogger } = require('./utils/log4'); // 捕获全局状态下的error app.on('error', err => { systemLogger.error(err); }); app.use(accessLogger()); const chalk = require('chalk'); /** * 接入模板引擎koa-nunjucks-2 */ const koaNunjucks = require('koa-nunjucks-2'); const path = require('path'); // const templating = require('./server/middlewares/tempalting'); // const config = require('./config/index'); const index = require('./routes/index'); const users = require('./routes/users'); // error handler onerror(app); app.use(json()); /** * middlewares 用来处理post请求 */ app.use(bodyparser({ enableTypes: ['json', 'form', 'text'] })); /** * Development style logger middleware for koa * <-- GET / * --> GET / 200 835ms 746b */ app.use(logger()); /** * koa-static中间件,统一处理静态资源文件 */ app.use(require('koa-static')(path.join(__dirname, 'public'))); /** * views中间件属于模板引擎 */ // app.use(views(__dirname + '/views', { // extension: 'pug' // })); // app.use(templating('views', { // noCache: !config.isProduction, // 开发环境下不缓存 // watch: !config.isProduction// 开发环境下监听 // })); /** * 配置好 koa-nunjucks-2 中间件之后,它默认会在请求上下文ctx上增加 render()方法,通过调用 ctx.render('模板名', 数据) 就可以渲染页面, * 放在使用路由前面,否则报错:ctx.render() 不是一个 function */ app.use(koaNunjucks({ ext: 'html', // 使用HTML后缀的模板 path: path.join(__dirname, 'views'), // 模板所在路径 nunjucksConfig: { // nunjucks的配置 trimBlocks: true// 开启转义,xss漏洞 } })); /** * logger * 每收到一个http请求,koa就会调用通过app.use() 注册 的async函数,并传入ctx和next参数 * @param ctx 由koa传入的封装了request和response的变量,我们可以通过它访问request和response * @param next koa把很多async函数组成一个处理链,每个async函数都可以做一些自己的事情,然后用await next()来调用下一个async函数。我们把每个async函数称为middleware,这些middleware可以组合起来,完成很多有用的功能 */ app.use(async (ctx, next) => { const start = new Date(); await next(); const ms = new Date() - start; console.log(`${ctx.method} ${ctx.url} - ${ms}ms`); }); // routes app.use(index.routes(), index.allowedMethods()); app.use(users.routes(), users.allowedMethods()); // error-handling app.on('error', (err, ctx) => { console.error('server error', err, ctx); }); // debug模块 const debug = require('debug')('vue-cli-plugin-generate:server'); /** * 设定监听端口 */ // app.set('port', process.env.PORT || 3000); /** * 启动监听 */ const server = app.listen('3000', function () { console.log(''); console.log(''); debug(chalk.cyan(`Express server listening on port ${server.address().port}`)); console.log(''); console.log(''); }); module.exports = app;
- utils下面为一些配置文件,mongoose.js为
const config = require('../config/index'); const constant = require('./constant'); const mongoose = require('mongoose'); const chalk = require('chalk'); const dataUrl = config.databaseUrl; mongoose.connect(dataUrl, (err) => { if (err) { console.log(chalk.red(err)); console.log(''); console.log(''); console.log(chalk.red(constant.CONNECT_FAIL)); console.log(''); console.log(''); } else { console.log(chalk.green(constant.CONNECT_SUCCESS)); console.log(''); console.log(); } }); module.exports = { mongoose };
- utils下面的constant.js
module.exports = { CONNECT_SUCCESS: ' 数据库连接成功...', CONNECT_FAIL: ' 数据库连接失败...', SUCCESS_CODE: 200 };
- config为项目的整体配置,config/index.js
const isProduction = process.env.NODE_ENV === 'production'; module.exports = { isProduction, databaseUrl: 'mongodb://wangxh:wangxh123456@127.0.0.1:27017/wxh0929?authSource=admin' };
- bin目录下的www文件
#!/usr/bin/env node /** * Module dependencies. */ const app = require('../app'); const debug = require('debug')('vue-cli-plugin-generate:server'); const http = require('http'); /** * 子进程,当启动项目额时候,创建一个异步进程去打开浏览器 */ const cp = require('child_process'); const os = require('os'); const chalk = require('chalk'); /** * Get port from environment and store in Express. */ const port = normalizePort(process.env.PORT || '3000'); // app.set('port', port); /** * Create HTTP server. */ const server = http.createServer(app.callback()); /** * 获取当前主机的IPv4地址 */ function getIPv4 () { const interfaces = os.networkInterfaces(); const ipv4s = []; Object.keys(interfaces).forEach((key) => { interfaces[key].forEach((item) => { if (item.family !== 'IPv4' || item.internal != false) return; ipv4s.push(item.address); }); }); return ipv4s[0]; } /** * Listen on provided port, on all network interfaces. */ server.listen(port, (err) => { if (err) { console.log(''); console.log(chalk.red(err)); console.log(''); } else { console.log(''); console.log(''); console.log(chalk.cyan(`Express server listening at http://localhost:${port} or at ${getIPv4()}:${port}`)); console.log(''); console.log(''); } }); /** * 自动打开浏览器 */ cp.exec(`start http://localhost:${port}/`); server.on('error', onError); server.on('listening', onListening); /** * Normalize a port into a number, string, or false. */ function normalizePort (val) { const port = parseInt(val, 10); if (isNaN(port)) { // named pipe return val; } if (port >= 0) { // port number return port; } return false; } /** * Event listener for HTTP server "error" event. */ function onError (error) { if (error.syscall !== 'listen') { throw error; } const bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port; // handle specific listen errors with friendly messages switch (error.code) { case 'EACCES': console.error(bind + ' requires elevated privileges'); process.exit(1); break; case 'EADDRINUSE': console.error(bind + ' is already in use'); process.exit(1); break; default: throw error; } } /** * Event listener for HTTP server "listening" event. */ function onListening () { const addr = server.address(); const bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port; debug('Listening on ' + bind); }
- vue项目的使用方法
//安装 cnpm i vue-cli-plugin-generate //scripts对象添加配置 scripts:{ "generate":"generate" } //运行 npm run generate
5、遇到的问题
- Error: listen EADDRINUSE: address already in use :::3000
1.netstat -nao|findstr 3000 //查看占用3000接口的进程 2.taskkill /pid 11328 /F //杀死进程 3.nodemon app.js //重新启动,项目正常
- koa-static中间件配置静态目录
/** * koa-static中间件,统一处理静态资源文件 */ app.use(require('koa-static')(__dirname + '/public'));
在views文件夹里面获取静态文件时,如果写成下面这种方式,将报错:
<script src="/public/js//bin/bootstrapValidator.min.js"></script>
正确的路径为:
<script src="/js//bin/bootstrapValidator.min.js"></script>
network为:
- 执行命令:sequelize db:create --charset 'utf8mb4',出现错误
解决方法:卸载全局包:npm uninstall sequelize -g,安装npm install sequelize --save 再次执行,=成功
- 最近开发无外网,一段时间后将持续更新
5、参考文档:
北栀女孩儿