SlideShare a Scribd company logo
Введение в технологию
От JavaScript никуда не деться 
«Всё, что может быть написано на JavaScript, 
должно быть написано на нём» 
«Any application that can be written in JavaScript, 
will eventually be written in JavaScript» 
Jeff Atwood 
основатель Stack Overflow
Основные идеи Node.js 
1. Один язык, один формат данных, 
одна парадигма, одна архитектура 
СУБД 
Мобильные 
приложения 
Сервер 
Браузер 
Оконные 
приложения 
JSON 
BSON 
JavaScript 
JavaScript 
JavaScript
Основные идеи Node.js 
2. Долгая жизнь приложений в 
оперативной памяти на стороне сервера 
• Состояние памяти сохраняется между запросами 
• Структуры данных (объекты, модель) 
• Соединения с БД и открытые файлы 
• Конфигурация и инициализация 
• Веб сервер внутри приложения, а не наоборот 
• Меньше IPC
Основные идеи Node.js 
3. Без ввода/вывода еще быстрее, 
чем с асинхронным вводом/выводом 
• Упреждающее чтение 
• Отложенная запись 
• Отдача всего из памяти
Преимущества JavaScript: 
1. Имеет очень низкий порог входа; 
2. Высочайшая гибкость; 
3. Высокая скорость разработки; 
4. Практически идеальный уровень 
абстракции; 
…
Недостатки JavaScript: 
1. Имеет очень низкий порог входа; 
2. Высочайшая гибкость; 
3. Высокая скорость разработки; 
4. Практически идеальный уровень 
абстракции; 
…
Особенности JavaScript 
Наличие огромного количества особенностей. 
Как в синтаксических конструкциях, так и в 
логике программ. 
“12” + 5 === “125” 
Но… 
“12” - 5 === 7 
[] + [] === “” 
[] + {} === “[object Object]” 
{} + [] === 0 
isNaN({} + {}) === true
Введение в NodeJS
Что такое NodeJS 
• Open Source JavaScript-движок V8 от Google; 
• Обёртка и библиотеки на JavaScript; 
• libuv; 
• Оболочка, написанная на C++.
Google V8 
• Разработка Google, исходный код которой был 
открыт в 2008 году; 
• Самый оптимальный JavaScript-движок на 
сегодняшний день; 
• Основа браузеров Google Chrome и Chromium.
Преимущества V8 
• Базовый и оптимизирующий компилятор; 
• Компиляция JavaScript-кода непосредственно в 
машинный код, без промежуточного байт-кода; 
• Эффективная система управления памятью; 
• Введение скрытых классов и встроенных кэшей, 
ускоряющих доступ к свойствам и вызовы 
функций.
Начало работы с NodeJS 
1. Установка дистрибутива с nodejs.org; 
2. Создание *.js файлов; 
3. Запуск программ: $ node *.js;
Элементарный пример 
hello.js: 
console.log(“Hello, world!”); 
$ node hello 
Hello, world!
API, менеджер пакетов и package.json 
$ npm init 
… 
$ npm install colors --save 
/ 
/node_modules 
/colors 
... 
main.js 
package.json 
net 
https 
buffer 
crypto 
path 
…
package.json 
{ 
"name": "Test", 
"version": "1.0.0", 
"description": "", 
"main": "index.js", 
"scripts": { 
"test": "echo "Error: no test specified" && exit 1“ 
}, 
"author": "", 
"license": "ISC" 
}
Система контроля версий 
• Git; 
• GitHub; 
• Структура проектов; 
• Репозитории npm; 
• Командная работа.
Специфика NodeJS
Однопоточность и многопоточность 
• Что дает однопоточность? 
• Действительно ли 1 процесс = 1 поток? 
• Как нагрузить все ядра? 
• cluster = require('cluster') 
• npm install webworker-threads 
• самостоятельно делаем IPC
Межпроцессовое взаимодействие 
• Родное IPC, cluster 
• Разделяемая память: Memcache? 
• Шина сообщений (MQ): ZeroMQ, RabbitMQ... 
• TCP, UDP, HTTP
Асинхронный ввод/вывод 
• Реактор 
• Очередь 
• СМО 
fs.readFile( 
‘a.txt’, 
onRead 
); 
http.get( 
‘http://...’, 
onGet 
); 
console.log(‘done?’);
Производительность 
• Производительность кода 
• Производительность сервера 
Факторы производительности Node.js 
• Асинхронность 
• Состояние в памяти 
• Минимизация IPC
Память 
• GC (RAM 32bit: 512Mb, 64bit:1.7Gb ) 
• node --max-old-space-size=3000 
• delete obj.field; delete arr[5]; delete name; 
• node --nouse-idle-notification 
--expose-gc application.js 
• Вызываем gc();
Профилирование 
• npm install -g node-inspector 
node --debug application.js 
• npm install heapdump 
var hd = require('heapdump'); 
hd.writeSnapshot( 
'dump'+Date.now()+'.heapsnapshot' 
);
Отладка 
• Через node-inspector 
• Выводом в консоль console.log(); или в лог 
• Если ошибку не видно 
• node --stack-trace-limit=1000 application.js 
• Может понадобиться фильтр
Ошибки 
• Общепринято в Node: function(err, arguments...) 
• Создаем new Error('Eror message') 
• Секция try {...} catch(e) {...} finally {...} 
• Событие .on('error', fn) если EventEmitter 
• Домены domain.create(); .run(fn); .on('error', fn); 
• Перехват 
process.on('uncaughtException', function(err) { 
console.log('uncaught Exception: '+err.stack); 
});
Обновление кода и перезапуск 
• Наблюдение за процессом forever 
npm install forever -g 
forever start --spinSleepTime 10000 application.js 
• Наблюдение за файлами 
http://livereload.com/ 
http://habrahabr.ru/post/168091/
Callback’и и вложенность 
Пример запроса: 
request('http://www.google.com/api', 
function (error, response, body) { 
var googleData = JSON.parse(body); 
... 
} 
);
Callback’и и вложенность 
request('http://www.google.com/api', 
function (gError, gResponse, gBody) { 
request('http://www.yandex.com/api', 
function (yError, yResponse, yBody) { 
request('http://www.twitter.com/api', 
function (tError, tResponse, tBody) 
{ 
... 
} 
...
Callback’и: Библиотека async 
async.parallel([ 
function(){ ... }, 
function(){ ... } 
], callback); 
Другие методы: series, parallel, whilst, until, 
waterfall, compose, queue, cargo, retry, each, map, 
reduce, detect, every ...
Callback’и: Библиотека async 
async.parallel([ 
function(callback){ request('http://google.com/api', 
function(error, response, body) { callback(error, body); }); 
}, 
function(callback){ request('http://yandex.com/api', 
function(error, response, body) { callback(error, body); }); 
}, 
function(callback){ request('http://twitter.com/api', 
function(error, response, body) { callback(error, body); }); 
}, 
], function(err, results) { 
... 
});
Callback’и: Библиотека async 
async.parallel([ 
function(callback){ googleApiService(callback); }, 
function(callback){ yandexApiService(callback); }, 
function(callback){ twitterApiService(callback); }, 
], function(err, results) { 
... 
});
Callback’и: Promise (Q) 
https://github.com/kriskowal/q 
Promise.then(function(success) { 
... 
}, function(error) { 
... 
});
Callback’и: Promise (Q) 
Q.fcall(googleApiService) 
.then(yandexApiService) 
.then(twitterApiService); 
Q.all([ 
googleApiService(), 
yandexApiService(), 
twitterApiService() 
]) 
.then();
Express 
Простой, нетребовательный и 
минималистический middleware- 
фреймворк для разработки WEB- 
приложений на NodeJS; 
$ npm install express --save
Простое приложение на express 
var express = require(“express”), 
app = express(); 
app.get(“/”, function (request, response) { 
response.send(“Hello, stranger!”); 
}); 
app.listen(80);
Приложение на express 
var express = require(“express”), 
app = express(), 
storage = { “home”: { head: “Sweet home” }, “about”: { head: “” } }; 
app.use(express.static(__dirname + “/public”)); 
app.get(“/:page?”, function (request, response) { 
var page = request.params.page, 
data = storage[page || “home”]; 
if (!data) return response.redirect(“/”); 
response.render(“home”, data); 
}); 
app.listen(80);
Элегантность express 
var express = require('express'); 
var path = require('path'); 
var favicon = require('serve-favicon'); 
var logger = require('morgan'); 
var cookieParser = require('cookie-parser'); 
var bodyParser = require('body-parser'); 
var routes = require('./routes/index'); 
var users = require('./routes/users'); 
var app = express(); 
// view engine setup 
app.set('views', path.join(__dirname, 'views')); 
app.set('view engine', 'jade'); 
// uncomment after placing your favicon in /public 
//app.use(favicon(__dirname + '/public/favicon.ico')); 
app.use(logger('dev')); 
app.use(bodyParser.json()); 
app.use(bodyParser.urlencoded()); 
app.use(cookieParser()); 
app.use(express.static(path.join(__dirname, 'public'))); 
app.use('/', routes); 
app.use('/users', users); 
/// catch 404 and forwarding to error handler 
app.use(function(req, res, next) { 
var err = new Error('Not Found'); 
err.status = 404; 
next(err); 
}); 
/// error handlers 
// development error handler 
// will print stacktrace 
if (app.get('env') === 'development') { 
app.use(function(err, req, res, next) { 
res.status(err.status || 500); 
res.render('error', { 
message: err.message, 
error: err 
}); 
}); 
} 
// production error handler 
// no stacktraces leaked to user 
app.use(function(err, req, res, next) { 
res.status(err.status || 500); 
res.render('error', { 
message: err.message, 
error: {} 
}); 
}); 
app.use('/', routes); 
app.use('/users', users); 
module.exports = app;
Сборка проектов 
• Для чего собирать проекты; 
• Система сборки grunt; 
• Gruntfile; 
• Пакеты npm grunt-contrib-*.
Пример Gruntfile.js 
module.exports = function(grunt) { 
grunt.initConfig({ 
uglify: { 
dist: { 
files: { 
“build/app.js”: [“source/app.js”] 
} 
} 
} 
}); 
grunt.loadNpmTasks(“grunt-contrib-uglify”); 
grunt.registerTask(“default”, [“uglify”]); 
}
Node.js введение в технологию, КПИ  #ITmeetingKPI
Grunt устанавливается как NPM 
(Node Package Manager) модуль. 
> npm install -g grunt 
> grunt 
> grunt serve 
> grunt build
Gruntfile.js 
module.exports = function (grunt) { 
require('load-grunt-tasks')(grunt); 
var yeoman = { 
app: 'app' 
}; 
try { 
yeomanConfig.app = 
require('./bower.json').appPath || yeoman.app; 
} catch () {e} 
grunt.initConfig({ 
yeoman: yeomanConfig,
Grunt register tasks - default 
grunt.registerTask 
('default', [ 
'jshint', 
'test', 
'build' 
]);
Grunt register tasks - test 
grunt.registerTask('test', 
[ 
'clean:server', 
'less:modulesToTmp', 
'copy:viewsModulesToTmp', 
'copy:jsModulesToTmp', 
'concat:modulesToTmp', 
'autoprefixer', 
'connect:test', 
'karma' 
]);
Grunt register tasks - build 
grunt.registerTask('build', [ 
'clean:dist', 
'less:modulesToTmp', 
'copy:viewsModulesToTmp', 
'copy:jsModulesToTmp', 
'useminPrepare', 
'autoprefixer', 
'copy:dist', 
'concat', 
'ngmin', 
'uglify', 
'imagemin', 
'htmlmin', 
'usemin', 
'rev'
Grunt register tasks - server 
grunt.registerTask('server', function (target) { 
if (target === 'dist') { 
return grunt.task.run(['build', 'open', 
'connect:dist:keepalive']); 
} 
grunt.task.run([ 
'clean:server', 
'less:modulesToTmp', 
'copy:viewsModulesToTmp', 
'copy:jsModulesToTmp', 
'concat:modulesToTmp', 
'autoprefixer', 
'configureProxies', 
'connect:livereload', 
'open', 
'watch'
Grunt tasks - clean 
clean: { 
server: '<%= yeoman.temp %>', 
dist: { 
files: [{ 
dot: true, 
src: [ 
'<%= yeoman.temp %>', 
'<%= yeoman.dist %>' 
] 
}] 
} 
}
Grunt tasks - less 
less: { 
modulesToTmp: { 
src: '<%= yeoman.app %>/modules/**/*.less', 
dest: '<%= yeoman.temp %>/css/main.css' 
} 
}
Grunt tasks - copy 
copy: { 
viewsModulesToTmp: { 
files: [{ 
expand: true, 
cwd: '<%= yeoman.app %>/modules/', 
dest: '<%= yeoman.temp %>/views', 
src: ['**/*.html'], 
rename: function(dest, src) { 
return dest + '/' + src.replace(/views//gi, ''); 
} 
}]
Grunt tasks - concat 
concat: { 
modulesToTmp: { 
options: { 
banner: '"use strict";n', 
process: function(src, filepath) { 
return '// Source: ' + filepath + 'n' + 
src.replace(/(^|n)[ t]*('use strict'|"use strict");?s*/g, '$1'); 
} 
}, 
files: { 
'<%= yeoman.temp %>/js/controllers.min.js' : '<%= yeoman.app %>/modules/**/*.Controllers.js', 
'<%= yeoman.temp %>/js/directives.min.js' : '<%= yeoman.app %>/modules/**/*.Directives.js', 
'<%= yeoman.temp %>/js/filters.min.js' : '<%= yeoman.app %>/modules/**/*.Filters.js', 
'<%= yeoman.temp %>/js/services.min.js' : '<%= yeoman.app %>/modules/**/*.Services.js' }}}
Grunt tasks - conect 
var LIVERELOAD_PORT = 35729; 
var lrSnippet = require('connect-livereload')({ port: LIVERELOAD_PORT }); 
var proxySnippet = require('grunt-connect-proxy/lib/utils').proxyRequest; 
var mountFolder = function (connect, dir) { return 
connect.static(require('path').resolve(dir)); }; 
connect: { 
options: { port: 8800, hostname: 'localhost' }, 
proxies: [{ context: '/api', host: '127.0.0.1', port: 7777, https: 
false, changeOrigin: false, xforward: false }], 
livereload: { 
options: { 
middleware: function (connect) { 
return [ 
lrSnippet, 
proxySnippet, 
mountFolder(connect, '.tmp'), 
mountFolder(connect, yeomanConfig.app) 
]; }}}
Grunt tasks - open 
open: { 
server: { 
url: 'http://localhost:<%= connect.options.port %>' 
} 
}
Grunt tasks - watch 
watch: { 
livereload: { 
options: { 
livereload: LIVERELOAD_PORT}, 
files: [ 
'<%= yeoman.temp %>/**/*.html', 
'<%= yeoman.temp %>/css/**/*.css', 
'<%= yeoman.temp %>/js/**/*.js', 
'<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}']}, 
js: { 
files: ['<%= yeoman.app %>/modules/**/*.js'], 
tasks: ['copy:jsModulesToTmp', 'concat:modulesToTmp'] 
}, 
css: { 
files: ['<%= yeoman.app %>/modules/**/*.less'], 
tasks: ['less:modulesToTmp']}
Node.js введение в технологию, КПИ  #ITmeetingKPI
Node.js введение в технологию, КПИ  #ITmeetingKPI
Node.js введение в технологию, КПИ  #ITmeetingKPI
Примеры внедрения 
и Highload-проекты
Интерактивное телевидение 7Sense 
• 10млн. открытых соединений на 15 серверах 
• 30тыс. request/second на одном сервере 
• Impress Application Server 
• Server-Sent Events 
• IPC, ZeroMQ
Масштабирование Impress App Server 
Load Balancer 
С1 С3 
C1N1 C1N2 C1N3 C2N1 C2N2 C2N3 C3N1 C3N2 
С0 
Impress Cloud Controller 
Impress 
Application 
Server 
IPC 
HTTP 
ØMQ 
pub/sub + req/rep 
С2 
C3N3
Жизненный цикл проекта 
• Юниттесты и интеграционные тесты 
• Continuous Integration (CI) 
• Travis-CI 
• drone.io 
• Развертывание среды 
• vagrant 
• docker
Сферы применения node.js 
Часто применяется для: 
• cервера веб-приложений и SPA 
• сервера мобильных приложений 
• системы сборки для фронт-энда 
• чаты, меседжинг 
• игровые сервера 
• как заплатка к ПО на других технологиях 
• парсеры, кравлеры
Сферы применения node.js 
Реже применяется для: 
• оконные приложения: node-webkit 
• приложения баз данных и корпоративные 
• промышленная автоматизация и программирование 
микроконтроллеров (arduino, espruino, tessel) 
• обработка и трансляция видео и звука
Сферы применения node.js 
Редко применяется (но подходит) для: 
• CMS, публикация контента 
• электронная коммерция и торговля 
И плохо подходит: 
• вычисления и моделирование 
• научные приложения
Тестирование. TDD.
karma: { 
unit: { 
configFile: 'karma.conf.js', 
singleRun: true 
} 
},
describe('Service: Auth', function () { 
// load the service's module 
beforeEach(module('devApp')); 
// instantiate service 
var Auth; 
beforeEach(inject(function (_Auth_) { 
Auth = _Auth_; 
})); 
it('should do something', function () { 
expect(!!Auth).toBe(true); 
}); 
});
var should = require('should'); 
var request = require('supertest'); 
describe('GET /api/things', function() { 
it('should respond with JSON array', 
function(done) { 
request(app) 
.get('/api/things') 
.expect(200) 
.expect('Content-Type', /json/) 
.end(function(err, res) { 
if (err) return done(err); 
res.body.should.be.instanceof(Array); 
done(); 
});
Node.js введение в технологию, КПИ  #ITmeetingKPI
Полезные материалы 
• npm (www.npmjs.org); 
• nodejs.org/api; 
• learn.javascript.ru; 
• learn.javascript.ru/nodejs-screencast; 
• nodeschool.io; 
• habrahabr.ru/hub/nodejs; 
• nodeguide.ru; 
• …

More Related Content

ODP
Архитектура программных систем на Node.js
PPTX
Heterogeneous databases
PPTX
Bloom filters
PDF
Git and Github
DOCX
Big Data Analytics Lab File
PDF
Node.js Меньше сложности, больше надежности Holy.js 2021
PDF
VTU 7TH SEM CSE DATA WAREHOUSING AND DATA MINING SOLVED PAPERS OF DEC2013 JUN...
PPT
Uniformed tree searching
Архитектура программных систем на Node.js
Heterogeneous databases
Bloom filters
Git and Github
Big Data Analytics Lab File
Node.js Меньше сложности, больше надежности Holy.js 2021
VTU 7TH SEM CSE DATA WAREHOUSING AND DATA MINING SOLVED PAPERS OF DEC2013 JUN...
Uniformed tree searching

What's hot (20)

PDF
Tech 2 Tech: Network performance
PDF
Cassandra Introduction & Features
PDF
Concurrency vs parallelism
PPTX
Hadoop Distributed File System
PPTX
Introduction to Storm
PDF
Mapreduce by examples
PDF
Stanford CS347 Guest Lecture: Apache Spark
PPTX
Data mining tools overall
PPTX
Apache PIG
PPTX
Learn nginx in 90mins
PDF
Apache ZooKeeper
PDF
ClickHouse Introduction, by Alexander Zaitsev, Altinity CTO
PPTX
Web mining (structure mining)
PPTX
Zookeeper Tutorial for beginners
PDF
Lec 4 expert systems
PDF
Distributed applications using Hazelcast
PPT
FIle Management.ppt
PPT
Disk structure
PPT
Free space managment46
PDF
Git Grundlagen
Tech 2 Tech: Network performance
Cassandra Introduction & Features
Concurrency vs parallelism
Hadoop Distributed File System
Introduction to Storm
Mapreduce by examples
Stanford CS347 Guest Lecture: Apache Spark
Data mining tools overall
Apache PIG
Learn nginx in 90mins
Apache ZooKeeper
ClickHouse Introduction, by Alexander Zaitsev, Altinity CTO
Web mining (structure mining)
Zookeeper Tutorial for beginners
Lec 4 expert systems
Distributed applications using Hazelcast
FIle Management.ppt
Disk structure
Free space managment46
Git Grundlagen
Ad

Similar to Node.js введение в технологию, КПИ #ITmeetingKPI (20)

PPT
Типичный стек технологий для использования с Node.js
PPT
Node.JS: возможности для РНР-разработчика
PPTX
What do you MEAN? или введение в Fullstack JavaScript
PDF
Introduction in Node.js (in russian)
PDF
Серверный JavaScript: NodeJS и CouchDB
PDF
CodeFest 2010. Столяров С. — Серверный JavaScript: NodeJS и CouchDB
PPT
ВВЕДЕНИЕ В NODE.JS
PPT
Node.js (RichClient)
PPT
Эффективное программирование на NodeJS
PDF
ОЛЕКСАНДР ХОТЕМСЬКИЙ «Антипаттерни та велосипеди в JavaScript автоматизації» ...
PDF
2014-08-02 03 Дмитрий Шматко. Первые впечатления от Node.js
PPTX
Windows Azure and node js
PDF
Devcamp nodejs-2010
PDF
Асинхронный JavaScript
PDF
Владимир Алаев "Разработка на Node.js: инструменты, библиотеки, сервисы"
PPTX
Примеры быстрой разработки API на масштабируемом сервере приложений Impress д...
PDF
"Webpack: 7 бед — один ответ" — Денис Измайлов, MoscowJS 17
PDF
NPM и модульная архитектура приложения
PDF
NodeJS в HighLoad проекте / Акрицкий Владимир (iAge Engineering)
PPTX
Full Stack разработка на JavaScript
Типичный стек технологий для использования с Node.js
Node.JS: возможности для РНР-разработчика
What do you MEAN? или введение в Fullstack JavaScript
Introduction in Node.js (in russian)
Серверный JavaScript: NodeJS и CouchDB
CodeFest 2010. Столяров С. — Серверный JavaScript: NodeJS и CouchDB
ВВЕДЕНИЕ В NODE.JS
Node.js (RichClient)
Эффективное программирование на NodeJS
ОЛЕКСАНДР ХОТЕМСЬКИЙ «Антипаттерни та велосипеди в JavaScript автоматизації» ...
2014-08-02 03 Дмитрий Шматко. Первые впечатления от Node.js
Windows Azure and node js
Devcamp nodejs-2010
Асинхронный JavaScript
Владимир Алаев "Разработка на Node.js: инструменты, библиотеки, сервисы"
Примеры быстрой разработки API на масштабируемом сервере приложений Impress д...
"Webpack: 7 бед — один ответ" — Денис Измайлов, MoscowJS 17
NPM и модульная архитектура приложения
NodeJS в HighLoad проекте / Акрицкий Владимир (iAge Engineering)
Full Stack разработка на JavaScript
Ad

More from Timur Shemsedinov (20)

PDF
How to use Chat GPT in JavaScript optimizations for Node.js
PDF
IT Revolution in 2023-2024: AI, GPT, business transformation, future professi...
PDF
Multithreading in Node.js and JavaScript
PDF
Node.js threads for I/O-bound tasks
PDF
Rethinking low-code
PDF
Hat full of developers
PDF
FwDays 2021: Metarhia Technology Stack for Node.js
PDF
Node.js for enterprise - JS Conference
PDF
Node.js for enterprise 2021 - JavaScript Fwdays 3
PDF
Node.js in 2021
PDF
Node.js middleware: Never again!
PDF
Patterns and antipatterns
PDF
Race-conditions-web-locks-and-shared-memory
PDF
Asynchronous programming and mutlithreading
PDF
Node.js in 2020 - part 3
PDF
Node.js in 2020 - part 2
PDF
Information system structure and architecture
PDF
Node.js in 2020 - part 1
PDF
Web Locks API
PDF
Node.js in 2020
How to use Chat GPT in JavaScript optimizations for Node.js
IT Revolution in 2023-2024: AI, GPT, business transformation, future professi...
Multithreading in Node.js and JavaScript
Node.js threads for I/O-bound tasks
Rethinking low-code
Hat full of developers
FwDays 2021: Metarhia Technology Stack for Node.js
Node.js for enterprise - JS Conference
Node.js for enterprise 2021 - JavaScript Fwdays 3
Node.js in 2021
Node.js middleware: Never again!
Patterns and antipatterns
Race-conditions-web-locks-and-shared-memory
Asynchronous programming and mutlithreading
Node.js in 2020 - part 3
Node.js in 2020 - part 2
Information system structure and architecture
Node.js in 2020 - part 1
Web Locks API
Node.js in 2020

Node.js введение в технологию, КПИ #ITmeetingKPI

  • 2. От JavaScript никуда не деться «Всё, что может быть написано на JavaScript, должно быть написано на нём» «Any application that can be written in JavaScript, will eventually be written in JavaScript» Jeff Atwood основатель Stack Overflow
  • 3. Основные идеи Node.js 1. Один язык, один формат данных, одна парадигма, одна архитектура СУБД Мобильные приложения Сервер Браузер Оконные приложения JSON BSON JavaScript JavaScript JavaScript
  • 4. Основные идеи Node.js 2. Долгая жизнь приложений в оперативной памяти на стороне сервера • Состояние памяти сохраняется между запросами • Структуры данных (объекты, модель) • Соединения с БД и открытые файлы • Конфигурация и инициализация • Веб сервер внутри приложения, а не наоборот • Меньше IPC
  • 5. Основные идеи Node.js 3. Без ввода/вывода еще быстрее, чем с асинхронным вводом/выводом • Упреждающее чтение • Отложенная запись • Отдача всего из памяти
  • 6. Преимущества JavaScript: 1. Имеет очень низкий порог входа; 2. Высочайшая гибкость; 3. Высокая скорость разработки; 4. Практически идеальный уровень абстракции; …
  • 7. Недостатки JavaScript: 1. Имеет очень низкий порог входа; 2. Высочайшая гибкость; 3. Высокая скорость разработки; 4. Практически идеальный уровень абстракции; …
  • 8. Особенности JavaScript Наличие огромного количества особенностей. Как в синтаксических конструкциях, так и в логике программ. “12” + 5 === “125” Но… “12” - 5 === 7 [] + [] === “” [] + {} === “[object Object]” {} + [] === 0 isNaN({} + {}) === true
  • 10. Что такое NodeJS • Open Source JavaScript-движок V8 от Google; • Обёртка и библиотеки на JavaScript; • libuv; • Оболочка, написанная на C++.
  • 11. Google V8 • Разработка Google, исходный код которой был открыт в 2008 году; • Самый оптимальный JavaScript-движок на сегодняшний день; • Основа браузеров Google Chrome и Chromium.
  • 12. Преимущества V8 • Базовый и оптимизирующий компилятор; • Компиляция JavaScript-кода непосредственно в машинный код, без промежуточного байт-кода; • Эффективная система управления памятью; • Введение скрытых классов и встроенных кэшей, ускоряющих доступ к свойствам и вызовы функций.
  • 13. Начало работы с NodeJS 1. Установка дистрибутива с nodejs.org; 2. Создание *.js файлов; 3. Запуск программ: $ node *.js;
  • 14. Элементарный пример hello.js: console.log(“Hello, world!”); $ node hello Hello, world!
  • 15. API, менеджер пакетов и package.json $ npm init … $ npm install colors --save / /node_modules /colors ... main.js package.json net https buffer crypto path …
  • 16. package.json { "name": "Test", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo "Error: no test specified" && exit 1“ }, "author": "", "license": "ISC" }
  • 17. Система контроля версий • Git; • GitHub; • Структура проектов; • Репозитории npm; • Командная работа.
  • 19. Однопоточность и многопоточность • Что дает однопоточность? • Действительно ли 1 процесс = 1 поток? • Как нагрузить все ядра? • cluster = require('cluster') • npm install webworker-threads • самостоятельно делаем IPC
  • 20. Межпроцессовое взаимодействие • Родное IPC, cluster • Разделяемая память: Memcache? • Шина сообщений (MQ): ZeroMQ, RabbitMQ... • TCP, UDP, HTTP
  • 21. Асинхронный ввод/вывод • Реактор • Очередь • СМО fs.readFile( ‘a.txt’, onRead ); http.get( ‘http://...’, onGet ); console.log(‘done?’);
  • 22. Производительность • Производительность кода • Производительность сервера Факторы производительности Node.js • Асинхронность • Состояние в памяти • Минимизация IPC
  • 23. Память • GC (RAM 32bit: 512Mb, 64bit:1.7Gb ) • node --max-old-space-size=3000 • delete obj.field; delete arr[5]; delete name; • node --nouse-idle-notification --expose-gc application.js • Вызываем gc();
  • 24. Профилирование • npm install -g node-inspector node --debug application.js • npm install heapdump var hd = require('heapdump'); hd.writeSnapshot( 'dump'+Date.now()+'.heapsnapshot' );
  • 25. Отладка • Через node-inspector • Выводом в консоль console.log(); или в лог • Если ошибку не видно • node --stack-trace-limit=1000 application.js • Может понадобиться фильтр
  • 26. Ошибки • Общепринято в Node: function(err, arguments...) • Создаем new Error('Eror message') • Секция try {...} catch(e) {...} finally {...} • Событие .on('error', fn) если EventEmitter • Домены domain.create(); .run(fn); .on('error', fn); • Перехват process.on('uncaughtException', function(err) { console.log('uncaught Exception: '+err.stack); });
  • 27. Обновление кода и перезапуск • Наблюдение за процессом forever npm install forever -g forever start --spinSleepTime 10000 application.js • Наблюдение за файлами http://livereload.com/ http://habrahabr.ru/post/168091/
  • 28. Callback’и и вложенность Пример запроса: request('http://www.google.com/api', function (error, response, body) { var googleData = JSON.parse(body); ... } );
  • 29. Callback’и и вложенность request('http://www.google.com/api', function (gError, gResponse, gBody) { request('http://www.yandex.com/api', function (yError, yResponse, yBody) { request('http://www.twitter.com/api', function (tError, tResponse, tBody) { ... } ...
  • 30. Callback’и: Библиотека async async.parallel([ function(){ ... }, function(){ ... } ], callback); Другие методы: series, parallel, whilst, until, waterfall, compose, queue, cargo, retry, each, map, reduce, detect, every ...
  • 31. Callback’и: Библиотека async async.parallel([ function(callback){ request('http://google.com/api', function(error, response, body) { callback(error, body); }); }, function(callback){ request('http://yandex.com/api', function(error, response, body) { callback(error, body); }); }, function(callback){ request('http://twitter.com/api', function(error, response, body) { callback(error, body); }); }, ], function(err, results) { ... });
  • 32. Callback’и: Библиотека async async.parallel([ function(callback){ googleApiService(callback); }, function(callback){ yandexApiService(callback); }, function(callback){ twitterApiService(callback); }, ], function(err, results) { ... });
  • 33. Callback’и: Promise (Q) https://github.com/kriskowal/q Promise.then(function(success) { ... }, function(error) { ... });
  • 34. Callback’и: Promise (Q) Q.fcall(googleApiService) .then(yandexApiService) .then(twitterApiService); Q.all([ googleApiService(), yandexApiService(), twitterApiService() ]) .then();
  • 35. Express Простой, нетребовательный и минималистический middleware- фреймворк для разработки WEB- приложений на NodeJS; $ npm install express --save
  • 36. Простое приложение на express var express = require(“express”), app = express(); app.get(“/”, function (request, response) { response.send(“Hello, stranger!”); }); app.listen(80);
  • 37. Приложение на express var express = require(“express”), app = express(), storage = { “home”: { head: “Sweet home” }, “about”: { head: “” } }; app.use(express.static(__dirname + “/public”)); app.get(“/:page?”, function (request, response) { var page = request.params.page, data = storage[page || “home”]; if (!data) return response.redirect(“/”); response.render(“home”, data); }); app.listen(80);
  • 38. Элегантность express var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var routes = require('./routes/index'); var users = require('./routes/users'); var app = express(); // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); // uncomment after placing your favicon in /public //app.use(favicon(__dirname + '/public/favicon.ico')); app.use(logger('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded()); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); app.use('/', routes); app.use('/users', users); /// catch 404 and forwarding to error handler app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); /// error handlers // development error handler // will print stacktrace if (app.get('env') === 'development') { app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: err }); }); } // production error handler // no stacktraces leaked to user app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: {} }); }); app.use('/', routes); app.use('/users', users); module.exports = app;
  • 39. Сборка проектов • Для чего собирать проекты; • Система сборки grunt; • Gruntfile; • Пакеты npm grunt-contrib-*.
  • 40. Пример Gruntfile.js module.exports = function(grunt) { grunt.initConfig({ uglify: { dist: { files: { “build/app.js”: [“source/app.js”] } } } }); grunt.loadNpmTasks(“grunt-contrib-uglify”); grunt.registerTask(“default”, [“uglify”]); }
  • 42. Grunt устанавливается как NPM (Node Package Manager) модуль. > npm install -g grunt > grunt > grunt serve > grunt build
  • 43. Gruntfile.js module.exports = function (grunt) { require('load-grunt-tasks')(grunt); var yeoman = { app: 'app' }; try { yeomanConfig.app = require('./bower.json').appPath || yeoman.app; } catch () {e} grunt.initConfig({ yeoman: yeomanConfig,
  • 44. Grunt register tasks - default grunt.registerTask ('default', [ 'jshint', 'test', 'build' ]);
  • 45. Grunt register tasks - test grunt.registerTask('test', [ 'clean:server', 'less:modulesToTmp', 'copy:viewsModulesToTmp', 'copy:jsModulesToTmp', 'concat:modulesToTmp', 'autoprefixer', 'connect:test', 'karma' ]);
  • 46. Grunt register tasks - build grunt.registerTask('build', [ 'clean:dist', 'less:modulesToTmp', 'copy:viewsModulesToTmp', 'copy:jsModulesToTmp', 'useminPrepare', 'autoprefixer', 'copy:dist', 'concat', 'ngmin', 'uglify', 'imagemin', 'htmlmin', 'usemin', 'rev'
  • 47. Grunt register tasks - server grunt.registerTask('server', function (target) { if (target === 'dist') { return grunt.task.run(['build', 'open', 'connect:dist:keepalive']); } grunt.task.run([ 'clean:server', 'less:modulesToTmp', 'copy:viewsModulesToTmp', 'copy:jsModulesToTmp', 'concat:modulesToTmp', 'autoprefixer', 'configureProxies', 'connect:livereload', 'open', 'watch'
  • 48. Grunt tasks - clean clean: { server: '<%= yeoman.temp %>', dist: { files: [{ dot: true, src: [ '<%= yeoman.temp %>', '<%= yeoman.dist %>' ] }] } }
  • 49. Grunt tasks - less less: { modulesToTmp: { src: '<%= yeoman.app %>/modules/**/*.less', dest: '<%= yeoman.temp %>/css/main.css' } }
  • 50. Grunt tasks - copy copy: { viewsModulesToTmp: { files: [{ expand: true, cwd: '<%= yeoman.app %>/modules/', dest: '<%= yeoman.temp %>/views', src: ['**/*.html'], rename: function(dest, src) { return dest + '/' + src.replace(/views//gi, ''); } }]
  • 51. Grunt tasks - concat concat: { modulesToTmp: { options: { banner: '"use strict";n', process: function(src, filepath) { return '// Source: ' + filepath + 'n' + src.replace(/(^|n)[ t]*('use strict'|"use strict");?s*/g, '$1'); } }, files: { '<%= yeoman.temp %>/js/controllers.min.js' : '<%= yeoman.app %>/modules/**/*.Controllers.js', '<%= yeoman.temp %>/js/directives.min.js' : '<%= yeoman.app %>/modules/**/*.Directives.js', '<%= yeoman.temp %>/js/filters.min.js' : '<%= yeoman.app %>/modules/**/*.Filters.js', '<%= yeoman.temp %>/js/services.min.js' : '<%= yeoman.app %>/modules/**/*.Services.js' }}}
  • 52. Grunt tasks - conect var LIVERELOAD_PORT = 35729; var lrSnippet = require('connect-livereload')({ port: LIVERELOAD_PORT }); var proxySnippet = require('grunt-connect-proxy/lib/utils').proxyRequest; var mountFolder = function (connect, dir) { return connect.static(require('path').resolve(dir)); }; connect: { options: { port: 8800, hostname: 'localhost' }, proxies: [{ context: '/api', host: '127.0.0.1', port: 7777, https: false, changeOrigin: false, xforward: false }], livereload: { options: { middleware: function (connect) { return [ lrSnippet, proxySnippet, mountFolder(connect, '.tmp'), mountFolder(connect, yeomanConfig.app) ]; }}}
  • 53. Grunt tasks - open open: { server: { url: 'http://localhost:<%= connect.options.port %>' } }
  • 54. Grunt tasks - watch watch: { livereload: { options: { livereload: LIVERELOAD_PORT}, files: [ '<%= yeoman.temp %>/**/*.html', '<%= yeoman.temp %>/css/**/*.css', '<%= yeoman.temp %>/js/**/*.js', '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}']}, js: { files: ['<%= yeoman.app %>/modules/**/*.js'], tasks: ['copy:jsModulesToTmp', 'concat:modulesToTmp'] }, css: { files: ['<%= yeoman.app %>/modules/**/*.less'], tasks: ['less:modulesToTmp']}
  • 58. Примеры внедрения и Highload-проекты
  • 59. Интерактивное телевидение 7Sense • 10млн. открытых соединений на 15 серверах • 30тыс. request/second на одном сервере • Impress Application Server • Server-Sent Events • IPC, ZeroMQ
  • 60. Масштабирование Impress App Server Load Balancer С1 С3 C1N1 C1N2 C1N3 C2N1 C2N2 C2N3 C3N1 C3N2 С0 Impress Cloud Controller Impress Application Server IPC HTTP ØMQ pub/sub + req/rep С2 C3N3
  • 61. Жизненный цикл проекта • Юниттесты и интеграционные тесты • Continuous Integration (CI) • Travis-CI • drone.io • Развертывание среды • vagrant • docker
  • 62. Сферы применения node.js Часто применяется для: • cервера веб-приложений и SPA • сервера мобильных приложений • системы сборки для фронт-энда • чаты, меседжинг • игровые сервера • как заплатка к ПО на других технологиях • парсеры, кравлеры
  • 63. Сферы применения node.js Реже применяется для: • оконные приложения: node-webkit • приложения баз данных и корпоративные • промышленная автоматизация и программирование микроконтроллеров (arduino, espruino, tessel) • обработка и трансляция видео и звука
  • 64. Сферы применения node.js Редко применяется (но подходит) для: • CMS, публикация контента • электронная коммерция и торговля И плохо подходит: • вычисления и моделирование • научные приложения
  • 66. karma: { unit: { configFile: 'karma.conf.js', singleRun: true } },
  • 67. describe('Service: Auth', function () { // load the service's module beforeEach(module('devApp')); // instantiate service var Auth; beforeEach(inject(function (_Auth_) { Auth = _Auth_; })); it('should do something', function () { expect(!!Auth).toBe(true); }); });
  • 68. var should = require('should'); var request = require('supertest'); describe('GET /api/things', function() { it('should respond with JSON array', function(done) { request(app) .get('/api/things') .expect(200) .expect('Content-Type', /json/) .end(function(err, res) { if (err) return done(err); res.body.should.be.instanceof(Array); done(); });
  • 70. Полезные материалы • npm (www.npmjs.org); • nodejs.org/api; • learn.javascript.ru; • learn.javascript.ru/nodejs-screencast; • nodeschool.io; • habrahabr.ru/hub/nodejs; • nodeguide.ru; • …