# nnws **Repository Path**: brucezds/nnws ## Basic Information - **Project Name**: nnws - **Description**: node.js web server - **Primary Language**: JavaScript - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2025-03-05 - **Last Updated**: 2025-03-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # NNWS - Node.js Ngingx Web Server 小巧方便的web服务程序,提供可视化UI配置界面,极简配置快速启动。
基于Node.js实现的Web服务器 实现了Nginx的主要功能 旨在提供一个简洁、高效、配置方便的web服务应用 在没有安装Nginx的服务器(或者不会配置Nginx的人)也能轻松实现Nginx主要功能的工具 项目小巧简洁,源码大小只有几百K,集成了服务端与可视化配置的前端UI (基于vue.js) NodeJs的首要目标是提供一种简单的、用于创建高性能服务器及可在该服务器中运行的各种应用程序的开发工具。所以基于Node.js的Web服务天然具有Node.js所有优点。 ## 优点 ### 配置 > UI可视化配置方式,服务器小白也能轻松上手,无需熟悉shell命令,每个配置参数有提示说明,使用体验极佳 ### 简洁 > 只实现最重要最常用的web服务功能,轻量级Web服务器 ### 高效 > 得益于NodeJs超强的高并发能力,处理高并发场景性能更高,天然具备Node.js的异步、非阻塞I/O优点 ### 安全 > 不同于php,jsp等web服务频繁被攻击,Node.js服务安全性更高 ### 毫秒级重启 > 使用PM2进程管理工具,可以实现毫秒级重启 ## 主要功能 - 静态网站服务器 - 站群管理功能 - 反向代理(整站代理或目录代理,如:api代理) - 同端口多https证书 ## 特性 - 同时支持http与https - 支持SPA的history模式 - 支持CORS - 支持压缩传输(compression) - 支持一键关闭站点 - 支持日志显示 - 支持多个静态文件目录 - 支持多个目录的反向代理 - 支持一键关闭反向代理 - 支持显示请求数据 - 反向代理目录支持正则匹配 - 可视化配置 - 登录次数过多自动锁定系统,禁止登录 ## 技术栈 - Node.js - Express - Vue.js - jwt.js - Element UI - http-proxy - json-db ## 使用方法 有4种运行方法 1. 直接git clone源码运行(需要运行npm i,可使用pm2管理) 2. git clone源码然后运行 ./bin/nnws.js(不需要运行npm i,可使用pm2管理) 3. 只下载nnws.js运行,然后使用本站提供的UI(不需要运行npm i,可使用pm2管理) 4. 下载nnws可执行文件,使用nohup运行,无须安装node.js环境(不能使用pm2管理) 5. 使用npm全局安装,然后直接nnws就可以运行(不能使用pm2管理) 6. 脚本安装 wget https://gitee.com/chen-binfa/nnws/releases/download/v1.0.0/nnws-install.sh && chmod +x nnws-install.sh && ./nnws-install.sh ``` javascript git clone https://gitee.com/chen-binfa/nnws cd nnws npm i npm start ``` > 建议使用pm2对网站进行管理 ``` javascript //先cd到此项目根目录 pm2 start ./app.js --name nnws ``` ### 直接使用 没有安装node.js运行环境时,要直接使用,可以在本仓库的发行版中下载nnws二进制文件 ```bash wget https://gitee.com/chen-binfa/nnws/releases/download/v1.0.0/nnws // 或者 window 版本 nnws.exe chmod +x nnws ./nnws //或者使用nohup nohup ./nnws & ``` 然后会看到一行输出:nohup: ignoring input and appending output to 'nohup.out' 此时,会在当前目录下多出两个文件: nnws-config.json 网站配置数据 nohup.out 运行日志 如果要停止运行,你需要使用以下命令查找到 nohup 运行脚本到 PID,然后使用 kill 命令来删除: ```bash ps -aux | grep "nnws" ``` ```bash kill 32323 ``` ## 访问配置后台 [http://localhost:3009/login.html](http://localhost:3009/login.html) - 其中的localhost为你的服务器IP或域名 - 默认登录账号密码: ``` 账号:admin 密码:admin888 ``` ## 打包成可执行程序 可以使用pkg进行打包,打包前需要本机先安装pkg ```bash npm i pkg -g ``` 然后运行 ```bash pkg . # or npm run build ``` 即可打包linux-x64版本的二进制程序 生成的目标程序位于 ./dist 目录下 ## UI预览 登录后台 ![登录](https://gitee.com/chen-binfa/nnws/raw/master/docs/screenhot/login.png) 网站管理 ![登录](https://gitee.com/chen-binfa/nnws/raw/master/docs/screenhot/website-list.png) 添加/修改网站 ![登录](https://gitee.com/chen-binfa/nnws/raw/master/docs/screenhot/add-website.png) 登录账号设置 ![登录](https://gitee.com/chen-binfa/nnws/raw/master/docs/screenhot/admin-update.png) ## 配置说明 当然,也可以手动配置参数,配置文件在根目录的 webconfig-db.js文件,配置格式如下: ``` javascript [ { enable: false, //是否启用 showLog: true, //是否显示日志 name: "我的网站", //网站名称 host: "a.com", //域名 staticDirs: ["/data/web/public"], //静态目录,支持多个 openInBrower: false, //是否启用后在立即在浏览器打开(仅支持windows系统下) history: true, //是否启用SPA的history模式 http: { //http服务配置 enable: true, //是否启用http服务 port: 80, //http服务端口 }, https: { //https服务配置 enable: true, //是否启用https服务 port: 443, //https服务端口 }, proxys: [ //反向代理配置 { enable: true, //是否启用 showPostData: true, //是否显示请求数据 showResData: true, //是否显示Response数据 target: "http://localhost:8106", //代理的目标站点 path: ["/api/*","/admin-api/*"], //代理目录,支持多个 }, ... //更多反向代理配置 ], }, ...//更多站点配置 ] ``` - 注意:https需要把证书放到 /ssl 目录下,先创建一个域名文件夹,文件名分别是 域名+.crt与域名+.key 如: ``` javascript /ssl/a.com/a.com.crt /ssl/a.com/a.com.key ``` ## 经典应用场景 ### 1. 简单的部署一个前端静态站点 配置域名、网站目录、端口即可 ### 2. 多个静态站点部署到一台服务器上,都使用80端口,使用不同域名 > 由于服务器数量有限,经常需要把多个网站配置到一台服务器上,生产环境中,通常都是使用80端口(https是443端口),如果独立的运行多个网站服务则会造成端口冲突。本系统对把相同端口的服务统一到一个进程,根据域名来判断访问哪个站点。 ### 3. 多个https站点,使用443端口,使用不同域名 > 多个https站点需要上传对应的域名证书到ssl文件夹 ### 4. 前端和后台使用相同域名,后端有独立服务 > 如,前端的访问路径是 https://a.com/index.html,后端API的访问路径是 https://a.com/api/*,就可以使用本系统的反向代理功能来实现 ### 5. 前端放在内网服务器,经过统一的外网服务器对外提供服务 > 为了安全,后端程序、API、服务、前端站点等通常部署在内网,由统一的web服务器对外提供访问服务,架构如下图: > ![登录](https://gitee.com/chen-binfa/nnws/raw/master/docs/screenhot/demo/2.png) > 或者更复杂一点的如下图: > ![登录](https://gitee.com/chen-binfa/nnws/raw/master/docs/screenhot/demo/3.png) ### 6. 后端API服务不支持跨域(CORS) > 1. 在前后端分离的架构中,有时候后端开发人员不会配置CORS,或者在本地测试需要调用远程API时,会提示跨域无法访问,使用本系统的反向代理功能轻松实现。 > 2. 公共或第三方API不允许跨域访问,前端就无法跨域调用,使用反向代理功能进行转发即可解决。 ### 7. 不会配置history模式,刷新后显示404 > 由于在nginx中history模式的配置比较麻烦, 有时候运维人员或服务器管理人员并不知道什么是SPA的history模式,或者知道也不懂得怎么配置,使用本系统配置的静态站点,只要打开history模式开关即可便捷的开启,非常方便。 ### 8. http转https > 1. 有一个http的站点,甲方要求改为https的访问方式,如果http的站点使用其它语言编写或年代比较久远,使用起来很麻烦,那么,就可以使用本系统反向代理功能来实现。 > 2. 前端配置了https的访问方式,但后端API仍然是http,会造成前端访问不到API,后端人员也不知道怎么改成https,这时候,就可以使用本系统反向代理功能来实现。 > 3. 前端需要调用网络上的一个公共API,但又不想向甲方暴露出我使用了公共API,就可以把公共API转发成自己的网址,甲方就看不出来了。 > 3. 前端调用的API是第三方公司开发,但对方不愿意修改成https,或者不想把ssl证书公开给对方 。 ### 9. https转http > 1. 反过来,前端是HTTP,后端是HTTPS,而你又没有对应域名的SSL证书,前端就无法调用后端API,通过反向代理把后端API转发成http即可实现。 > 2. 前端需要调用网络上的一个公共HTTPS API,而你的前端是http,就可以把公共API转发成http访问形式,并且解决跨域问题。 ### 10. 多个静态目录 > 1. 反过来,前端是HTTP,后端是HTTPS,而你又没有对应域名的SSL证书,前端就无法调用后端API,通过反向代理把后端API转发成http即可实现。 > 2. 前端需要调用网络上的一个公共HTTPS API,而你的前端是http,就可以把公共API转发成http访问形式,并且解决跨域问题。 ### 11. 作为图片或文件服务器 > 如果没有专用的图片服务器,图片上传后,前端无法访问,只要配置一个静态站点,把静态目录指向图片文件夹,即可当作图片服务器来使用。 ### 12. 多个后端API服务需要统一到一个 > http://a.com/sms 短信发送API > http://b.com/data 数据请求API > http://c.com/chain 链访问API 要把上面三个API统一成一个域名访问: > http://d.com/sms 短信发送API > http://d.com/data 数据请求API > http://d.com/chain 链访问API ### 13. API调试,查看提交数据 > 通过查实时日志,可以即可查看到提交的数据。 ### 14. API数据转换、格式化提交 > 在数据提交至后端API前,对数据进行转换,或者格式化处理。 ### 15. 同一个域名下,每个目录对应不同站点(如示范站) > http://a.com/a/ 客户A的示范站 > http://a.com/b/ 客户B的示范站 > http://a.com/c/ 客户C的示范站 在静态目录中,配置三个文件夹即可,使用逗号分隔。 ## todo 1. 首次启动时,自动生成一个jwt 密钥 2. 首次登录成功提示修改账号密码 3. 登录页面启动时,自动检测后台API是否正常,如不正常自动提示要配置 4. 登录后台后也能自由切换服务器 5. 增加重启单个网站的功能,每个网站创建一个工作进程,主进程中把配置文件格式化完成,获得网站列表,然后在工作进程中启动 6. 网站配置中增加进程数量配置 5. 代码: ```javascript const cluster = require("cluster"); if (cluster.isMaster) { console.log(`主进程 ${process.pid} 正在运行`); // Fork workers. for(let i=0;i<3;i++){ cluster.fork(); } let arr=['a','b','c']; cluster.on("message", (child, message) => { // console.log("主进程收到消息:", message); let msg=arr.pop(); child.send(msg); }); } else { console.log(`子进程 ${process.pid} 已经启动`); process.on('message', (message) => { console.log('Received message from master:', message); }); setTimeout(function(){ process.send('12121'); }); } ```