Skip to content

Commit a544c23

Browse files
committed
book.n2o.space
1 parent 89bd57f commit a544c23

File tree

2 files changed

+378
-0
lines changed

2 files changed

+378
-0
lines changed

CNAME

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
book.n2o.space

index.html

+377
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,377 @@
1+
<!DOCTYPE html>
2+
<html >
3+
<head>
4+
5+
<link rel=stylesheet type="text/css" href="http://synrc.com/synrc.css">
6+
<meta name="Author" content="5HT">
7+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
8+
<meta property="og:image" content="images/s_64.png"/>
9+
<meta http-equiv="X-UA-Compatible" content="IE=IE10,chrome=1" />
10+
<title>N2O
11+
</title>
12+
</head>
13+
<body >
14+
<!--HEVEA command line is: hevea index.tex -o index.htm -->
15+
<!--CUT STYLE article--><!--HTMLHEAD-->
16+
17+
<div class="nonselectedwrapper white" style="padding: 10px 0px 10px 0px;margin: 0px 0px 10px 0px;">
18+
<a href="//synrc.com/">
19+
<img style="float:left; margin-left: 55px; margin-top: 5px; margin-bottom:-5px;" src="http://synrc.com/images/synrc.png" border="0"></a>
20+
21+
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top" style="display:none;margin-top:39px;">
22+
<input type="hidden" name="cmd" value="_s-xclick">
23+
<input type="hidden" name="hosted_button_id" value="P8WQHAQK5HWWW">
24+
<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif" border="0" name="submit" style="width:74px;margin-top:0px;">
25+
</form>
26+
27+
<div align=right style="float:right;width:700px;height: auto; margin: 20px 50px 0px 0px;">
28+
<script type="text/javascript">
29+
30+
var args = (window.location).toString().split('/');
31+
var page_name = args[args.length-1];
32+
var menu = {'http://synrc.com/index.htm': 'Home',
33+
'http://synrc.com/research.htm': 'Showcase',
34+
'http://synrc.com/apps/': 'Apps',
35+
'http://synrc.com/feedback.htm': 'Contacts',
36+
'http://spawnproc.com': '<b>Spawnproc</b>', };
37+
38+
Object.keys(menu).forEach(function (key) {
39+
if (page_name == key) { document.write('<div class="menu" style="font-weight: bold;">'+menu[key]+'</div>'); }
40+
else { document.write('<a class="menu" href="'+key+'">'+menu[key]+'</a>'); }
41+
});
42+
43+
</script>
44+
</div>
45+
</div>
46+
47+
<hr size="1">
48+
49+
<!--ENDHTML-->
50+
<!--CUT DEF section 1 --><div class="nonselectedwrapper">
51+
<div class="article">
52+
<div class="toc">
53+
<!--TOC section id="sec1" TOC-->
54+
<h2 id="sec1" class="section">TOC</h2><!--SEC END -->
55+
<!--TOC paragraph id="sec2" -->
56+
<!--SEC END --><p>
57+
<a href="http://synrc.com/apps/n2o/doc/web">1. Framework</a> <br>
58+
59+
<a href="http://synrc.com/apps/n2o/doc/web/setup.htm">2. Setup</a> <br>
60+
61+
<a href="http://synrc.com/apps/n2o/doc/web/processes.htm">3. Processes</a> <br>
62+
63+
<a href="http://synrc.com/apps/n2o/doc/web/endpoints.htm">4. Endpoints</a> <br>
64+
65+
<a href="http://synrc.com/apps/n2o/doc/web/handlers.htm">5. Handlers</a> <br>
66+
67+
<a href="http://synrc.com/apps/n2o/doc/web/protocols.htm">6. Protocols</a> <br>
68+
69+
<a href="http://synrc.com/apps/n2o/doc/web/api.htm">7. API</a> <br>
70+
71+
<a href="http://synrc.com/apps/n2o/doc/web/elements.htm">8. Elements</a> <br>
72+
73+
<a href="http://synrc.com/apps/n2o/doc/web/actions.htm">9. Actions</a> <br>
74+
75+
<a href="http://synrc.com/apps/n2o/doc/web/macros.htm">10. JavaScript</a> <br>
76+
77+
<a href="http://synrc.com/apps/n2o/doc/web/utf8.htm">11. UTF-8</a> <br>
78+
79+
<a href="http://synrc.com/apps/n2o/doc/web/packages.htm">12. Packages</a> <br>
80+
81+
<a href="http://synrc.com/apps/n2o/doc/web/persistence.htm">13. Persistence</a> <br>
82+
83+
<a href="http://synrc.com/apps/n2o/doc/web/last.htm">14. History</a> <br>
84+
85+
<a href="http://synrc.com/apps/n2o/doc/book.pdf">Download PDF</a> <br>
86+
87+
</p></div>
88+
89+
<div class="articlecol">
90+
91+
<!--TOC section id="sec3" N2O: Application Server-->
92+
<h2 id="sec3" class="section">N2O: Application Server</h2><!--SEC END --><p>N2O was started as the first Erlang Web Framework
93+
that uses WebSocket protocol only. We saved great compatibility with Nitrogen
94+
and added many improvements, such as binary page construction,
95+
binary data transfer, minimized process spawns, transmission of all events over the WebSocket
96+
and work within Cowboy processes. N2O renders pages several times faster than Nitrogen.</p>
97+
<!--TOC subsection id="sec4" Wide Coverage-->
98+
<h3 id="sec4" class="subsection">Wide Coverage</h3><!--SEC END --><p>
99+
N2O is unusual in that it solves problems in different web development domains
100+
and stays small and concise at the same time. Started as a Nitrogen concept
101+
of server-side framework it can also build offline client-side applications
102+
using the same source code. This became possible with powerful Erlang JavaScript Parse
103+
Transform which enables running Erlang on JavaScript platform and brings in Erlang and JavaScript
104+
interoperability. You can use Elixir, LFE and Joxa languages for backend development as well.</p>
105+
<!--TOC paragraph id="sec5" -->
106+
<!--SEC END --><p>
107+
N2O supports DSL and HTML templates. It lets you build JavaScript
108+
control elements in Erlang and perform inline rendering with DSL using
109+
the same code base for both client and server-side.
110+
How to use N2O is up to you. You can build mobile applications using server-side rendering
111+
for both HTML and JavaScript thus reducing CPU cycles and saving the battery of a mobile device.
112+
Or you can create rich offline desktop applications using Erlang JavaScript compiler.</p><!--TOC subsection id="sec6" Why Erlang in Web?-->
113+
<h3 id="sec6" class="subsection">Why Erlang in Web?</h3><!--SEC END --><p>
114+
We have benchmarked all the existing modern web frameworks that were built using functional
115+
languages and Cowboy was still the winner. The chart below shows raw HTTP
116+
performance of functional and C-based languages with concurrent
117+
primitives (Go, D and Rust) on a VAIO Z notebook with i7640M processor.</p><p>
118+
119+
<img src="http://synrc.com/apps/n2o/doc/images/n2o_benchmark.png" style="margin-left: -20px;margin-botton: 30px; padding:20 20 20 20px;"><br>
120+
121+
Picture. <span style="font-weight:bold">Web-Servers raw performance grand congregation</span><br>
122+
<br>
123+
124+
125+
126+
Erlang was built for low latency streaming of binary data in telecom systems.
127+
It’s fundamental design goal included high manageability, scalability
128+
and extreme concurrency. Thinking of WebSocket channels as binary
129+
telecom streams and web pages as user binary sessions
130+
helps to get an understanding reasons behind choosing Erlang
131+
over other alternatives for web development.</p>
132+
<!--TOC paragraph id="sec7" -->
133+
<!--SEC END --><p>
134+
Using Erlang for web allows you to unleash the full power of telecom systems for
135+
building web-scale, event-driven, message-passing, NoSQL, asynchronous, non-blocking,
136+
reliable, highly-available, performant, secure, real-time, distributed applications.
137+
See Erlang: The Movie II.</p>
138+
<!--TOC paragraph id="sec8" -->
139+
<!--SEC END --><p>
140+
N2O outperforms full Nitrogen stack with only 2X raw HTTP Cowboy
141+
performance downgrade thus upgrading rendering performance several
142+
times compared to any other functional web framework. And
143+
sure it’s faster than raw HTTP performance of Node.js.</p>
144+
<!--TOC subsection id="sec9" Rich and Lightweight Applications-->
145+
<h3 id="sec9" class="subsection">Rich and Lightweight Applications</h3><!--SEC END --><p>
146+
There are two approaches for designing client/server communication.
147+
The first one is called ’data-on-wire’. With this approach only JSON, XML or binary
148+
data are transferred over RPC and REST channels. All HTML rendering
149+
is performed on the client-side. This is the most suitable approach for building desktop
150+
applications. Examples include React, Meteor and ClojureScript.
151+
This approach can also be used for building mobile clients.</p>
152+
<!--TOC paragraph id="sec10" -->
153+
<!--SEC END --><p>
154+
Another approach is sending pre-rendered parts of pages and JS
155+
and then replacing HTML and executing JavaScript on the client-side. This approach
156+
is better suited for mobile web development since the
157+
client doesn’t have much resources.</p>
158+
<!--TOC paragraph id="sec11" -->
159+
<!--SEC END --><p>
160+
With N2O you can create both types of applications. You can use N2O REST framework
161+
for desktop applications based on Cowboy REST API along with DTL
162+
templates for initial HTML rendering for mobile applications.
163+
You can also use Nitrogen DSL-based approach for modeling parts of pages
164+
as widgets and control elements, thanks to Nitrogen
165+
rich collection of elements provided by Nitrogen community.</p>
166+
<!--TOC paragraph id="sec12" -->
167+
<!--SEC END --><p>
168+
In cases when your system is built around Erlang infrastructure, N2O
169+
is the best choice for fast web prototyping, bringing simplicity
170+
of use and clean codebase. Despite HTML being transfered over the wire,
171+
you still have access to all your Erlang services directly.</p>
172+
<!--TOC paragraph id="sec13" -->
173+
<!--SEC END --><p>
174+
You can also create offline applications using Erlang JavaScript compiler
175+
just the way you would use ClojureScript, Scala.js, Elm, WebSharper
176+
or any other similar tool. N2O includes: REST micro frameworks,
177+
server-side and client-side rendering engines,
178+
WebSocket events streaming, JavaScript generation
179+
and JavaScript macro system along with <span style="font-weight:bold">AVZ</span> authorization
180+
library (Facebook, Google, Twitter, Github, Microsoft), key-value storages
181+
access library <span style="font-weight:bold">KVS</span> and <span style="font-weight:bold">MQS</span> Message Bus client library (gproc, emqttd).</p>
182+
<!--TOC subsection id="sec14" JSON and BERT-->
183+
<h3 id="sec14" class="subsection">JSON and BERT</h3><!--SEC END --><p>
184+
N2O uses JSON and BERT. All messages passed over
185+
WebSockets are encoded in native Erlang External Term Format.
186+
It is easy to parse it in JavaScript with <span style="font-weight:bold">dec(msg)</span>
187+
and it helps to avoid complexity on the server-side. Please refer
188+
to <a href="http://bert-rpc.org">http://bert-rpc.org</a> for detailed information.</p>
189+
<!--TOC subsection id="sec15" DSL and Templates-->
190+
<h3 id="sec15" class="subsection">DSL and Templates</h3><!--SEC END --><p>
191+
We like Nitrogen for the simple and elegant way it constructs typed
192+
HTML with internal DSL. This is analogous to Scala Lift,
193+
OCaml Ocsigen and Haskell Blaze approach. It lets you develop reusable control
194+
elements and components in the host language.</p>
195+
<!--TOC paragraph id="sec16" -->
196+
<!--SEC END --><p>
197+
Template-based approach (Yesod, ASP, PHP, JSP, Rails, Yaws and ChicagoBoss)
198+
requires developers to deal with raw HTML. It allows
199+
defining pages in terms of top-level controls, placeholders
200+
and panels. N2O also support this approach by proving bindings
201+
to DTL and ET template engines.</p>
202+
<!--TOC paragraph id="sec17" -->
203+
<!--SEC END --><p>
204+
The main N2O advantage is its suitability for large-scale projects
205+
without sacrificing simplicity and comfort of prototyping solutions
206+
in fast and dynamic manner. Below is an example of complete Web Chat
207+
implementation using WebSockets that shows how Templates, DSL and
208+
asynchronous inter-process communication work in N2O.</p><div class="center">Listing 1: chat.erl</div><p><br>
209+
</p><div class="lstlisting"> -module(chat).
210+
-include_lib("nitro/include/nitro.hrl").
211+
-compile(export_all).
212+
213+
main() -&gt;
214+
#dtl { file = "login",
215+
app = review,
216+
bindings = [ { body, body() } ] }.
217+
218+
body() -&gt;
219+
[ #span { id=title, body="Your nickname: " },
220+
#textbox { id=user, body="Anonymous" },
221+
#panel { id=history },
222+
#textbox { id=message },
223+
#button { id=send, source=[user,message],
224+
body="Send",
225+
postback=chat } ].
226+
227+
event(init) -&gt; wf:reg(room), wf:async("looper",fun loop/1);
228+
event(chat) -&gt; User = wf:q(user),
229+
Message = wf:q(message),
230+
n2o_async:send("looper",{chat,User,Message}).
231+
232+
loop({chat,User,Message}) -&gt;
233+
Terms = #panel { body = [
234+
#span { body = User }, ": ",
235+
#span { body = Message } ]},
236+
wf:insert_bottom(history, Terms),
237+
wf:flush(room).</div><p>Just try to build the similar functionality with your favorite
238+
language/framework and feel the difference! Here are one message bus,
239+
one async <span style="font-weight:bold">gen_server</span> worker under supervision, NITRO DSL, DTL template,
240+
WebSockets, HTML and JavaScript generation in a simple file that you can
241+
put in your N2O application directory tree without restart and
242+
manual compilation. Also you can create single-file bundle
243+
which is able to run in Windows, Linux and Mac. Moreover this
244+
application is ready to run under multiplatform LING Erlang virtual machine.</p><!--TOC subsection id="sec18" Changes from Nitrogen-->
245+
<h3 id="sec18" class="subsection">Changes from Nitrogen</h3><!--SEC END --><p>
246+
We took a liberty to break some compatibility with the original
247+
Nitrogen framework, mostly because we wanted to have a clean codebase
248+
and achieve better performance. However, it’s still possible to port
249+
Nitrogen web sites to N2O quite easily. E.g., N2O returns id and
250+
class semantics of HTML and not <span style="font-weight:bold">html_id</span>.
251+
We simplified HTML rendering without using
252+
<span style="font-weight:bold">html_encode</span> which should be handled by application layer.</p>
253+
<!--TOC paragraph id="sec19" -->
254+
<!--SEC END --><p>
255+
Nitrogen.js, originally created by Rusty Klophaus, was removed
256+
because of the pure WebSocket nature of N2O which doesn’t
257+
require jQuery on the client-side anymore. In terms of lines of code
258+
we have impressive showing. New <span style="font-weight:bold">xhr.js</span> 25 LOC and <span style="font-weight:bold">bullet.js</span> 18 LOC
259+
was added as the replacement, also <span style="font-weight:bold">nitrogen.js</span> takes only 45 LOC.
260+
UTF-8 <span style="font-weight:bold">utf8.js</span> 38 LOC could be plugged separately only when you’re
261+
using <span style="font-weight:bold">bert.js</span> 200 LOC formatter. <span style="font-weight:bold">n2o.js</span> protocol handler is about 20 LOC.</p>
262+
<!--TOC paragraph id="sec20" -->
263+
<!--SEC END --><p>
264+
We also removed <span style="font-weight:bold">simple_bridge</span> and optimized N2O on each level to
265+
unlock maximum performance and simplicity. We hope you will enjoy
266+
using N2O. We are fully convinced it is the most efficient way to
267+
build Web applications in Erlang.</p>
268+
<!--TOC paragraph id="sec21" -->
269+
<!--SEC END --><p>
270+
Original Nitrogen was already tested in production under high load and we
271+
decided to remove <span style="font-weight:bold">nprocreg</span> process registry along
272+
with <span style="font-weight:bold">action_comet</span> heavy process creation. N2O creates a single
273+
process for an async WebSocket handler, all operations
274+
are handled within Cowboy processes.</p>
275+
<!--TOC paragraph id="sec22" -->
276+
<!--SEC END --><p>
277+
Also, we introduced new levels of abstraction. You can extend
278+
the set of available protocols (Nitrogen, Heartbeat, Binary),
279+
change protocol formatters to BERT, JSON or MessagePack, inject
280+
your code on almost any level. The code structure
281+
is clean and Nitrogen compatibility layer NITRO is fully detachable
282+
from N2O and lives in a separate <span style="font-weight:bold">synrc/nitro</span> application.
283+
284+
<br><br>
285+
<h2><a name="testimonials"><b>N2O in Production</b></a></h2><blockquote>In this framework, most of all I liked the fact that most of the
286+
tasks solving in one code, in one language. And is not spread to the
287+
front-end & back-end.<div align=right>Alex Radetsky,
288+
<a href="http://pearlpbx.com/">PearlPBX</a></div></blockquote>
289+
290+
<blockquote>Writing asynchronous web-applications has never been so easy for me.
291+
Now I really like to push data to client!<div align=right>Max Treskin,
292+
<a href="http://metachord.com/">Metachord</a></div></blockquote>
293+
294+
<blockquote>N2O is the easiest way how to write different webapps. It just works.
295+
<div align=right>Alexander Karpich,
296+
<a href="http://rontel.ru/">RON-Telecom CJSC</a></div></blockquote>
297+
298+
<blockquote>N2O is nice way to deal with WebSockets.
299+
<div align=right>Roman Gladkov
300+
<a href="http://crashkeeper.com/">Crashkeeper, Inc.</a></div></blockquote>
301+
302+
<h2><a name="trendsetters"><b>Erlang Trendsetters on N2O</b></a></h2>
303+
304+
<!--blockquote>This [N2O] makes Websockets so easy. Thanks for this, it's great.
305+
<div align=right>Joe Armstrong,
306+
<a href="http://ericsson.com/">Ericsson AG</a></div></blockquote-->
307+
308+
<blockquote>Excited to see these guys pushing boundaries; that's exactly what
309+
inspired Nitrogen in the first place. My hat is off to the <a href="http://synrc.com">synrc.com</a>
310+
team for their work on N2O...
311+
<div align=right style="margin-top: 10px;">Rusty Klophaus, Nitrogen author,
312+
<a href="http://basho.com/">Basho Technologies, Inc.</a></div></blockquote>
313+
314+
<blockquote>N2O is one of the most interesting Cowboy based frameworks.
315+
<div align=right style="margin-top: 10px;">Loïc Hoguin, Cowboy,
316+
<a href="http://ninenines.eu/">Nine Nines</a></div></blockquote>
317+
318+
<br><center>
319+
<iframe src="http://slid.es/maximsokhatsky/n2o/embed" width="600" height="400" scrolling="no" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
320+
</center><br>
321+
322+
323+
<!--div id="disqus_thread"></div>
324+
<script type="text/javascript">
325+
var disqus_shortname = 'synrc'; // required: replace example with your forum shortname
326+
(function() {
327+
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
328+
dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
329+
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
330+
})();
331+
</script>
332+
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
333+
<a href="https://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a-->
334+
335+
336+
</p></div>
337+
</div>
338+
</div><div class="clear"> </div><!--CUT END -->
339+
<!--HTMLFOOT-->
340+
341+
<div class="nonselectedwrapper">
342+
<div class="verywidecol">
343+
344+
<div style="width:100%;height:300px;float:left;font-size:16pt;" align=center>
345+
<hr size=1>
346+
<br><br><br>
347+
<a href="//synrc.com/news/index.htm">Events</a> |
348+
<a href="//synrc.com/privacy.htm">Privacy Policy</a> |
349+
<a href="//synrc.com/feedback.htm">Feedback</a> |
350+
<a href="//synrc.com/brandbook.htm">Brandbook</a><br>
351+
Copyright &copy; 2005&ndash;2016 <a href="//synrc.com/index.htm"> Synrc Research Center s.r.o.</a>
352+
</div>
353+
354+
</div>
355+
</div>
356+
357+
358+
<div class="clear"></div>
359+
360+
<script type="text/javascript">
361+
362+
var _gaq = _gaq || [];
363+
_gaq.push(['_setAccount', 'UA-29227518-1']);
364+
_gaq.push(['_trackPageview']);
365+
366+
(function() {
367+
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
368+
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'https://www') + '.google-analytics.com/ga.js';
369+
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
370+
})();
371+
372+
</script>
373+
374+
<script type="text/javascript" src="http://synrc.com/hi.js"></script>
375+
<!--ENDHTML-->
376+
</body>
377+
</html>

0 commit comments

Comments
 (0)