Today there are exists a lot of web servers created for Node.js and it's hard to tell which one is better. Engineers are working to add something new into their products and using the last JS and v8 abilities to bring faster, handy and effective solutions. And I'm working on one too. It's Plant. In this article I will tell about Plant's ability to work without Node.js.
Plant is a WebAPI charged web server, what means it's using the same interfaces as browsers do. Also it's transport agnostic and you can deliver requests using anything: TCP, WebSocket, WebRTC, etc. Tying all this up it could work in a browser and on a server in the same way. What this ability gives to us?
- We can develop a web server using only code editor and web browser, using DevTool's debugger instead of console.log for troubleshooting and then just move it to Node.js.
- We don't even need to install anything.
- It makes tests more reliable and simple to write, run and understand.
- Easy to learn: code is isolated into browser and free of environment influence.
- Truly crossplatform: it works in the same way everywhere.
TL;DR. Here it is the simple demo and complex demo.
Well let's start. All you need to start is to create simple HTML file with empty page.
<!DOCTYPE html>
<html>
<head></head>
<body></body>
</html>
Import
To use Plant in your web page just import it from unpkg.com:
<script src="https://unpkg.com/@plant/plant@2.4.0/dist/plant.js"></script>
Put it into <head>
. Then create new <script>
into <body>
element for our application.
Create server
Server creation is similar to Express' or Koa's with small differences.
// Instantiate server
const plant = new Plant()
// Add handler
plant.use('/index.html', ({req, res}) => {
res.html('<!DOCTYPE html><html><body>Hello</body></html>')
})
That's it. We created a very simple request handler which serves '/index.html' page. Note that route is very strict. It would handle /index.html
but not /
.
Making request
Browsers couldn't listen requests and we will simulate it on ourselves. This code could be used to handle requests delivered by WebSocket or any other transport, so it could be used by anything.
This is our final code which will de explained later:
const handle = plant.getHandler()
const context = createContext('GET', 'https://localhost:8000/index.html')
handle(context)
.then(({res}) => {
res.status // -> 200
res.body // -> '<!DOCTYPE html>...
})
Creating context
Plant context is a simple Object instance. It requires Socket, Request and Response instances to be passed as socket
, req
and res
properties respectively.
function createContext(method, url, {headers = {}, body} = {}) {
const req = new Plant.Request({
url: new URL(url),
method,
body,
headers,
})
const res = new Plant.Response({
url: new URL(url),
})
const socket = new Plant.Socket({
peer: new Plant.Peer({
uri: new Plant.URI({
protocol: 'browser',
host: navigator.appName,
})
})
})
return {req, res, socket}
}
Socket requires a peer instance which represents another party of a connection. Peer should always have an address provided as URI. URI is using here instead of standard URL due to URL's inability to work with custom schemes. All this needed due we suggest that peer could receive connections too, because Plant can use transport supporting this ability.
POST requests
To simulate POST request we need to create ReadableStream instance and pass it into Request constructor.
const body = streamFrom('Hello')
new Request({
method: 'GET',
url: 'https://localhost:8000',
body,
})
function streamFrom(value) {
return new ReadableStream({
start(controller) {
// Encode UTF8 into Uint8Array and push it into the stream
const encoder = new TextEncoder()
controller.enqueue(encoder.encode(value))
controller.close()
},
})
}
Function createStream
creates ReadableStream instance and write whole passed value as a single chunk into it.
Conclusion
Now you can put it all together and emulates request right in a browser on your own without using Node.js. Or you can get write and debug your API in a browser and then move it to Node.js with minimal changes. And the same code could be used in tests.
If you meet some difficulties or want to check yourself use simple example or more complex demonstration.
Repositories
Plant
Plant is WebAPI standards based HTTP2 web server, created with modular architecture and functional design in mind. Also it's pure and less coupled.
Plant supports HTTP 1 and HTTP 2 protocols. But it's transport agnostic and can work right in the browser over WebSockets, WebRTC, or PostMessage.
Features
- ☁️ Lightweight: only 8 KiB minified and gzipped.
- ✨ Serverless ready: works even in browser.
- 🛡 Security oriented: uses the most strict Content Securiy Policy (CSP) by default.
- 📐 Standards based: uses WebAPI interfaces.
- 🛳 Transport agnostic: no HTTP or platform coupling, ship requests via everything.
Table of Contents
Install
Examples
Hello World
Hello world with HTTP2 as transport.
⚠️ Note that default CSP header value isdefault-src localhost; form-action localhost
This will…
rumkin / plant-browser-demo
Nodeless web server demo
Plant Browser Demo
This is a single-file demo web application. Its' purpose is to show how to develop fully functional web server with test coverage without Node.js using only browser and code editor.
Usage
- Save page on disk.
- Open it in code editor.
- Update
#Server
and#Spec
scripts code. - Refresh the page. DevTools console should contain complete output of your test.
Dependencies
Structure overview
Code of the example is structured into several scripts. Each script contains code related to specific task.
<script id="Server"></script>
<script id="Spec"></script>
<script id="TestupHelpers"></script>
<script id="PlantHelpers"></script>
<script id="Main"></script>
Where:
-
#Server
. Your http API code. -
#Spec
. Your tests for the…
Top comments (3)
So this is not a good practice right. But just a nice experiment.
Why?
It’s a production-ready solution. If you have tests and this tests pass in a browser and node.js, then you can develop in browser and run code in node.