{"id":16114750,"url":"https://github.com/solarliner/django-node","last_synced_at":"2025-04-06T08:17:02.607Z","repository":{"id":80989088,"uuid":"263181665","full_name":"SolarLiner/django-node","owner":"SolarLiner","description":"An experiment in making Node.js SSR available to Django.","archived":false,"fork":false,"pushed_at":"2020-05-11T23:29:58.000Z","size":30,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-12T13:48:14.658Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SolarLiner.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-11T23:26:26.000Z","updated_at":"2020-05-11T23:30:00.000Z","dependencies_parsed_at":null,"dependency_job_id":"b7374574-6100-4fba-97d0-01b6204aa23a","html_url":"https://github.com/SolarLiner/django-node","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SolarLiner%2Fdjango-node","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SolarLiner%2Fdjango-node/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SolarLiner%2Fdjango-node/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SolarLiner%2Fdjango-node/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SolarLiner","download_url":"https://codeload.github.com/SolarLiner/django-node/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247451665,"owners_count":20940944,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-09T20:15:40.087Z","updated_at":"2025-04-06T08:17:02.593Z","avatar_url":"https://github.com/SolarLiner.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `django_node`\n\nAn experiment in making Node.js SSR available to Django.\n\n# Context\n\nDjango provides an excellent and mature ORM system simplifying descriptions of \nstructured data. On the front-end side, JavaScript has a mature web application\nlibrary, making it easy through the use of frameworks and libraries to create rich\nweb applications.  \nHowever, at first the HTML was generated through DOM manipulation directly in the\nbrowser, making low-end devices struggle to display those applications.\n\nOne of the many solutions to this problem is to render a version of the HTML on the\nserver before having the client \"hydrate\" the HTML - that is to say reconciliate the\nserver HTML with its internal representation, which is faster than starting on the\nclient from scratch. However, these techniques require JavaScript to be run on the\nserver, essentially rendering this technique innaccessible from any other platform\nthan Node.js itself.\n\nThe use-case behind this approach is to be able to use Django's ORM while being\nable to use SSR to boost performance on web browsers.\n\n# The approach\n\nA first version of this used a naive \"transitive node process\" approach where the \nnode executable was launched with the frontend script for every request. This worked\nand helped iron out the API surface but proved to be too resource-intensive and slow\nfor even the lightest of workloads.\n\nThis version uses [ZeroMQ](https://zeromq.org/) to transfer a JSON string out of the\nDjango server process into the node process, and take a string in from the Node \nprocess (i.e. containing the resulting HTML) and back to the Django server. In the\ncurrent approach, the Node process is in charge of outputing *all* the HTML; basically\nthe Django server process acts as a proxy for the Node server.\n\nBecause the messaging system is implemented with ZeroMQ, there is no additional\noverhead of bringing up an additional HTTP server on the Node process; and ZeroMQ has\nproven itself to be reliable.\n\n## The Django infrastrcture\n\nMost of the work is pulled by an implementation of `HttpResponse` that sends a\nPython dictionary encoded as JSON and passed through ZeroMQ as a string in request\nmode. [`NodeHttpResponse`](noderesponse/http.py) then waits for a response that it will take to be the body\nof the response for the Django server.  \n\nThe communication is triggered on the first access to the `NodeHttpResponse.connect`\nproperty. This property access is idempotent - the communication will only be triggered\nonce for the instance, and the response is cached and re-used on any subsequent\n`connect` access.\n\nThe [`NodeResponseMixin`](noderesponse/views.py) mixin is a sibling of \n`SimpleTemplateResponse` in spirit - it, along with `NodeView`, the counterpart of `View`\nallows all of the higher-level features of Django views to work seamlessly to the\nuser. Most of the classes in [the `generic` module](noderesponse/generic) are direct\nre-implementation (even reusing Django code by assigning functions directly in the \nnew classes) of the generic Django view, allowing for simple creation of Node.js-based\nviews. As an example, see [`views.py`](example_nodeview/views.py) in the example Django\napplication.\n\n## The Node.js infrastructure\n\nThe Node process sets up a ZeroMQ server which listens for incoming messages. Its job\nis to deserialize the JSON string and process the request (typically this should be\nimplemented in its own module to hide the implementation details, and leaving the \nrequest processing to end-users), before sending back the generated HTML (hardcoded\ncontent-type for now, the response could be changed to allow the Node.js server to\nset the content-type itself) to the Django process.\n\nIn fact, there is nothing locking the setup to Node.js only, any process which setups\na ZeroMQ server can be used here; the process isn't managed by Django and must be\nstarted manually.\n\n# Conclusion\n\nWhile brittle and definitely not production-ready, this approach has the advantage of\nallowing Node.js-backed SSR to feature in monolithic server deployment scenarios, and\nin a lighter fashion than having two HTTP servers running on one machine, proxying\nrequests back and forth.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsolarliner%2Fdjango-node","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsolarliner%2Fdjango-node","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsolarliner%2Fdjango-node/lists"}