当前位置: 首页 > 后端技术 > Node.js

[翻译]HTTP-2ServerPush

时间:2023-04-03 19:59:07 Node.js

viaNode.js,Express.js原文:OptimizeYourAppwithHTTP/2ServerPushUsingNodeandExpress作者:AzatMardan代码:http2-node-server-pushWhatisHTTP/2ServerPushHTTP/2是web开发的新标准,它有很多好的优点,可以让web访问更快,开发工作更简单。例如,多路复用传输的引入不需要合并资源,服务器推送(ServerPush)资源允许浏览器预加载。本文并未描述HTTP/2的所有优点。您可以在上一篇文章中了解有关{%post_linkhttp2-node-express%}的更多信息。本文重点介绍在Node.js环境中使用Express.js和HTTP/2库spdy。服务器推送通过在一个HTTP/2请求中捆绑多个资源来工作。在后台,服务器发送一个PUSH_PROMISE,无论HTML文件是否需要资源,客户端(包括浏览器)都可以利用它。如果浏览器检测到需要该资源,它将匹配从服务器收到的PROMISE,并使该资源表现得像普通的浏览器Get请求资源一样。很明显,如果匹配到一个push,浏览器不需要重新请求,直接使用客户端缓存。这里有几篇关于ServerPush的好处的文章:ServerPush的好处是什么?AnnouncingSupportforHTTP/2ServerPush使用HTTP2.0ServerPush进行创新这是一个在Node.js教程中实现ServerPush的实践。为了清楚和简单起见,我们只实现一个路由地址为/pushy的Node.js和Express.js服务器,它会推送一个JS文件。如前所述,我们将使用HTTP/2库spdy。HTTP/2和Node.js首先解释一下为什么在Node.js环境下选择HTTP/2库spdy。目前,有两个主要的库为Node.js实现了HTTP/2:spdyhttp2这两个库与Node.js核心模块的http和https模块api非常相似。这意味着如果您不使用Express,则这两个库之间没有区别。不过spdy库支持HTTP/2和Express,而http2库目前不支持Express。这就是我们选择使用spdy的原因,它是Node.js非常适合Express的实践标准服务框架。之所以叫spdy,是源于谷歌的SPDY协议,后来升级为HTTP/2。HTTPS密钥和证书要在浏览器(Firefox、Safari、Chrome或Edge)中访问HTTPS,您需要生成密钥和证书。前往搜索“sslkeygeneration”或按照以下步骤生成密钥和证书。本文提供的源代码中没有上传生成的密钥和证书$mkdirhttp2-node-server-push$cdhttp2-node-server-push$opensslgenrsa-des3-passoutpass:x-outserver.pass。密钥2048...$opensslrsa-passinpass:x-inserver.pass.key-outserver.keywritingRSAkey$rmserver.pass.key$opensslreq-new-keyserver.key-outserver.csr...CountryName(2lettercode)[AU]:USStateorProvinceName(fullname)[Some-State]:California...Achallengepassword[]:...$opensslx509-req-sha256-days365-inserver.csr-signkeyserver.key-outserver.crt按照上面的步骤,你会生成三个SSL文件:.crt.构建项目首先初始化项目,通过package.json下载项目依赖:npminit-ynpmiexpress@4.14.0morgan@1.7.0spdy@3.4.0--savenpminode-dev@3.1.1--save-dev当前目录结构如下/http2-node-server-push/node_modulesindex.jspackage.jsonserver.crtserver.csrserver.key然后在package.json的scripts中添加两行脚本,简化命令(node-dev,automaticOverload):"start":"./node_modules/.bin/node-dev.","start-advanced":"./node_modules/.bin/node-devindex-advanced.js"现在你可以开始使用Node.js,Express.js,spdy用服务器推送写这个简单的实现HTTP/2服务器写脚本首先,创建index.js脚本,并导入和实例化依赖,看看上面的项目目录结构。其中,我使用了ES6/ES2015语法const来声明依赖。如果您不熟悉声明语法,可以阅读每个忙碌的JavaScript开发人员必须知道的10大ES6功能。consthttp2=require('spdy')constlogger=require('morgan')constexpress=require('express')constapp=express()constfs=require('fs')然后,设置morganlogger监听服务了哪些请求的服务器。app.use(logger('dev'))设置首页,可见/pushy是我们服务器推送的页面。app.get('/',function(req,res){res.send(`hello,http2!goto/pushy`)})serverpush只是调用spdy实现的res.push,我们设置文件path名称作为第一个参数传入,浏览器将使用此路径名来匹配推送承诺资源。res.push()的第一个参数/main.js必须匹配HTML文件中所需的文件名。第二个参数是可选对象,设置资源的一些资源信息描述。app.get('/pushy',(req,res)=>{varstream=res.push('/main.js',{status:200,//可选方法:'GET',//可选请求:{accept:'*/*'},response:{'content-type':'application/javascript'}})stream.on('error',function(){})stream.end('alert("hellofrompushstream!");')res.end('')})可以看到,stream对象有on和end两个方法。前者监听error和finish事件,后者监听发送端完成,然后main.js会触发弹窗。或者,如果你有多个数据块,你可以选择使用res.write()最后使用res.end(),其中res.end()会自动关闭结束响应,而res.write()会保持打开状态.(这在本文的源代码中没有实现)最后,读取HTTPS密钥和证书并使用spdy启动服务器。varoptions={key:fs.readFileSync('./server.key'),cert:fs.readFileSync('./server.crt')}http2.createServer(options,app).listen(8080,()=>{console.log(`服务器正在侦听https://localhost:8080。您可以在浏览器中打开URL。`)})此实现的关键在于流。不是树林中的河流,而是开发人员从源到客户使用的已建立的数据通道流。如果你对Node.js和Express.js的流程和HTTP请求和返回信息一知半解,可以看看你不知道的Node启动和使用命令节点索引比较HTTP/2ServerPush这篇文章。js或者npmstat运行服务器脚本,然后访问https://localhost:3000/pushy,就可以看到弹窗了!而我们这个路由是没有文件的,可以查看服务端的日志,在服务端没有推送的情况下,只会有一次请求,而不是两次请求(一个HTML,一个JS)。可以在浏览器中检测到接收服务器端推送的行为。启动Chrome开发者工具,打开Network选项卡,可以看到main.js里面没有绿色的时间条,说明没有等待时间TTFB(TimetoFirstByte),仔细看可以看到request是由Push发起的(在Initiator栏查看),如果没有使用HTTP/2服务器或者服务器推送的HTTP/1,该栏会显示文件名,比如index.html,index发起的显示.html是index.html。实践结束,使用Express和Spdy简单推送JS资源,这个资源可以用于后面HTML中