cari
Rumahhujung hadapan webtutorial jsNode.js bijak melaksanakan kemas kini hangat bagi aplikasi web code_node.js

Latar belakang

Saya percaya bahawa pelajar yang telah membangunkan aplikasi web menggunakan Node.js pasti telah bermasalah dengan masalah bahawa kod yang baru diubah suai mesti dimulakan semula sebelum proses Node.js boleh dikemas kini. Pelajar yang biasa menggunakan PHP untuk pembangunan akan mendapati ia sangat tidak boleh digunakan Seperti yang dijangkakan, PHP adalah bahasa pengaturcaraan terbaik di dunia. Memulakan semula proses secara manual bukan sahaja merupakan pertindihan kerja yang sangat menjengkelkan, tetapi apabila skala aplikasi menjadi lebih besar, masa permulaan secara beransur-ansur mula menjadi tidak dapat diabaikan.

Sudah tentu, sebagai pengaturcara, tidak kira bahasa yang anda gunakan, anda tidak akan membiarkan perkara sebegitu menyeksa anda. Cara paling langsung dan universal untuk menyelesaikan masalah seperti ini ialah memantau pengubahsuaian fail dan memulakan semula proses. Kaedah ini juga telah disediakan oleh banyak penyelesaian matang, seperti penyelia nod yang terbengkalai, PM2 yang kini popular, atau nod-dev yang agak ringan, dsb., yang semuanya berdasarkan idea ini.

Artikel ini memberikan idea lain dengan hanya pengubahsuaian kecil, anda boleh mencapai kod kemas kini panas sifar semula dan menyelesaikan masalah kemas kini kod yang menjengkelkan semasa membangunkan aplikasi web dengan Node.js.

Idea umum

Bercakap tentang kemas kini panas kod, yang paling terkenal pada masa ini ialah fungsi kemas kini hangat bahasa Erlang Bahasa ini dicirikan oleh konkurensi tinggi dan pengaturcaraan teragih Senario aplikasi utamanya adalah bidang seperti perdagangan sekuriti dan pelayan permainan . Senario ini lebih kurang memerlukan perkhidmatan mempunyai cara pengendalian dan penyelenggaraan semasa operasi, dan pengemaskinian panas kod adalah bahagian yang sangat penting, jadi kita boleh melihat secara ringkas pendekatan Erlang.

Memandangkan saya tidak pernah menggunakan Erlang, kandungan berikut semuanya khabar angin Jika anda ingin mempunyai pemahaman yang mendalam dan tepat tentang pelaksanaan kemas kini panas kod Erlang, sebaiknya rujuk dokumentasi rasmi.

Pemuatan kod Erlang diuruskan oleh modul yang dipanggil code_server Kecuali beberapa kod yang diperlukan semasa permulaan, kebanyakan kod dimuatkan oleh code_server.
Apabila code_server mendapati bahawa kod modul telah dikemas kini, ia akan memuat semula modul Permintaan baharu selepas itu akan dilaksanakan menggunakan modul baharu, manakala permintaan yang masih dilaksanakan akan terus dilaksanakan menggunakan modul lama.
Modul lama akan dilabelkan lama selepas modul baharu dimuatkan dan modul baharu akan dilabel semasa. Semasa kemas kini panas seterusnya, Erlang akan mengimbas dan membunuh modul lama yang masih dilaksanakan, dan kemudian terus mengemas kini modul mengikut logik ini.
Tidak semua kod dalam Erlang membenarkan kemas kini hangat modul asas seperti kernel, stdlib, pengkompil dan modul asas lain tidak dibenarkan dikemas kini secara lalai
. Kita boleh mendapati bahawa Node.js juga mempunyai modul yang serupa dengan code_server, iaitu sistem yang diperlukan, jadi pendekatan Erlang juga harus dicuba pada Node.js. Dengan memahami pendekatan Erlang, kami boleh meringkaskan secara kasar isu utama dalam menyelesaikan kemas kini hangat kod dalam Node.js

Cara mengemas kini kod modul
Cara mengendalikan permintaan menggunakan modul baharu
Bagaimana untuk melepaskan sumber modul lama

Kemudian mari kita analisa titik masalah ini satu persatu.

Cara mengemas kini kod modul

Untuk menyelesaikan masalah kemas kini kod modul, kita perlu membaca pelaksanaan pengurus modul Node.js dan memaut terus ke module.js. Melalui pembacaan mudah, kita dapati bahawa kod teras terletak pada Module._load Mari permudahkan kod dan siarkan.

// Check the cache for the requested file.
// 1. If a module already exists in the cache: return its exports object.
// 2. If the module is native: call `NativeModule.require()` with the
// filename and return the result.
// 3. Otherwise, create a new module for the file and save it to the cache.
// Then have it load the file contents before returning its exports
// object.
Module._load = function(request, parent, isMain) {
 var filename = Module._resolveFilename(request, parent);

 var cachedModule = Module._cache[filename];
 if (cachedModule) {
 return cachedModule.exports;
 }

 var module = new Module(filename, parent);
 Module._cache[filename] = module;
 module.load(filename);

 return module.exports;
};

require.cache = Module._cache;

Anda boleh mendapati bahawa terasnya ialah Module._cache Selagi cache modul ini dikosongkan, pengurus modul akan memuatkan semula kod terkini apabila ia diperlukan.

Tulis program kecil untuk mengesahkannya

// main.js
function cleanCache (module) {
 var path = require.resolve(module);
 require.cache[path] = null;
}

setInterval(function () {
 cleanCache('./code.js');
 var code = require('./code.js');
 console.log(code);
}, 5000);
// code.js
module.exports = 'hello world';

Mari laksanakan main.js dan ubah suai kandungan code.js pada masa yang sama Kita dapati bahawa dalam konsol, kod kami telah berjaya dikemas kini kepada kod terkini.

Node.js bijak melaksanakan kemas kini hangat bagi aplikasi web code_node.js

Jadi masalah pengurus modul yang mengemas kini kod telah diselesaikan Seterusnya, mari lihat bagaimana kita boleh membuat modul baharu benar-benar dilaksanakan dalam aplikasi web.

Cara menggunakan modul baharu untuk mengendalikan permintaan

Untuk lebih selaras dengan tabiat penggunaan semua orang, kami akan terus menggunakan Express sebagai contoh untuk mengembangkan masalah ini Malah, menggunakan idea yang sama, kebanyakan aplikasi web boleh digunakan.

Pertama sekali, jika perkhidmatan kami seperti DEMO Express dan semua kod berada dalam modul yang sama, kami tidak boleh memuatkan modul tersebut

var express = require('express');
var app = express();

app.get('/', function(req, res){
 res.send('hello world');
});

app.listen(3000);

Untuk mencapai pemuatan panas, sama seperti perpustakaan asas yang tidak dibenarkan di Erlang, kami memerlukan beberapa kod asas yang tidak boleh dikemas kini secara panas untuk mengawal proses kemas kini. Dan jika operasi seperti app.listen dilaksanakan semula, ia tidak akan jauh berbeza daripada memulakan semula proses Node.js. Oleh itu, kami memerlukan beberapa kod pintar untuk mengasingkan kod perniagaan yang kerap dikemas kini daripada kod asas yang jarang dikemas kini.

// app.js 基础代码
var express = require('express');
var app = express();
var router = require('./router.js');

app.use(router);

app.listen(3000);
// router.js 业务代码
var express = require('express');
var router = express .Router();

// 此处加载的中间件也可以自动更新
router.use(express.static('public'));

router.get('/', function(req, res){
 res.send('hello world');
});

module.exports = router;

然而很遗憾,经过这样处理之后,虽然成功的分离了核心代码, router.js 依然无法进行热更新。首先,由于缺乏对更新的触发机制,服务无法知道应该何时去更新模块。其次, app.use 操作会一直保存老的 router.js 模块,因此即使模块被更新了,请求依然会使用老模块处理而非新模块。

那么继续改进一下,我们需要对 app.js 稍作调整,启动文件监听作为触发机制,并且通过闭包来解决 app.use 的缓存问题

// app.js
var express = require('express');
var fs = require('fs');
var app = express();

var router = require('./router.js');

app.use(function (req, res, next) {
 // 利用闭包的特性获取最新的router对象,避免app.use缓存router对象
 router(req, res, next);
});

app.listen(3000);

// 监听文件修改重新加载代码
fs.watch(require.resolve('./router.js'), function () {
 cleanCache(require.resolve('./router.js'));
 try {
  router = require('./router.js');
 } catch (ex) {
  console.error('module update failed');
 }
});

function cleanCache(modulePath) {
 require.cache[modulePath] = null;
}

再试着修改一下 router.js 就会发现我们的代码热更新已经初具雏形了,新的请求会使用最新的 router.js 代码。除了修改 router.js 的返回内容外,还可以试试看修改路由功能,也会如预期一样进行更新。

当然,要实现一个完善的热更新方案需要更多结合自身方案做一些改进。首先,在中间件的使用上,我们可以在 app.use 处声明一些不需要热更新或者说每次更新不希望重复执行的中间件,而在 router.use 处则可以声明一些希望可以灵活修改的中间件。其次,文件监听不能仅监听路由文件,而是要监听所有需要热更新的文件。除了文件监听这种手段外,还可以结合编辑器的扩展功能,在保存时向 Node.js 进程发送信号或者访问一个特定的 URL 等方式来触发更新。

如何释放老模块的资源

要解释清楚老模块的资源如何释放的问题,实际上需要先了解 Node.js 的内存回收机制,本文中并不准备详加描述,解释 Node.js 的内存回收机制的文章和书籍很多,感兴趣的同学可以自行扩展阅读。简单的总结一下就是当一个对象没有被任何对象引用的时候,这个对象就会被标记为可回收,并会在下一次GC处理的时候释放内存。

那么我们的课题就是,如何让老模块的代码更新后,确保没有对象保持了模块的引用。首先我们以 如何更新模块代码 一节中的代码为例,看看老模块资源不回收会出现什么问题。为了让结果更显著,我们修改一下 code.js

// code.js
var array = [];

for (var i = 0; i < 10000; i++) {
 array.push('mem_leak_when_require_cache_clean_test_item_' + i);
}

module.exports = array;
// app.js
function cleanCache (module) {
 var path = require.resolve(module);
 require.cache[path] = null;
}

setInterval(function () {
 var code = require('./code.js');
 cleanCache('./code.js');
}, 10);

好~我们用了一个非常笨拙但是有效的方法,提高了 router.js 模块的内存占用,那么再次启动 main.js 后,就会发现内存出现显著的飙升,不到一会 Node.js 就提示 process out of memory。然而实际上从 app.js 与 router.js 的代码中观察的话,我们并没发现哪里保存了旧模块的引用。

我们借助一些 profile 工具如 node-heapdump 就可以很快的定位到问题所在,在 module.js 中我们发现 Node.js 会自动为所有模块添加一个引用

function Module(id, parent) {
 this.id = id;
 this.exports = {};
 this.parent = parent;
 if (parent && parent.children) {
 parent.children.push(this);
 }

 this.filename = null;
 this.loaded = false;
 this.children = [];
}

因此相应的,我们可以调整一下cleanCache函数,将这个引用在模块更新的时候一并去除。

// app.js
function cleanCache(modulePath) {
 var module = require.cache[modulePath];
 // remove reference in module.parent
 if (module.parent) {
  module.parent.children.splice(module.parent.children.indexOf(module), 1);
 }
 require.cache[modulePath] = null;
}

setInterval(function () {
 var code = require('./code.js');
 cleanCache(require.resolve('./code.js'));
}, 10); 

再执行一下,这次好多了,内存只会有轻微的增长,说明老模块占用的资源已经正确的释放掉了。

使用了新的 cleanCache 函数后,常规的使用就没有问题,然而并非就可以高枕无忧了。在 Node.js 中,除了 require 系统会添加引用外,通过 EventEmitter 进行事件监听也是大家常用的功能,并且 EventEmitter 有非常大的嫌疑会出现模块间的互相引用。那么 EventEmitter 能否正确的释放资源呢?答案是肯定的。

// code.js
var moduleA = require('events').EventEmitter();

moduleA.on('whatever', function () {
});

Apabila modul code.js dikemas kini dan semua rujukan dialihkan keluar, modulA juga akan dikeluarkan secara automatik selagi ia tidak dirujuk oleh modul lain yang belum dikeluarkan, termasuk pendengar acara dalaman kami.

Hanya terdapat satu senario aplikasi EventEmitter yang cacat yang tidak boleh ditangani di bawah sistem ini, iaitu code.js akan mendengar peristiwa pada objek global setiap kali ia dilaksanakan, yang akan menyebabkan peristiwa pelekap berterusan pada objek global . Pada masa yang sama, Node.js akan segera menggesa bahawa terlalu banyak pengikatan peristiwa telah dikesan, yang mungkin merupakan kebocoran memori.

Pada ketika ini, anda dapat melihat bahawa selagi rujukan yang ditambahkan secara automatik oleh Node.js dalam sistem memerlukan diproses, kitar semula sumber modul lama bukanlah masalah besar, walaupun kami tidak dapat mencapai kemas kini panas seterusnya seperti Erlang . Modul lama yang tinggal tertakluk kepada kawalan terperinci seperti pengimbasan, tetapi kami boleh menyelesaikan masalah pelepasan sumber modul lama melalui kaedah pengelakan yang munasabah.

Dalam aplikasi web, masalah rujukan lain ialah modul yang belum dikeluarkan atau modul teras mempunyai rujukan kepada modul yang perlu dikemas kini secara hangat, seperti app.use Akibatnya, sumber modul lama tidak boleh dikeluarkan dan baharu permintaan tidak boleh diproses dengan betul. Gunakan modul baharu untuk pemprosesan. Penyelesaian kepada masalah ini adalah untuk mengawal entri terdedah pembolehubah global atau rujukan, dan mengemas kini secara manual entri semasa pelaksanaan kemas kini panas. Sebagai contoh, enkapsulasi penghala dalam Cara Menggunakan Modul Baharu untuk Memproses Permintaan adalah contoh Melalui kawalan entri ini, tidak kira bagaimana kita merujuk modul lain dalam router.js, ia akan dikeluarkan dengan keluaran entri. .

Masalah lain yang boleh menyebabkan keluaran sumber ialah operasi seperti setInterval, yang akan mengekalkan kitaran hayat objek daripada dikeluarkan Walau bagaimanapun, kami jarang menggunakan teknologi jenis ini dalam aplikasi web, jadi kami tidak memberi perhatian kepadanya rancangan itu.

Epilog

Setakat ini, kami telah menyelesaikan tiga masalah utama kemas kini panas kod Node.js dalam aplikasi web Walau bagaimanapun, kerana Node.js sendiri tidak mempunyai mekanisme pengimbasan yang berkesan untuk objek yang dikekalkan, ia tidak boleh 100% menghapuskan masalah yang disebabkan oleh setInterval. Sumber modul lama tidak boleh dikeluarkan. Ia juga disebabkan oleh pengehadan sedemikian yang dalam rangka kerja YOG2 yang kami sediakan pada masa ini, teknologi ini digunakan terutamanya dalam tempoh pembangunan dan penyahpepijatan untuk mencapai pembangunan pesat melalui kemas kini hangat. Kemas kini kod dalam persekitaran pengeluaran masih menggunakan fungsi restart atau hot reload PM2 untuk memastikan kestabilan perkhidmatan dalam talian.

Memandangkan kemas kini hangat sebenarnya berkait rapat dengan rangka kerja dan seni bina perniagaan, artikel ini tidak memberikan penyelesaian umum. Sebagai rujukan, mari kita perkenalkan secara ringkas cara kami menggunakan teknologi ini dalam rangka kerja YOG2. Memandangkan rangka kerja YOG2 itu sendiri menyokong pemisahan apl antara subsistem hadapan dan belakang, strategi kemas kini kami adalah untuk mengemas kini kod pada butiran apl. Pada masa yang sama, kerana operasi seperti fs.watch akan mempunyai masalah keserasian, dan beberapa alternatif seperti fs.watchFile akan menggunakan lebih banyak prestasi, jadi kami menggabungkan fungsi penggunaan mesin ujian YOG2 untuk memaklumkan rangka kerja bahawa ia perlu dikemas kini oleh memuat naik dan menggunakan kod apl baharu. Semasa mengemas kini cache modul pada butiran Apl, cache penghalaan dan cache templat akan dikemas kini untuk melengkapkan semua kemas kini kod.

Jika anda menggunakan rangka kerja seperti Express atau Koa, anda hanya perlu mengikut kaedah dalam artikel dan menggabungkan keperluan perniagaan anda sendiri dengan beberapa pengubahsuaian pada laluan utama, dan anda boleh menggunakan teknologi ini dengan baik.

Kenyataan
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
JavaScript: meneroka serba boleh bahasa webJavaScript: meneroka serba boleh bahasa webApr 11, 2025 am 12:01 AM

JavaScript adalah bahasa utama pembangunan web moden dan digunakan secara meluas untuk kepelbagaian dan fleksibiliti. 1) Pembangunan front-end: Membina laman web dinamik dan aplikasi satu halaman melalui operasi DOM dan kerangka moden (seperti React, Vue.js, sudut). 2) Pembangunan sisi pelayan: Node.js menggunakan model I/O yang tidak menyekat untuk mengendalikan aplikasi konkurensi tinggi dan masa nyata. 3) Pembangunan aplikasi mudah alih dan desktop: Pembangunan silang platform direalisasikan melalui reaktnatif dan elektron untuk meningkatkan kecekapan pembangunan.

Evolusi JavaScript: Trend Semasa dan Prospek Masa DepanEvolusi JavaScript: Trend Semasa dan Prospek Masa DepanApr 10, 2025 am 09:33 AM

Trend terkini dalam JavaScript termasuk kebangkitan TypeScript, populariti kerangka dan perpustakaan moden, dan penerapan webassembly. Prospek masa depan meliputi sistem jenis yang lebih berkuasa, pembangunan JavaScript, pengembangan kecerdasan buatan dan pembelajaran mesin, dan potensi pengkomputeran IoT dan kelebihan.

Demystifying JavaScript: Apa yang berlaku dan mengapa pentingDemystifying JavaScript: Apa yang berlaku dan mengapa pentingApr 09, 2025 am 12:07 AM

JavaScript adalah asas kepada pembangunan web moden, dan fungsi utamanya termasuk pengaturcaraan yang didorong oleh peristiwa, penjanaan kandungan dinamik dan pengaturcaraan tak segerak. 1) Pengaturcaraan yang didorong oleh peristiwa membolehkan laman web berubah secara dinamik mengikut operasi pengguna. 2) Penjanaan kandungan dinamik membolehkan kandungan halaman diselaraskan mengikut syarat. 3) Pengaturcaraan Asynchronous memastikan bahawa antara muka pengguna tidak disekat. JavaScript digunakan secara meluas dalam interaksi web, aplikasi satu halaman dan pembangunan sisi pelayan, sangat meningkatkan fleksibiliti pengalaman pengguna dan pembangunan silang platform.

Adakah Python atau JavaScript lebih baik?Adakah Python atau JavaScript lebih baik?Apr 06, 2025 am 12:14 AM

Python lebih sesuai untuk sains data dan pembelajaran mesin, manakala JavaScript lebih sesuai untuk pembangunan front-end dan penuh. 1. Python terkenal dengan sintaks ringkas dan ekosistem perpustakaan yang kaya, dan sesuai untuk analisis data dan pembangunan web. 2. JavaScript adalah teras pembangunan front-end. Node.js menyokong pengaturcaraan sisi pelayan dan sesuai untuk pembangunan stack penuh.

Bagaimana saya memasang javascript?Bagaimana saya memasang javascript?Apr 05, 2025 am 12:16 AM

JavaScript tidak memerlukan pemasangan kerana ia sudah dibina dalam pelayar moden. Anda hanya memerlukan editor teks dan penyemak imbas untuk memulakan. 1) Dalam persekitaran penyemak imbas, jalankan dengan memasukkan fail HTML melalui tag. 2) Dalam persekitaran Node.js, selepas memuat turun dan memasang node.js, jalankan fail JavaScript melalui baris arahan.

Bagaimana cara menghantar pemberitahuan sebelum tugas bermula di kuarza?Bagaimana cara menghantar pemberitahuan sebelum tugas bermula di kuarza?Apr 04, 2025 pm 09:24 PM

Cara Menghantar Pemberitahuan Tugas di Quartz terlebih dahulu Apabila menggunakan pemasa kuarza untuk menjadualkan tugas, masa pelaksanaan tugas ditetapkan oleh ekspresi cron. Sekarang ...

Dalam JavaScript, bagaimana untuk mendapatkan parameter fungsi pada rantaian prototaip dalam pembina?Dalam JavaScript, bagaimana untuk mendapatkan parameter fungsi pada rantaian prototaip dalam pembina?Apr 04, 2025 pm 09:21 PM

Cara mendapatkan parameter fungsi pada rantaian prototaip dalam JavaScript dalam pengaturcaraan JavaScript, pemahaman dan memanipulasi parameter fungsi pada rantaian prototaip adalah tugas yang biasa dan penting ...

Apakah sebab kegagalan perpindahan gaya dinamik Vue.js dalam program WeChat Mini Webview?Apakah sebab kegagalan perpindahan gaya dinamik Vue.js dalam program WeChat Mini Webview?Apr 04, 2025 pm 09:18 PM

Analisis sebab mengapa kegagalan anjakan gaya dinamik menggunakan vue.js dalam pandangan web applet weChat menggunakan vue.js ...

See all articles

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
3 minggu yang laluBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
3 minggu yang laluBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Cara Memperbaiki Audio Jika anda tidak dapat mendengar sesiapa
3 minggu yang laluBy尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Cara Membuka Segala -galanya Di Myrise
3 minggu yang laluBy尊渡假赌尊渡假赌尊渡假赌

Alat panas

mPDF

mPDF

mPDF ialah perpustakaan PHP yang boleh menjana fail PDF daripada HTML yang dikodkan UTF-8. Pengarang asal, Ian Back, menulis mPDF untuk mengeluarkan fail PDF "dengan cepat" dari tapak webnya dan mengendalikan bahasa yang berbeza. Ia lebih perlahan dan menghasilkan fail yang lebih besar apabila menggunakan fon Unicode daripada skrip asal seperti HTML2FPDF, tetapi menyokong gaya CSS dsb. dan mempunyai banyak peningkatan. Menyokong hampir semua bahasa, termasuk RTL (Arab dan Ibrani) dan CJK (Cina, Jepun dan Korea). Menyokong elemen peringkat blok bersarang (seperti P, DIV),

SublimeText3 Linux versi baharu

SublimeText3 Linux versi baharu

SublimeText3 Linux versi terkini

Dreamweaver Mac版

Dreamweaver Mac版

Alat pembangunan web visual

SublimeText3 versi Inggeris

SublimeText3 versi Inggeris

Disyorkan: Versi Win, menyokong gesaan kod!

DVWA

DVWA

Damn Vulnerable Web App (DVWA) ialah aplikasi web PHP/MySQL yang sangat terdedah. Matlamat utamanya adalah untuk menjadi bantuan bagi profesional keselamatan untuk menguji kemahiran dan alatan mereka dalam persekitaran undang-undang, untuk membantu pembangun web lebih memahami proses mengamankan aplikasi web, dan untuk membantu guru/pelajar mengajar/belajar dalam persekitaran bilik darjah Aplikasi web keselamatan. Matlamat DVWA adalah untuk mempraktikkan beberapa kelemahan web yang paling biasa melalui antara muka yang mudah dan mudah, dengan pelbagai tahap kesukaran. Sila ambil perhatian bahawa perisian ini