13+ReviewNode项目遇到的常见问题及解决方案整理一下解决方案,避免大家继续踩坑。事不宜迟,让我们开始吧!1.window和mac下设置NODE_ENV变量的问题我们都知道在前端项目中,会根据不同的环境变量来处理不同的逻辑。在nodejs中也是如此。我们需要设置本地的开发环境、测试环境、线上环境等,这时候一直设置环境变量的解决方法是在package.json中的script属性中设置,如下:"scripts":{"start":"exportNODE_ENV=development&&nodemon-wsrc--exec\"babel-nodesrc\"","build":"babelsrc--out-dirdist","run-build":"nodedist","test":"echo\"Error:notestspecified\"&&exit1"}从start命令可以发现我们使用exportNODE_ENV=development来定义开发环境的环境变量。由于笔者使用的是Mac电脑,我们可以使用export来定义一个node环境变量。但是在和朋友开发项目的时候发现执行yarnstart后会报错。看了报错信息,发现是window下export不识别。后来笔者发现window定义的环境变量是可以设置的,所以对于window用户,如果使用上面的方法设置NODE_ENV,可以使用如下方法:"scripts":{"start":"setNODE_ENV=development&&nodemon-wsrc--exec\"babel-nodesrc\""}2.执行npminstall项目开发时出现node-gyp错误拉取新node项目代码执行npminstall时出现如下错误会报:node-gyp是在node环境下用来为不同平台生成不同编译器的工程文件。如果你遇到同样的针对该问题,我们可以采用如下解决方案:npminstall-gnode-gyp或者直接删除package-lock.json或yarn.lock,然后重新安装yarninstall或npminstall。笔者亲测有效3、node+koa2项目中删除设置cookie的解决方案由于HTTP是无状态协议,需要cookie来区分用户。我们可以把cookie看做是浏览器和服务器协同实现的一种规范。cookie的处理分为以下3个步骤(基础知识和重要知识):服务端发送cookie给客户端,浏览器保存cookie(后端可以设置expires或者maxAge,以a的形式存在会议)。好的cookie被发送到服务器。在开发node后台项目时,我们经常会涉及到用户管理模块,也就是说我们需要对用户的登录状态进行管理,在用户退出时及时删除用户的cookie。好在koa2自带了cookie处理工具方法,我们可以这样设置cookies:router.post(api.validVip,asyncctx=>{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通信由两部分组成:socket.io集成(或安装)在浏览器端加载的NodeJSHTTP服务器客户端库socket.io-client如果我们直接使用koa或者egg,需要让他们内部集成的http兼容socket.io。这时候我们可以这样处理:importkoafrom'koa';importhttpfrom'http';constapp=newkoa();constserver=http.createServer(app.callback());constio=require('socket.io')(server);//正常业务处理//ioio.on('connection',(socket)=>{console.log('auserconnected');socket.on('docload',(msg)=>{console.log('docload',msg)io.emit('getData',users)})});server.listen(3000,()=>{//...});通过以上方法,koa和socket.io就可以正常兼容了。以后我们IM应用就可以正常开发了!5、nodejs第三方模块依赖特定node版本导致的报错解决方法。我以前遇到过这种情况。主要原因是第三方不向下兼容node版本。此时的解决办法是更新这个更新第三方包到最新版本(如果还在维护),或者使用node包管理工具(n)切换到适配的node版本,如下://更新最新包npmixxx@latest//使用包管理工具nnpmi-gn可以很方便的管理node版本。如果您有兴趣,可以尝试一下。6、如何在nodejs中创建定时任务定时任务是后端开发中最常见的功能之一。其实质是系统根据时间规则自动在后台执行相应的任务。有java、PHP等丰富的后台语言。定时任务的支持,对于nodejs这个后起之秀来说,虽然没有这么成熟的生态,但是定时任务的模块还是有的,比如node-schedule。NodeSchedule是一个灵活的类似cron和非cron的Node.js作业调度程序。它允许我们使用可选的重复规则安排作业(任意函数)在特定日期执行。它在任何给定时间仅使用一个计时器(而不是每秒/分钟重新评估即将到来的作业)。一个很实际的场景是,我们想让节点程序在每年的双十一或者双十二自动抓取某电商公司的“商品羊毛”,推送到我们的邮箱中。这个时候,我们就可以使用NodeSchedule来启动一个定时任务来执行我们的业务操作。作者的很多节点应用都采用了类似的模型。有兴趣的可以互相交流。那么什么是cron-styleScheduling?github上有一个简单的介绍:所以我们可以这样写一个定时任务:letschedule=require('node-schedule');lettestJob=schedule。scheduleJob('42****',function(){console.log('这段代码会在以后每个时刻的第42分钟执行,比如22:42、23:42');});7.nodejs项目中使用import、export和decorator@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对应的模块,如下:yarnadd@babel/cli@babel/core@babel/node@babel/plugin-proposal-class-properties@babel/plugin-proposal-decorators@babel/preset-envthis你可以像写前端项目一样使用这些新的语法特性!8、nodejs优雅处理json文件,提升json读写性能为nodejs优化事实上,有很多事情要谈。这里主要说一下json相关的优化方案。我们需要从两个方面进行优化。一是json文件的读写性能。这时候我们可以使用fast-json-stringify来大大提高json的读写速度本质是提供了一套json-schema约束,让json结构更加有序,从而提高读取和查询速度的JSON。下面的使用方法:constfastJson=require('fast-json-stringify')conststringify=fastJson({title:'H5DooringSchema',type:'object',properties:{firstName:{type:'string'},lastName:{type:'string'},age:{description:'Ageinyears',type:'integer'},reg:{type:'string'}}})比如在H5的后台-dooring,有很多接口需要频繁读写json数据。这时候使用fast-json-stringify会大大提高读写性能另一方面,如果我们在node端操作json,如果使用原生的写法,会很麻烦。这时候我们最好自己封装json的读取来提高代码的简洁性,或者直接使用第三方库jsonfile来方便的读取json文件,使用如下例子:constjson=require('jsonfile')constfileName='h5-dooring.json'constjsonData=jsonFile.readFileSync(fileName)9.nodejs读取大文件报错解决方案在nodejs中我们可以使用两种方式来读写文件,如下:fs.readFile()一次性将文件读入内存,如果文件过大节点内存不足报错fs.createReadStream()以文件流的形式读取,此时,您不必担心文件的大小。从上面的介绍我们可以看出,如果我们要读取的文件可能非常大(比如视频这样的大文件),我们一开始就会使用fs.createReadStream()。其实如果我们需要读取文件Parsing,比如逐行分析resumes等文件提取关键语料,我们可以使用node的readline模块,这时候我们可以逐行读取解析文件行,以下情况:constfs=require("fs");constpath=require("path");constreadline=require("readline");constreadlineTask=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的功能。具体情况现在如下:importkoafrom'koa';从“koa-compress”导入压缩;constapp=newkoa();//打开gzipconstoptions={threshold:2048};应用程序使用(压缩(选项));当然koa-compress也有很多自定义配置项,大家自己感受一下11.解决window和linux系统下路径分隔符不一致的问题。这个问题也是系统之间的差异造成的,也是需要考虑的问题。我们都知道Linux系统下路径的分隔符是/,比如h5-dooring/src/pages,但是在window下解析的路径可能是h5-dooring\\src\\pages。这个时候我们就需要做适配,否则我们部署到不同的系统报错是难免的,所以我们需要全局配置路径通配符。作者的解决方法如下:importosfrom'os'const_$=(os.platform().toLowerCase()==='win32')?'\\':'/';这时候我们可以用_$来代替具体的路径。上面的代码使用了node的os模块。如果你有兴趣,可以研究一下。我们可以使用os模块处理许多由系统差异引起的有趣问题。12、nodejs是如何实现父子进程通信的?因为nodejs是单线程的,所以有时候我们需要支持处理多进程的业务。目前nodejs可以通过父子进程的模式来模拟多个进程。我们可以使用child_process,大体流程如下:之前笔者分享的很多node实战项目都采用了child_process,大体实现流程如下://child.jsfunctioncomputedTotal(arr,cb){//time-消耗计算任务}//与主进程通信//监控主进程Signalprocess.on('message',(msg)=>{computedTotal(bigDataArr,(flag)=>{//发送完成信号给主进程process.send(flag);})});//main.jsconst{fork}=require('child_process');app.use(async(ctx,next)=>{if(ctx.url==='/fetch'){constdata=ctx.request.body;//通知子进程开始执行任务并传入数据constres=awaitcreatePromisefork('./child.js',data)}//创建一个异步线程functioncreatePromisefork(childUrl,data){//加载子进程constres=fork(childUrl)//通知子进程开始工作data&&res.send(data)returnnewPromise(reslove=>{res.on('message',f=>{reslove(f)})})}awaitnext()})13.节点端图片编辑/压缩图片编辑压缩在很多使用前端技术的场景中很常见。事实上,有很多图像需要在节点端进行处理。毕竟客户端处理的质量不好控制,此时我们就可以使用node-images了,node-images是一个轻量级的跨平台的node端图像编解码库。其主要特点如下:轻量级:无需安装任何图像处理库跨平台:Windows下发布编译.node文件即可下载使用。易于使用:jQuery风格的API,简单可靠。我们可以用它来裁剪和压缩图像。基本用法如下:constimages=require("images");images("input.jpg")//loadimagefile.size(400)//将图片按比例缩放到400像素宽.draw(images("logo.png"),10,10)//在(10,10)处绘制Logo.save("output.jpg",{//保存图片到文件,图片质量为50quality:50});在H5-Dooring编辑器中,您也可以使用它来进行图片处理和编辑,您也可以根据实际业务使用。14、节点端解析“命令行命令串”,实现在线自动打包部署项目。作者在我写的实现自动化工作流的文章中也介绍了node解析cmd字符串和执行命令行命令的方式。使用child_process模块的exec。这里写一个简单的例子:constcmdStr=`cd${outWorkDir}&&yarnbuild${fid}`//解析命令行指令,实现在线自动打包构建项目exec(cmdStr,function(err,stdout,stderr){if(err){console.log('apierror:'+stderr);io.emit('htmlWorked',{result:'error',message:stderr})}else{//...}})15.如何解决节点应用崩溃、负载均衡和进程管理解决这个问题最好的方法是使用pm2或forever,它提供强大的节点进程管理、负载均衡能力,并提供一定程度的应用监控。推荐线上环境使用pm2来管理我们的节点应用。觉得有用吗?如果喜欢,请收藏。顺便给个赞。您的支持是对我最大的鼓励!微信搜索“趣谈前端”,发现更多有趣的H5小游戏,webpack、node、gulp、css3、javascript、nodeJS、Canvas数据可视化等前端知识与实战。
