大厂技术高级前端Node进阶
点击上方 程序员成长指北,关注公众号
回复1,加入高级Node交流群
文章图片
转载自:围的围前言 团队中会遇到在线文档管理的需求,包括技术文档,接口文档,
https://segmentfault.com/a/1190000037621367
最近有小伙伴经常问实战内容,这篇不错,可以学习下!
excel
文档,和产品原型的托管等需求,一直没有找到合适的开源项目来满足需求,所以动手实现了个文档管理系统(实现起来并不复杂,该教程只是提供思路,并非最佳实践)Github: https://github.com/huangwei9527/Ink-wash-docs功能列表
演示地址:http://www.inkwash.online/
- [x] 登录注册
- [x] 工作台|文档列表
- [x] 文档编辑预览(支持:md, excel,html产品原型托管)
- [x] 协作编辑
- [x] 访问权限设置
- [x] 团队管理
- [x] 点赞收藏
- [x] 模板管理
- [x] 浏览历史
- [x] 回收站
- [ ] 文件夹形式阅读(接口文档)
- [ ] 编辑历史版本
文章图片
阅读前准备 1、了解
vue
技术栈开发 2、了解 koa
3、了解 egg
4、了解 mongodb
技术栈 前端:
vue
: 模块化开发少不了angular,react,vue三选一,这里选择了vue。vuex
: 状态管理sass
: css预编译器element-ui
:不造轮子,有现成的优秀的vue组件库当然要用起来。服务端:
egg.js
:企业级框架,按照一套统一的约定进行应用开发,开发十分高效。mongodb
:一个基于分布式文件存储的数据库,比较灵活。egg-alinode
:阿里提供的免费nodejs服务器性能监控。工程搭建 这里我们将前后端项目放在同一个目录下管理,分别用
egg
脚手架和 vue-cli3
生成初始化项目,拷贝合并到同一个目录下,记得合并下 package.json
内容。(脚手架生成项目就不介绍了,按照文档来就是了),合并后将 vue
项目 src
目录改为 web
,如下:···
·
|-- app// egg 初始化app目录
|-- config// egg 初始化app目录
|-- public// vue 静态资源目录
|-- web// 原 src 目录,改成 web 用作前端项目目录
·
···
这样的话 我们需要再把我们vue webpack打包配置稍作一下调整,首先是把原先的编译指向src的目录改成 web,其次为了 npm run build 能正常编译 web 我们也需要为 babel-loader 再增加一个编译目录:
- 根目录新增
vue.config.js
,目的是为了改造vue
项目入口,改为:web/main.js
module.exports = { pages: { index: { entry: "web/main.js" } } }
babel-loader
能正常编译web
目录, 在vue.config.js
新增如下配置
// 扩展 webpack 配置
chainWebpack: config => {
config.module
.rule('js')
.include.add(/web/).end()
.use('babel')
.loader('babel-loader')
.tap(options => {
// 修改它的选项...
return options
})
}
package.json
新增前端项目打包命令
"dev-web": "vue-cli-service serve",
"build-web": "vue-cli-service build",
至此前后端项目初始化工作就完了,前端开发启动
npm run dev-web
后端开发启动 npm run dev
工程目录结构
|-- app--------服务器端项目代码
|--controller--------用于解析用户的输入,处理后返回相应的结果
|--extend--------框架的扩展
|--middleware--------编写中间件
|--model--------Schema数据模型
|--public--------用于放置静态资源
|--service--------用于编写业务逻辑层
|--router.js--------用于配置 URL 路由规则
|-- config--------egg 配置文件
|--config.default.js--------默认配置
|--config.local.js--------开发环境配置
|--config.prod.js--------生产环境配置
|--plugin.js--------配置需要加载的插件
|-- web--------前端项目界面代码
|--common--------前端界面对应静态资源
|--components--------组件
|--config--------配置文件
|--filter--------过滤器
|--pages--------页面
|--router--------路由配置
|--store--------vuex状态管理
|--service--------axios封装
|--App.vue--------App
|--main.js--------入口文件
|--permission.js--------权限控制
|-- docs--------预留编写项目文档目录
|-- vue.config.js--------vue webpack配置文件
|-- package.json
...
...
完成项目目录初始化后,接下来先把
mongodb
全局得一些中间件、扩展方法给配置上,为接口开发做好准备工作mongodb配置 1、安装
mongoose
模块npm install egg-mongoose --save
2、配置
config
文件// config/plugin.js
exports.mongoose = {
enable: true,
package: 'egg-mongoose',
};
// config/config.default.js
config.mongoose = {
url: 'mongodb://127.0.0.1:27017/inkwash',
options: {},
};
全局中间件和扩展配置 1、统一处理接口
后端接口开发中我们需要一个统一得返回格式,可以在
context
对象下扩展个返回数据 function
用于统一处理接口 response data
app
下新建文件夹 extend
新建 context.js
// app/extend/context.js
module.exports = {
/**
* 返回客户端的内容
* @param status // 接口是否成功
* @param body // 返回数据
* @param msg // 返回信息提示
* @param code // 返回状态码
*/
returnBody (status = true, body = {}, msg = 'success', code = 200) {
this.status = code;
this.body = {
status: status,
body: body,
msg,
code: code
}
}
}
// 调用
const { ctx } = this;
ctx.returnBody(true, {}, "成功");
2、添加统一处理错误得中间件
app文件夹下新建
middleware
文件夹,新建 error_handler.js
, 并配置 congfig
全局中间件配置// app/middleware/error_handler.js
module.exports = () => {return async function errorHandler(ctx, next) {
try {
await next();
} catch (err) {
// 所有的异常都会在app上出发一个error事件,框架会记录一条错误日志
ctx.app.emit('error', err, ctx);
const status = err.status || 500;
// 如果时生产环境的时候 500错误的详细错误内容不返回给客户端
const error = status === 500 && ctx.app.config.env === 'prod' ? '网络错误' : err.message;
ctx.body = {
msg: error,
status: false,
body: {},
code: status
};
}
};
};
// app/middleware/error_handler.js
// config/config.default.js 配置全局中间件
config.middleware = [ 'errorHandler'];
jwt鉴权登录认证 1、安装 egg-jwt token生成以及验证包
npm install egg-jwt --save
2、安装完成后在根目录下的
config/plugin.js
配置一下,如:'use strict';
/** @type Egg.EggPlugin */
module.exports = {
jwt: {
enable: true,
package: "egg-jwt"
},
mongoose: {
enable: true,
package: 'egg-mongoose',
}
};
3、接下来在
config/config.default.js
里面继续配置:config.jwt = {
secret: "123456"//自定义 token 的加密条件字符串
};
4、在
context
上扩展两个 function
, getToken
和 checkToken
用于生成 token
和验证 token
// app/extend/context.js
async getToken(data) {
return await this.app.jwt.sign(data, this.app.config.jwt.secret, {expiresIn: 30* 24 * 60 * 60 + 's'});
},
async checkToken(token) {
return await this.app.jwt.verify(token, this.app.config.jwt.secret)
}
5、编写个中间件实现登录验证拦截 在
app/middleware
文件夹下新建 auth.js
// app/middleware/auth.js
module.exports = () => {
return async function(ctx, next) {
let token = '';
if (
ctx.headers.authorization && ctx.headers.authorization.split(' ')[0] === 'Bearer'
) {
token = ctx.headers.authorization.split(' ')[1];
} else if (ctx.query.accesstoken) {
token = ctx.query.accesstoken;
} else if (ctx.request.body.accesstoken) {
token = ctx.request.body.accesstoken;
}
let user;
try{
user = await ctx.checkToken(token);
}catch (e) {
ctx.returnBody(false,{}, 'Token 无效,请重新登录', 401);
}
if (!user) {
ctx.returnBody(false,{}, 'Token 无效,请重新登录', 401);
return;
}
ctx.request.user = user;
await next();
};
};
好了以上配置完成后就开始接下来的核心注册功能相关操作了。
- 首先我在根目录下的
app/router.js
创建访问路由:
import { Application } from 'egg';
export default (app: Application) => {
const { controller, router, jwt } = app;
//正常路由
router.post('/auth/register', controller.auth.register);
// 只有在需要验证 token 的路由上添加jwt
router.post('/user/infor',jwt, controller.user.infor);
};
- 接下来我去编写我的控制器,在根目录下的
app/controller/home.ts
编写内容:这里使用了两个我们在app/extend/context.js
上扩展的两个通用方法
- 通过
ctx.getToken
(用户信息object
对象)将用户信息通过jwt
生成token
返回给前端
- 通过
ctx.returnBody
返回数据
// app/controller/auth.js
const Controller = require('egg').Controller
class AuthController extends Controller {
async login() {
//... 略
}
async register() {
const { ctx, service } = this;
const { username, password, email } = ctx.request.body
let userData = https://www.it610.com/article/await ctx.service.user.createUser(username, password, email);
userData = userData.toObject();
let userDataStr = JSON.parse(JSON.stringify(userData));
// 生成token
let token =await ctx.getToken(userDataStr);
ctx.returnBody(true, {access_token: token, userInfo: userData},"注册成功!")
}
}module.exports = AuthController;
- 前端请求的时候需要在
headers
里面上默认的验证字断Authorization
就可以了,如:
axios({
method: 'get',
url: 'http://127.0.0.1:7001/user/info',
headers:{
// 切记 token 不要直接发送,要在前面加上 Bearer 字符串和一个空格
'Authorization':`Bearer ${token}`
}
})
- 接口从
token
获取加密信息
- 在
app/extend/context.js
再扩展个getUser
方法获取token
加密信息
// app/extend/context.js
// 获取用户信息
async getUserData() {
var token = this.headers.authorization ? this.headers.authorization : '';
token = token.substring(7) //把Bearer 截取掉,解析的时候不需要加上Bearer
let user = {}
try {
user = this.app.jwt.verify(token, this.app.config.jwt.secret);
} catch (err) {
user = {}
}
return user;
}
- 实现获取个人信息接口
// app/controller/user.js
'use strict';
const Controller = require('egg').Controller;
class UserController extends Controller {
async info() {
let {ctx} = this;
let user = await this.ctx.getUserData()
ctx.returnBody(true, user)
}
}module.exports = UserController;
至此我们就实现了
jwt
生成 token
, 然后通过前端传过来的 token
获取当前登录用户的信息,jwt
登录授权这块应该是讲完了,其他的业务接口应该实现起来难度不大md文档编辑 文档编辑器使用
Vdito r
, 一款浏览器端的 Markdown
编辑器,支持所见即所得(富文本)、即时渲染(类似 Typora
)和分屏预览模式 安装 Vditor
npm install vditor --save
在代码中引入并初始化对象
excel表格编辑 安装
x-data-spreadsheet
npm install x-data-spreadsheet
import Spreadsheet from "x-data-spreadsheet";
// If you need to override the default options, you can set the override
// const options = {};
// new Spreadsheet('#x-spreadsheet-demo', options);
const s = new Spreadsheet("#x-spreadsheet-demo")
.loadData({}) // load data
.change(data => {
// save data to db
});
// data validation
s.validate()
axure原型托管 原型
axure
页面托管,参考 WuliHub
让用户上传生成的 html
压缩包,然后解压到静态资源目录,返回访问地址就 ok
, 前端拿到原型地址用内嵌 iframe
渲染出来就 ok
打包编译&&静态资源设置 1、配置前端
vue
页面打包命令// kage.json script新增打包命令
"build-web": "vue-cli-service build",
2、运行
npm run build-web
根目录会生成 dist
前端代码静态文件,因为 egg
支持设置多个静态资源目录,这里就直接配置根目录下的dist
文件夹为静态目录, 配置 config
// config/config.default.js
config.static = {
prefix: '/',// 将静态资源前缀改为'/'(默认是 '/public')
dir: [
path.join(__dirname, '../app/public'),
path.join(__dirname, '../dist')
]
}
打包完成后启动
egg
, 就可以通过 http://localhost/:7001/index.html
访问到前端页面了因为直接访问
http://localhost/:7001
会 404
可以再配置个路由重定向,将跟路由 '/'
重定向到 '/index.html'
// app/router.js
// 重定向到index页面
app.router.redirect('/', '/index.html', 302);
部署 服务端部署运行
start
命令npm run start
性能监控
node
服务性能监控这块可以使用阿里免费开源的 alinode
1、安装 egg-alinode
npm i egg-alinode
2、插件配置
// config/plugin.js
exports.alinode = {
enable: true,
package: 'egg-alinode',
};
3、配置
config
// config/config.default.js
exports.alinode = {
enable: true,
appid: 'my app id',
secret: 'my app secret',
};
这样就可以了,监控数据可以在阿里
Node.js
性能平台控制台看到监控面板Node 社群
我组建了一个氛围特别好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你对Node.js学习感兴趣的话(后续有计划也可以),我们可以一起进行Node.js相关的交流、学习、共建。下方加 考拉 好友回复「Node」即可。
文章图片
【中间件|【实战篇】egg+vue+mongodb实践开发在线文档管理平台——水墨文档】“分享、点赞、在看” 支持一波????
推荐阅读
- mybatis|SSM框架整合(Spring+SpringMVC+Mybatis)
- Python|基于PyTorch的flappy bird游戏
- spring|Spring Boot 实现接口幂等性的 4 种方案
- 架构|你有了解过这些架构设计,架构知识体系吗((架构书籍推荐))
- JAVA|SpringBoot 线程池
- java|Java 应用线上问题排查思路、常用工具小结
- spring|Java 微服务的QPS上不去(试试这些办法)
- java|java gc日志乱码_让bug无处藏身,Java 线上问题排查思路、常用工具
- java|java gc日志乱码_让 Bug 无处藏身,Java 线上问题排查思路、常用工具