自分のアプリケーション ログを確認すると、ログ ページに入ってからロードするのに常に数秒かかることがわかりました (インターフェイスはページ分割されていません)。そのため、ネットワーク パネルを開いて確認しました。
その場合に、インターフェイスが圧縮されていないことがわかりまし
たここでは Node.Service
この記事ではHTTP数据压缩
Node侧的实践
します
。
クライアントがサーバーへのリクエストを開始すると、リクエスト ヘッダーにaccept-encoding
フィールドが追加されます。このフィールドの値は支持的压缩内容编码
content-encoding
することにより、コンテンツの实际压缩使用的编码算法
deflate
LZ77
アルゴリズムと哈夫曼编码(Huffman Coding)
両方を使用します哈夫曼编码(Huffman Coding)
に基づくデータ圧縮アルゴリズム。
gzip
DEFLATE
です
Brotli
br
データ形式はdeflate
圧縮率20%
さらに改善することを目的としています。
Gzip
Deflate/Inflate
zlib 模块
Brotli
gzip
では、シナリオに応じてDeflate/Inflate
およびBrotli
が使用される例として使用します。同じ方法ですが、API は
stream
操作に基づいています。
buffer
の操作
いくつかの必須モジュールを導入します
const zlib = require('zlib') const fs = require('fs') const ストリーム = require('ストリーム') const testFile = 'tests/origin.log' const targetFile = `${testFile}.gz` Const decodeFile = `${testFile}.un.gz`
/圧縮の結果ビュー。ここではdu
コマンドを使用して、解凍前後の結果を直接カウントします。
# du -ah テストを実行します。 # 結果は以下の通り 108K testing/origin.log.gz 220 万のテスト/origin.log 220万テスト/origin.log.un.gz 4.6M は、
createGzip
とcreateUnzip
使用した
流(stream)
ベースの操作zlib
API は、Node.js 内部スレッド プールを使用し、非同期と見なすことができる方法 1:インスタンスのpipe
メソッドを直接使用してストリームを転送します。
// 圧縮 const readStream = fs.createReadStream(testFile) const writeStream = fs.createWriteStream(targetFile) readStream.pipe(zlib.createGzip()).pipe(writeStream) // 解凍 const readStream = fs.createReadStream(targetFile) const writeStream = fs.createwriteStream(decodeFile) readstream.pipe(zlib.createunzip())。パイプ(writestream)
メソッド2: stream
でpipeline
を使用すると、コールバック
//圧縮const readstream = fs.createreadstream(testfile)で他の処理を行うことができます。
const writeStream = fs.createWriteStream(targetFile) stream.pipeline(readstream、zlib.creategzip()、writestream、err => { if (エラー) { コンソール.エラー(エラー); } }) // const readstream = fs.createreadStream(TargetFile)を減圧する const writeStream = fs.createWriteStream(decodeFile) stream.pipeline(readstream、zlib.createunzip()、writestream、err => { if (エラー) { console.error(err); } })
方法3: Promise pipeline
Method
const {promisify} = require( 'util') const パイプライン = promisify(stream.pipeline) // Const const readStream = fs.CreaterEadStream(testFile) const writeStream = fs.createwriteStream(targetfile) パイプライン(readStream、zlib.createGzip()、writeStream) .catch(err => { コンソール.エラー(エラー); }) // 解凍 const readStream = fs.createReadStream(targetFile) const writeStream = fs.createwriteStream(decodeFile) パイプライン(ReadStream、Zlib.Createunzip()、WriteStream) .catch(err => { console.error(err); })
Buffer
ベースの操作では、gzip
API とunzip
API を利用します。これらの 2 つのメソッドには、同步
と异步
の
gzip
gzipSync
unzip
unzipSync
メソッド 1: readStream
Buffer
に変換し、その後の操作を実行します。
// Compression const buff = [] readStream.on('データ', (チャンク) => { buff.push(チャンク) }) readStream.on('end', () => { zlib.gzip(Buffer.concat(buff), targetFile, (err, resBuff) => { if(エラー){ コンソール.エラー(エラー); process.exit() } fs.writeFileSync(targetFile,resBuff) }) })
// 圧縮 const buff = [] readStream.on('データ', (チャンク) => { buff.push(チャンク) }) readStream.on('end', () => { fs.writeFileSync(targetFile,zlib.gzipSync(Buffer.concat(buff))) })
方法 2: readFileSync
を通じて直接読み取る
// 圧縮された const readBuffer = fs.readFileSync(testFile) const decodeBuffer = zlib.gzipSync(readBuffer) fs.writeFileSync(targetFile,decodeBuffer) // 解凍 const readBuffer = fs.readFileSync(targetFile) const decodeBuffer = zlib.gzipSync(decodeFile) fs.writefilesync(targetfile、decodebuffer)
ファイル圧縮に加えて、テキストコンテンツの圧縮/圧縮は、送信されたコンテンツを直接解凍する必要がある場合が
あり
ます
readFileSync( testFile, { encoding: 'utf-8' })
流(stream)
操作に基づいてstring
= buffer
bufferconstbuffer=Buffer.from(testData)
buffer
= stream
streamconsttransformStream
string
buffer
stream
検討してください。
= 新しいストリーム.PassThrough() transformStream.Write(バッファー) // または const transformStream = new Stream.Duplex() transformstream.push(buffer.from(testData)) transformStream.push(null)
ここではファイルに書き込む例を示します。もちろん、 HTTP的Response
(後で別途紹介します) などの他のストリームに書き込むこともできます
。 .pipe(zlib.creategzip()) .pipe(fs.createWriteStream(targetFile)) は、Buffer.from を使用して、バッファー操作
constbuffer = Buffer.from(testData)
Buffer
基づいてBuffer.from
列をbuffer
に変換し
、変換のために同期 API を直接使用します。コンテンツ
const result = zlib.gzipsync(buffer)はファイル
http
HTTP Server
圧縮コンテンツを直接返すこともできます
。他のノードWebフレームワークの
デモンストレーション用のシンプルなサーバーは
Node Web
もちろん、ワンクリックでアクセスできる既製のプラグインがあります。
const http = require( 'http') const {passthrough、pipeline} = require( 'stream') const zlib = require( 'zlib') //テストデータconst testtxt = 'テストデータ123'.repeat(1000) const app = http.createserver((req、res)=> { const {url} = req // サポートされている圧縮アルゴリズムを読み取る const acceptEncoding = req.headers['accept-encoding'].match(/(br|deflate|gzip)/g) //デフォルトの応答データ型 res.setHeader('Content-Type', 'application/json; charset=utf-8') //いくつかの例ルートconstルート= [ ['/gzip', () => { if(acceptencoding.includes( 'gzip')){ res.setheader( 'content-encoding'、 'gzip') //同期APIを使用して、テキストコンテンツRes.End(zlib.gzipsync(buffer.from(testtxt)))を直接圧縮する 戻る } res.end(testTxt) }]、 ['/deflate'、()=> { if(acceptencoding.includes( 'deflate'))){ res.setheader( 'Content-Encoding'、 'deflate') // Stream const riginstream = new passthrough()に基づく単一操作 OriginStream.Write(buffer.from(testTxt))) OriginStream.Pipe(zlib.createdeflate())。パイプ(res) OriginStream.End() 戻る } res.End(testtxt) }]、 ['/br', () => { if(acceptencoding.includes( 'br')){ res.setheader( 'content-encoding'、 'br') res.setHeader('Content-Type', 'text/html; charset=utf-8') // ストリームに基づく複数の書き込み操作 constoriginStream = new PassThrough() Pipeline(originStream, zlib.createBrotliCompress(), res, (err) => { if (エラー) { コンソール.エラー(エラー); } }) OriginStream.write(buffer.from( '<h1> brotlicompress </h1>')) OriginStream.write(buffer.from( '<h2>テストデータ</h2>')) OriginStream.write(Buffer.from(testTxt)) オリジンストリーム.エンド() 戻る } res.end(testTxt) }] 】 const ルート = ルート.find(v => url.startsWith(v[0])) if(route){ ルート[1]() 戻る } // res.setheaderに戻る( 'content-type'、 'text/html; charset = utf-8') res.end(`<h1>404: ${url}</h1> <h2>登録ルート</h2> <ul> $ {routes.map(r => `<li> <a href =" $ {r [0]} "> $ {r [0]} </a> </li>`).jein( '') } </ul> `) res.end() }) app.listen(3000)