NodeJs从入门到实战 作为一名热爱学习的前端工程师,想要获得更大的成长,除了积累原生JavaScript的相关知识,还是有必要掌握后端开发的,这样是从一个全端开发工程师彻底转变成大前端的一个必经之路!
项目背景 由于我平时对前端领域比较感兴趣,所以也曾开发过属于自己的个人网站,从Hexo脚手架搭建的博客站,到前后端分离的个人网站,以及后面所接触到的unicloud云开发,这其中也渐渐对nodejs技术有了更进一步的了解。
目前负责公司的一个可视化平台的后台服务器项目,从最初的技术选型到一步一步的搭建,测试,到最终部署到Linux系统上,以及后期的迭代更新,也收获满满。
技术架构 因为是团队开发,我才用前后端分离的方式,具体技术栈如下: 服务端:NodeJs + Koa + sequelize + sqlite3 部署上线:pm2 代码管理: git
服务端技术架构图:
技术架构说明
这里我们采用node社区比较轻量的服务端框架Koa,然后服务端中间件有:
koa-static 提供静态资源访问,具体用途在项目实现细节里面会详细介绍
koa-body 处理请求报文,让koa可以方便的拿到post/put的数据
koa2-cors 本地联调时通过cors方式处理跨域问题
multer 用来处理文件上传
koa-router 用来编写服务端路由和api
koa-send 用于处理文件下载
axios HttpAPI请求工具, 这里是辅助前端进行第三方跨域请求
sequelize Node的ORM框架Sequelize来操作数据库,用于将关系数据库映射到对象上,然后进行的封装。
上面就是我们web服务端主要使用的中间件,对于每一块如何去组织和架构,包括自己实现错误校验中间件,我会在后面一一介绍,由于写服务端的过程中也查阅了很多资料,如有不足或需要优化的地方,欢迎交流。 目录 model-sequelize/ | +- .vscode/无 | | | +- launch.json <-- VSCode 配置文件 | +- controller/接口函数 | +- applys.js <-- 应用接口函数 | +- node_util.js <-- 通用接口函数 | +- project.js <-- 项目管理接口函数 | …… | +- lib/请求响应处理封装 | +- return.js <-- 过滤响应 | +- util/工具库 | +- init | +- model | +- view/前端静态代码托管 | +- | +- models/ <-- 存放所有数据表映射关系 | +- project.js <-- 项目管理 | …… | +- db.js <-- 如何定义Model | +- model.js <-- 如何导入Model | +- database.js <-- 初始化数据库 | +- database.sqlite <-- sqlite3数据库文件 | +- server.js <-- 业务代码(总入口) | +- server.json <-- 业务配置项 | +- package.json <-- 项目描述文件 | +- node_modules/ <-- npm安装的所有依赖包
常用功能精讲 sequelize 在没有sequelize之前,nodejs调用数据表,需要手写晦涩难懂的sql语句。 而sequelize采用底层封装的思路,将数据表抽象成为对象,然后通过API进行实现增删改查。 就如同vue解放了原生dom操作一般,有木有很方便。 // 连接数据库 const sequelize = new Sequelize({ host: 'localhost', dialect: 'sqlite', // timezone: '+08:00', pool: { max: 5, min: 0, acquire: 30000, idle: 10000 }, storage: 'database.sqlite', operatorsAliases: false }); // 数据表建立 例子: module.exports = db.defineModel("user", { username: db.Sequelize.STRING, password: db.Sequelize.STRING, status: db.Sequelize.STRING, token: db.Sequelize.STRING, // 保存至前端的加密信息 暂时由status+时间戳组成 wechat_sceneId:db.Sequelize.INTEGER, // 微信小程序所加载的场景id }, { // freezeTabelName 为 true 时不会在库中映射表时增加复数表名 // 该选项为 true 时,user 在映射时映射成 user,而为 false 时会映射成users freezeTableName: true }) // 多表关联建立 例子: // 关联一对多表查询 applys.belongsTo(projects, { foreignKey: 'projectId', targetKey: 'id' }); // 数据表的查询操作(其中model是我对所有数据表对象的封装) const userList=async ()=>{ let results = await model.user.findAll() return results }
最后想了解更多关于sequelize的使用,可以前往廖雪峰大佬的个人网站学习。##sequelize
supervisor
打包上线/打包成应用 进程常驻pm2 npm install -g pm2 $ pm2 start app.js # 启动app.js应用程序 $ pm2 start app.js -i 4 # cluster mode 模式启动4个app.js的应用实例 # 4个应用程序会自动进行负载均衡 $ pm2 start app.js --name="api" # 启动应用程序并命名为 "api" $ pm2 start app.js --watch # 当文件变化时自动重启应用 $ pm2 start script.sh # 启动 bash 脚本 $ pm2 list # 列表 PM2 启动的所有的应用程序 $ pm2 monit # 显示每个应用程序的CPU和内存占用情况 $ pm2 show [app-name] # 显示应用程序的所有信息 $ pm2 logs # 显示所有应用程序的日志 $ pm2 logs [app-name] # 显示指定应用程序的日志 $ pm2 flush # 清空所有日志文件 $ pm2 stop all # 停止所有的应用程序 $ pm2 stop 0 # 停止 id为 0的指定应用程序 $ pm2 restart all # 重启所有应用 $ pm2 reload all # 重启 cluster mode下的所有应用 $ pm2 gracefulReload all # Graceful reload all apps in cluster mode $ pm2 delete all # 关闭并删除所有应用 $ pm2 delete 0 # 删除指定应用 id 0 $ pm2 scale api 10 # 把名字叫api的应用扩展到10个实例 $ pm2 reset [app-name] # 重置重启数量 $ pm2 startup # 创建开机自启动命令 $ pm2 save # 保存当前应用列表 $ pm2 resurrect # 重新加载保存的应用列表 $ pm2 update # Save processes, kill PM2 and restore processes $ pm2 generate # Generate a sample json configuration file pm2文档地址:http://pm2.keymetrics.io/docs/usage/quick-start/
mysql数据库连接功能相关知识 开启本地数据库局域网访问 1、更新root账户的权限。打开mysql命令行窗口,输入 grant all privileges on *.* to root@"%" identified by 'abc' with grant option; flush privileges; 上述语句的完整模板为: grant all privileges on 库名.表名 to '用户名'@'IP地址' identified by '密码' with grant option; flush privileges; 测试,没有问题。 2、创建一个新账户,如guest,并将可被访问的主机定义为%,即所有主机都可访问该账户。 测试,没有问题。 参考: https://jingyan.baidu.com/article/6dad50755e3dd1a123e36ec4.html
docker打包镜像
window上要使用docker,可以使用docker desktop工具安装和运行docker desktop 测试demo 执行步骤1-clone 克隆仓库镜像 执行步骤2-build 编译 执行步骤3-run
创建配置项
FROM node:12.13.0 # Create app directory WORKDIR /usr/src/app # Install app dependencies # A wildcard is used to ensure both package.json AND package-lock.json are copied # where available (npm@5+) COPY package*.json ./ RUN yarn install #RUN npm install --registry=https://registry.npm.taobao.org # If you are building your code for production #RUN npm ci --only=production # Bundle app source COPY . . EXPOSE 3000 CMD [ "node", "server.js" ]
dockerignore.git .svn node_modules public static/model database.sqlite npm-debug.log
编译打包服务端项目
编译 docker build -t yanyufanchen/node-web-app . node-web-app为打包的镜像名称 可以用:用户名/镜像名 查看所有镜像 docker images 修改标签 docker tag IMAGEID(镜像id) REPOSITORY:TAG(用户名/镜像名:标签) 运行镜像 docker run -p 3000:3000 -d 镜像名 映射端口49160:原有端口8080 推送远程仓库 docker push 镜像名称:标签 删除镜像 docker rmi -f 241c2cc33dde(镜像名称) 查看容器 docker ps 停止容器 docker stop 删除容器 docker rm -f
遇到的问题安装docker desktop工具后出现提示”wsl2 installation is incomplete“ 原因:是没有安装linux在windows的子系统,可以在window store上下载debian工具 解决方案:https://www.jiloc.com/45016.html 1、安装debian 2、启动debian 3、注册账号密码 依然没有解决,安装wsl更新包 https://www.cnblogs.com/xiluhua/p/14120713.html https://github.com/xiluhua/docker-desktop
代码混淆 uglify-es混淆 安装
From NPM for use as a command line app:
npm install uglify-es -g
From NPM for programmatic use:
npm install uglify-es
使用
混用多个混淆属性选项: uglifyjs example.js -c -m --mangle-props regex=/_$/,reserved=[bar_] 混淆并输出到指定目录下 uglifyjs text2.js -o out/text2.js -c -m --mangle-props regex=/_$/,reserved=[bar_]
地址
uglify-js只能混淆es5以下 参考中文文档 http://www.suoniao.com/article/52 uglify-es可以混淆es6 https://github.com/mishoo/UglifyJS/tree/harmony
参考资料