Greetings, dear reader. Even before this, I didn’t even know about the existence of Node.js, but I managed to weightily with JavaScript, after which I don’t want to write on anything else. Many who have understood JS and its Zen, that everything is an object, in closures, anonymous functions, prefer to work only with it. Once, with a friend, we exchanged thoughts about PHP, criticized the meager and inconvenient features of the OOP, and I said: “I’d like to write JS instead of PHP on the server side, and I received an instant answer:“ nodejs is in your hands. ” Without hesitation, I started digging through wiki and other resources, then in the shortest possible time I raised Ubuntu Server to the Virtual Box and put Node.js there myself.
I’m just warning you that if you haven’t worked with JavaScript or are just too familiar with it, start with it, otherwise Node.js may seem like a dark forest to you. I want to introduce you to the language immediately in practice, and also show the idea of practical application again. I will give an example of the implementation of a small template parser, all of this will fit into 2 small files, deliberately no frills, in order to visually and transparently see "how it works."
So, the concept is as follows: we will use inserts in the following template:
<script type = " nodejs " > 100 + 235 ; </script >
FractalizeR's HabraSyntax Source Code Highlighter .
This code will display 335 on the screen. Why such a method, and not for example:
<% = 100 + 235%> ? This is the idea, firstly, these tags will contain the usual JS-code, and this design will support syntax highlighting in editors without any rituals of sacrifices with a tambourine. Why choose JS code? “It's barbaric!” Well, I personally like the 1C-Bitrix template model, I think it’s very convenient, just make the conditions and cycles in the language you know, and not learn the new syntax template every time and get into its tight framework. Plus, it's JS! Catch a thought? Typically, designers as impose, and write to JS, and then inserts, with the same JS, that is, they continue to typeset, just knowing that their code is replaced on the server side with what they return in it at the end of the manipulation. For me, so the best solution.
Now, finally, let's move on to our favorite practice, step by step, write the code describing the actions. First, create two files: start.js for our script and template.html for the template. Further code is written in start.js. Let's connect the built-in Node.js modules, which are necessary for the example to work:
var http = require ( ' http ' ) ; //
var fs = require ( ' fs ' ) ; // ,
var vm = require ( ' vm ' ) ; // JS- ,
FractalizeR's HabraSyntax Source Code Highlighter .
')
Please note that Node.js does not require any Apache and other things, if you compare it with PHP, this is a different element. The server rises right in the script and is created when the script is executed from the console. Let's declare a variable to create a server and also immediately declare, for example, a JSON data structure for exporting to a template:
var host = {
addr : ' 127.0.0.1 ' ,
port : 8070
} ;
var jsonExport = {
title : ' ' ,
list : [
{ name : ' ' , msg : ' ' } ,
{ name : ' ' , msg : ' ' } ,
{ name : ' ' , msg : ' ! ' }
]
} ;
FractalizeR's HabraSyntax Source Code Highlighter .
Pay attention to port 8070, just in case if the 80th is busy with Apache, or something else. If you are sure that the port is free, you can deliver the 80th. 127.0.0.1 is a local machine, and the server will be accessible only within it, this is enough for us so far.
Next, create the server itself with a request handler from the browser:
var server = http . createServer ( function ( request , response ) {
//
} ) ;
FractalizeR's HabraSyntax Source Code Highlighter .
For now, let's go through the handler code and immediately start the wiretapping of port 8070 on the local machine and send a report to the console:
server . listen ( host . port , host . addr ) ;
console . log ( ' : ' + host . addr + ' : ' + host . port ) ;
FractalizeR's HabraSyntax Source Code Highlighter .
Now it's time to describe the handler code:
response . writeHead ( 200 , { ' content-type ' : ' text/html; charset=utf-8 ' } ) ;
fs . readFile ( ' ./template.html ' , function ( err , data ) {
//
} ) ;
FractalizeR's HabraSyntax Source Code Highlighter .
The first line is the return in the headers of the 200th server response, ala OK, everything is fine. The second parameter is the object that passes the remaining headers, in this case, the content type and encoding. The next line is to read the template file and the handler.
And as you might have guessed, the template processing code, the final part of the start.js script:
var data = data . toString ( ) ;
var dataArr = data . match ( / \<script type=(nodejs|'nodejs'|"nodejs")\>([^\0]+?)< \/ script\> /gi m ) ;
for ( var i = 0 ; i < ( dataArr . length | | 0 ) ; i + + ) {
var code = dataArr [ i ] . replace ( / ^\<script([^\>]+)\>([^\0]+?)< \/ script\>$ /i m , ' $2 ' ) ;
data = data . replace ( / \<script type=(nodejs|'nodejs'|"nodejs")\>([^\0]+?)< \/ script\> /i m ,
vm . runInNewContext ( code , jsonExport ) ) ;
}
response . end ( data ) ;
FractalizeR's HabraSyntax Source Code Highlighter .
1st line - convert the resulting file content to a string to work with regs. I will not write any details about regs, just note the reg keys for understanding what is happening.
2nd line - create an array of the found pieces of the parser code that needs to be processed and replaced with the result of the execution. The keys gim, g are more than one match, i is case-insensitive, m is a multi-line search (instead of searching in separate strings). Regarding reg, I want to mention only one of my methods, which I often use, it may be useful to you. The dot character captures all characters except line breaks, in this case we also need line breaks! And instead of a point we write:
[^ \ 0] , which means everything that does not equal null (emptiness). Interesting, yes? It is possible and just
[^] , but if you use it in JavaScript, of course, Internet Explorer will give an error, because we use the first, longer version.
The 3rd line is a cycle, we go through the array of found calls to the parser code.
The first line of the cycle - we pull out the code between the <script *> ... </ script> of the current parser code and add it to the code variable.
2nd and 3rd line of the cycle - in the data variable we replace the current call to the parser with the result of the execution using the vm module, which executes the specified code in a specific context. In this case, he passed our JSON structure as this context. Notice that reg without the g key to work only with the current insert, since we replace all of the code in its entirety.
Our start.js file is ready, here’s the whole view:
var http = require ( ' http ' ) ;
var fs = require ( ' fs ' ) ;
var vm = require ( ' vm ' ) ;
var host = {
addr : ' 127.0.0.1 ' ,
port : 8070
} ;
var jsonExport = {
title : ' ' ,
list : [
{ name : ' ' , msg : ' ' } ,
{ name : ' ' , msg : ' ' } ,
{ name : ' ' , msg : ' ! ' }
]
} ;
var server = http . createServer ( function ( request , response ) {
response . writeHead ( 200 , { ' content-type ' : ' text/html; charset=utf-8 ' } ) ;
fs . readFile ( ' ./template.html ' , function ( err , data ) {
var data = data . toString ( ) ;
var dataArr = data . match ( / \<script type=(nodejs|'nodejs'|"nodejs")\>([^\0]+?)< \/ script\> /gi m ) ;
for ( var i = 0 ; i < ( dataArr . length | | 0 ) ; i + + ) {
var code = dataArr [ i ] . replace ( / ^\<script([^\>]+)\>([^\0]+?)< \/ script\>$ /i m , ' $2 ' ) ;
data = data . replace ( / \<script type=(nodejs|'nodejs'|"nodejs")\>([^\0]+?)< \/ script\> /i m ,
vm . runInNewContext ( code , jsonExport ) ) ;
}
response . end ( data ) ;
} ) ;
} ) ;
server . listen ( host . port , host . addr ) ;
console . log ( ' : ' + host . addr + ' : ' + host . port ) ;
FractalizeR's HabraSyntax Source Code Highlighter .
And then, without thinking twice, we write the following code in the template.html file (I think no explanation is required for the layout):
<html >
<head >
<meta http-equiv = " content-type " content = " text/html; charset=utf-8 " >
<title > <script type = " nodejs " > title ; </script > </title >
</head >
<body >
<h1 > <script type = " nodejs " > title ; </script > </h1 >
<script type = " nodejs " >
var out = ' ' ;
out + = ' <ul>\n ' ;
for ( var i = 0 ; i < list . length ; i + + ) {
out + = ' \t\t<li><b> ' + list [ i ] . name + ' </b> ' + list [ i ] . msg + ' </li>\n ' ;
}
out + = ' \t</ul> ' ;
out ;
</script >
</body >
</html >
FractalizeR's HabraSyntax Source Code Highlighter .
I think it will be easy for you to analyze this code yourself. The inserts simply display the key values from our JSON context structure. A list is displayed at the bottom, at first everything is added to a local variable, and then it returns at the end for output.
So, now a little magic, type in the console:
node start . js
FractalizeR's HabraSyntax Source Code Highlighter .
Go to
http://127.0.0.1:8070 and admire! Good luck with experiments!
PS Do not forget that this is only an example, there is not even an error handler and other things, the example is very minimalist.