前端工程师都会遇到的nodejs常见问题和解决方案复盘
qiyuwang 2024-10-31 15:50 14 浏览 0 评论
笔者之前陆陆续续接手过几个nodejs项目, 也参与过几个有点意思的nodejs开源项目, 最近把其中遇到的一些问题和解决方案做一个梳理, 避免大家继续踩坑. 话不多说我们开始吧~
1. window和mac下设置NODE_ENV变量的问题
我们都知道在前端项目中会根据不同的环境变量来处理不同的逻辑, 在nodejs中也一样, 我们需要设置本地开发环境, 测试环境, 线上环境等, 此时有一直设置环境变量的方案是在package.json中的script属性中设置, 如下:
"scripts": { "start": "export NODE_ENV=development && nodemon -w src --exec \"babel-node src\"", "build": "babel src --out-dir dist", "run-build": "node dist", "test": "echo \"Error: no test specified\" && exit 1" }复制代码
从start指令中我们可以发现我们用export NODE_ENV=development来定义开发环境的环境变量,由于笔者采用的是mac电脑,所以可以用export来定义一个node环境变量. 但是在和朋友合作开发项目时发现执行yarn start后会报错, 后面看错误信息才发现window下不识别export, 后面笔者发现window定义环境变量可以用set, 所以对于window用户, 如果你使用了以上方法设置NODE_ENV, 可以采用如下方式:
"scripts": { "start": "set NODE_ENV=development && nodemon -w src --exec \"babel-node src\"" }复制代码
2. 执行npm install发生node-gyp报错的问题
在项目开发过程中有时候拉取新的node项目代码后执行npm install, 会报如下错误:
node-gyp就是在node环境中使用的生成不同平台不同编译器的项目文件, 如果你遇到了相同的问题, 我们可以采用如下方案:
npm install -g node-gyp复制代码
或者直接删除package-lock.json或者yarn.lock, 然后重新yarn install或者npm install即可, 笔者清测有效.
3. node + koa2项目中删除已设置的cookie的解决办法
由于HTTP是无状态协议,所以需要cookie来区分用户之间的身份。 我们可以把cookie作为是一个由浏览器和服务器共同协作实现的规范。
cookie的处理分为以下3步(基础且重要的知识):
- 服务器向客户端发送cookie
- 浏览器将cookie保存(可以在后端设置expires或者maxAge,以session形式存在)
- 每次浏览器都会将之前设置好的cookie发向服务器
在开发node后台项目时我们经常涉及用户管理模块, 这意味我们需要对用户进行登录态管理, 在用户退出时能及时删除用户的cookie, 好在koa2自带了处理cookie的方法, 我们可以通过如下的方式设置cookie:
router.post(api.validVip, async ctx => { ctx.cookies.set('vid', 'xuxiaoxi', { maxAge: 24 * 3600 * 1000 }); });复制代码
以上我们随便设置了一个有效期为1天的cookie, 那如果业务有变动, 需要在有效期内清空此cookie, 我们该如何处理呢? 解析来给出一个相对可用的解决方案:
ctx.cookies.set('vid', '', { maxAge: 0 });复制代码
此时客户端的cookie将在下次请求时自动失效.
4. socket.io如何与koa/egg配合使用
我们都知道完整的socket.io通信由两部分组成:
- 与NodeJS HTTP 服务器集成(或安装在其上)的socket.io
- 在浏览器端加载的客户端库socket.io-client
如果我们直接使用koa或者egg, 我们需要将它们内部集成的http和socket.io做兼容, 此时我们可以这样处理:
import koa from 'koa';import http from 'http';const app = new koa();const server = http.createServer(app.callback());const io = require('socket.io')(server);// 正常的业务处理// ioio.on('connection', (socket) => { console.log('a user connected'); socket.on('doc load', (msg) => { console.log('doc load', msg) io.emit('getData', users) }) });server.listen(3000, () => { // ...});复制代码
通过以上的方式就可以正常的将koa和socket.io 做兼容. 后面我们就可以正常的开发IM应用啦~
5. 由于nodejs第三方模块依赖特定node版本导致的报错解决方案
这个情况笔者之前也遇到过, 主要原因是第三方没有和node版本做到很好的向后兼容, 此时解决方案就是更新此第三方包到最新版本(如果还在维护的情况), 或者使用node包管理工具(n)切换到适配的node版本, 如下:
// 更新最新的包npm i xxx@latest?// 使用包管理工具nnpm i -g n复制代码
使用n可以很方便的管理node版本, 感兴趣可以尝试一下.
6. nodejs如何创建定时任务
定时任务在后端开发中是很常见的功能之一, 其本质是根据时间规则,系统在后台自动执行相应的任务. 在java, PHP 等后台语言中有很丰富的定时任务的支持, 对于nodejs 这个兴起之秀来说, 虽然没有那么成熟的生态, 但是仍然有定时任务的模块, 比如node-schedule.
Node Schedule 是用于Node.js的灵活的 cron 类和非 cron 类作业调度程序。它允许我们使用可选的重复规则来安排作业(任意函数)在特定日期执行。它在任何给定时间仅使用一个计时器(而不是每秒钟/分钟重新评估即将到来的作业)。
一个很实用的场景是我们想在每年的双十一或者双十二让node程序自动抓取某电商的“商品羊毛”, 并推送到自己的邮箱, 此时我们就可以用Node Schedule来开启一个定时任务来执行我们的业务操作, 笔者的很多node应用都采用了类似的模式.感兴趣可以互相交流一下.
那什么是cron风格的Scheduling呢? 其github上给出了一个简单的介绍:
所以我们可以像如下方式这样来写一个定时任务:
let schedule = require('node-schedule');let testJob = schedule.scheduleJob('42 * * * *', function(){ console.log('将在未来的每个时刻的42分时执行此代码, 比如22:42, 23:42');});复制代码
7. 在nodejs项目中使用import, export和修饰器@decorator语法
我们都知道现在nodejs版本已经到14.0+版本了, 对最新的es语法支持的也足够好, 但是目前仍然有一些语法不支持, 比如es的模块导入导出(import, export), 装饰器(@decorator)等, 此时我们要在node项目中使用这些新特性, 我们就不得不借助工具, 这里笔者采用babel7来解决上述问题, 如下:
# .babelrc{ "presets": [ [ "@babel/preset-env", { "targets": { "node": "current" } } ] ], "plugins": [ ["@babel/plugin-proposal-decorators", { "legacy": true }], ["@babel/plugin-proposal-class-properties", { "loose" : true }] ]}复制代码
我们只需要在项目根目录里新建并写入如上文件, 并安装babel对应的模块即可, 如下:
yarn add @babel/cli @babel/core @babel/node @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators @babel/preset-env复制代码
此时就可以想写前端项目一样使用这些新语法特性啦~
8. nodejs中优雅的处理json文件以及提高json读写性能
对于nodejs优化方面其实有很多要聊的, 这里主要来说说json相关的优化方案. 我们需要从2个方面来优化, 一个就是json文件的读写性能, 此时我们可以采用fast-json-stringify 来大大提高json的读写速度, 其本质是提供了一套json-schema约束, 让json结构更加有序, 从而提高json的读取查询速度. 如下使用方式:
const fastJson = require('fast-json-stringify')const stringify = fastJson({ title: 'H5 Dooring Schema', type: 'object', properties: { firstName: { type: 'string' }, lastName: { type: 'string' }, age: { description: 'Age in years', type: 'integer' }, reg: { type: 'string' } }})复制代码
比如说在H5-Dooring的后台中, 有很多需要频繁读写json数据的接口, 此时使用fast-json-stringify对读写性能会有很大的提升.
另一方面, 我们在node 端操作json, 如果用原生的写法会非常麻烦, 此时我们最好自己对json读取进行封装来提高代码的简约性, 或者我们直接使用第三方库jsonfile 来轻松读写json文件, 如下使用案例:
const json = require('jsonfile')const fileName = 'h5-dooring.json'const jsonData = jsonFile.readFileSync(fileName)复制代码
9. nodejs读取大文件报错解决方案
在nodejs中 我们可以使用两种方式来读写文件, 如下:
- fs.readFile() 一次性将文件读取进内存中, 如果文件过大会导致node内存不够而报错
- fs.createReadStream() 以文件流的方式读取, 此时可以不用担心文件的大小
由以上介绍可知如果我们要读取的文件可能会很大(比如视频等大文件), 我们一开始就要使用fs.createReadStream(), 其实如果我们需要对文件进行解析, 比如要对简历等文件进行逐行解析提取关键语料, 我们可以使用node的readline模块, 此时我们就可以对文件进行逐行读取并解析, 如下案例:
const fs = require("fs");const path = require("path");const readline = require("readline");const readlineTask = readline.createInterface({ input: fs.createReadStream(path.join(__dirname, './h5-dooring')),}); readlineTask.on('line', function(chunk) { // 读取每一行数据}); readlineTask.on('close', function() { //文件读取结束的逻辑}复制代码
10. nodejs如何开启gzip优化网站性能
对于nodejs开启gzip 的操作也属于node性能优化的一部分, 经过这样的处理可以让我们的网站加载更快, 我们可以使用koa的koa-compress中间件来实现gzip 功能. 具体实现如下:
import koa from 'koa';import compress from 'koa-compress';const app = new koa();// 开启gzipconst options = { threshold: 2048 };app.use(compress(options));复制代码
当然koa-compress还有很多自定义的配置项, 大家可以感受一下.
11. 解决window和linux系统下路径分隔符不一致的问题
这个问题也是系统之间的差异导致的, 也是需要考虑的问题, 我们都知道在linux系统下路径的分隔符为/, 比如h5-dooring/src/pages, 但是在window下解析的可能就是h5-dooring\\src\\pages这样的路径, 此时我们需要做适配, 不然我们部署到不同系统上报错是必然的, 所以我们需要全局配置路径通配符, 笔者的解决方案如下:
import os from 'os'const _$ = (os.platform().toLowerCase() === 'win32') ? '\\' : '/';复制代码
此时涉及到具体路径的地方我们用_$ 代替即可, 以上代码我们用到了node的os模块, 感兴趣的可以研究一下, 我们可以用os模块处理很多有意思的因为系统差异导致的问题.
12. nodejs如何实现父子进程通信
由于nodejs是单线程的, 但是有时候我们需要支持处理多个进程的业务, 目前nodejs可以通过哦父子进程的模式来模拟多进程, 我们可以用到child_process, 大致流程如下:
笔者之前分享的很多node实战项目都采用了child_process, 大致实现过程如下:
// child.jsfunction computedTotal(arr, cb) { // 耗时计算任务}// 与主进程通信// 监听主进程信号process.on('message', (msg) => { computedTotal(bigDataArr, (flag) => { // 向主进程发送完成信号 process.send(flag); })});// main.jsconst { fork } = require('child_process');app.use(async (ctx, next) => { if(ctx.url === '/fetch') { const data = ctx.request.body; // 通知子进程开始执行任务,并传入数据 const res = await createPromisefork('./child.js', data) } // 创建异步线程 function createPromisefork(childUrl, data) { // 加载子进程 const res = fork(childUrl) // 通知子进程开始work data && res.send(data) return new Promise(reslove => { res.on('message', f => { reslove(f) }) }) } await next()})复制代码
13. node端实现图片编辑/压缩
图片编辑压缩在很多场景中用前端的技术实现比较常见, 其实在node端也有很多需要处理的图片需要, 毕竟客户端处理的质量不好控制, 此时我们可以采用node-images, 他是一款node 端轻量级跨平台图像编解码库, 其主要特性如下:
- 轻量级:无需安装任何图像处理库。
- 跨平台:Windows下发布了编译好的.node文件,下载就能用。
- 使用简单:jQuery风格的API,简单可依赖
我们可以使用它来裁剪, 压缩图片, 基本使用如下:
const images = require("images");images("input.jpg") //加载图像文件 .size(400) //等比缩放图像到400像素宽 .draw(images("logo.png"), 10, 10) //在(10,10)处绘制Logo .save("output.jpg", { //保存图片到文件,图片质量为50 quality : 50 });复制代码
在H5-Dooring 编辑器中哦你也使用了它来做图片处理和编辑, 大家也可以更根据实际业务来使用.
14. node端解析“命令行指令字符串”实现线上自动打包部署项目
关于node解析cmd字符串并执行命令行指令的方式笔者之前在写自己实现一个自动化工作流的文章中也介绍过, 使用了child_process模块的exec, 具体实现可以参考文章:
基于NodeJS从零构建线上自动化打包工作流(H5-Dooring特别版)
这里写一个简单的例子:
const cmdStr = `cd ${outWorkDir} && yarn build ${fid}`// 解析命令行指令, 实现线上自动打包构建项目exec(cmdStr, function(err, stdout, stderr){ if(err) { console.log('api error:'+stderr); io.emit('htmlWorked', { result: 'error', message: stderr }) } else { // ... }})复制代码
15. 如何解决node应用崩溃, 负载均衡和进程管理
解决此问题最好的方式就是采用pm2 或者forever, 其提供了强大的node进程管理, 负载均衡的能力, 并提供了一定程度的应用监控, 建议在线上环境使用pm2 来管理我们的node应用.
觉得有用 ?喜欢就收藏,顺便点个赞吧,你的支持是我最大的鼓励!微信搜 “趣谈前端”,发现更多有趣的H5游戏, webpack,node,gulp,css3,javascript,nodeJS,canvas数据可视化等前端知识和实战.
相关推荐
- windows开启telnet服务,检测远程服务端口是否可以连通
-
本文介绍windwos开启telnet服务,telnet服务一般可以用于检测远程主机的某个端口服务是否可以连通,在日常的工作中,我们经常会遇到在本地的windows检测远程服务端口是否可以连通。win...
- 仅在Web登录新华三交换机条件下启用设备Telnet登录方式
-
概述Web登录新华三交换机可以在“网络-服务”页面中启用设备Telnet服务或SSH服务,也可以在“设备-管理员”设置管理员用户的可用服务,然而,在设备Web页面中,无法设置lineVTY用户线【l...
- 思科交换机,路由器如何关闭telnet 开启ssh服务
-
SSH为建立在应用层基础上的安全协议。SSH是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议。利用SSH协议可以有效防止远程管理过程中的信息泄露问题。今天我们就来说说思科交换机,路...
- 智能化弱电行业常用的DOS命令,掌握了你也能成为...
-
前言在做智能化弱电项目时,前端摄像头设备安装结束后,我们会对网络摄像头进行调试,调试过程中会遇到前端摄像头没有图像或者图像出来了画面卡顿的现象。我们会采用ping命令来测试网络的连通性和网络承载能力。...
- 「干货」eNSP模拟器之配置Telnet登录
-
配置说明:配置Telnet,使R2(模拟PC)通过SW1登录到R1进行管理和配置。操作步骤:system-view##进入系统视图[Huawei]sysnameR1##改名为R1[R1]int...
- win11开启telnet服务怎么操作 win11打开telent指令是什么
-
telnet服务是我们在进行远程连接的时候,必须要打开的一项功能。但是有不少用户们不清楚在windows11系统中怎么开启telnet服务。今天小编就使用详细的图文教程,来给大家说明一下打开telen...
- 华三(H3C)交换机Telnet的远程登陆
-
一,配置交换机管理IP[SW1]vlan20//创建管理vlan[SW1]interfacevlan20//进入vlan接口[SW1-Vlanif20]ipaddress192.168....
- win10 telnet命令怎么查看端口是否打开
-
可能大家也会遇到这个问题,win10telnet命令查看端口是否打开的步骤是什么?具体方法如下:1、键盘输入快捷键WIN+R,打开运行窗口。2、输入cmd,点击确定按钮。3、弹出cmd命令行窗...
- Windows 7如何打开Telnet功能(win7系统打开telnet)
-
Windows7默认安装后是没有开启telnet客户端功能的,例如,我们在开始菜单中输入cmd,然后使用telnet命令,会弹出下图提示:‘telnet’不是内部或外部命令,也不是可运行程序或批处理文...
- 为锐捷路由器交换机开启web和telnet,实现轻松管理
-
笔者上一篇文章写了关于锐捷二层交换机配置教程,那么接下来讲一下锐捷的路由交换设备配置web、telnet技巧。同样,今天的教程也是基于命令行,比较简单,适合新手小白进行学习。准备工作配置前准备:con...
- 一文学会telnet命令的用途和使用方法
-
Telnet是一个古老的远程登录协议,可以让本地计算机获得远程计算机的工作能力。它采用了TCP的可靠连接方式,可以连接任何网络互通的远程计算机。不过由于它采用了明文传输方式,存在安全风险,目前已经很少...
- Telnet命令是什么?如何使用?(telnet命令在哪里开启)
-
telnet命令是一个常用的远程登陆工具,使用它,我们可以快捷地登陆远程服务器进行操作。那么如何使用telnet命令呢?首先,我们需要打开telnet功能,任何电脑默认是关闭此功能的,开启方式如下:打...
- win11系统如何开启telnet服务(拷贝版本)
-
我们要知道,Telnet协议是Internet远程登陆服务的标准协议,可以使用户在本地计算机上完成远程主机的工作,不过对于一些刚接触win11中文版系统的用户来说,可能还不知道telnet服务在哪...
- 如何开启telnet客户端(如何开启telnet服务)
-
Telnet协议是TCP/IP协议家族中的一员,是Internet远程登陆服务的标准协议和主要方式,Telnet是常用的远程控制Web服务器的方法。工作中经常用到telnet客户端,但在windows...
- Telnet 是什么,如何启用它?(telnet有什么用)
-
对于Internet等TCP/IP网络,Telnet是一个终端仿真程序。Telnet软件在您的系统上运行并将您的个人计算机链接到网络服务器。它将所有数据转换为纯文本这一事实被认为是易受...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- navicat无法连接mysql服务器 (65)
- 下横线怎么打 (71)
- flash插件怎么安装 (60)
- lol体验服怎么进 (66)
- ae插件怎么安装 (62)
- yum卸载 (75)
- .key文件 (63)
- cad一打开就致命错误是怎么回事 (61)
- rpm文件怎么安装 (66)
- linux取消挂载 (81)
- ie代理配置错误 (61)
- ajax error (67)
- centos7 重启网络 (67)
- centos6下载 (58)
- mysql 外网访问权限 (69)
- centos查看内核版本 (61)
- ps错误16 (66)
- nodejs读取json文件 (64)
- centos7 1810 (59)
- 加载com加载项时运行错误 (67)
- php打乱数组顺序 (68)
- cad安装失败怎么解决 (58)
- 因文件头错误而不能打开怎么解决 (68)
- js判断字符串为空 (62)
- centos查看端口 (64)