Node.JS
Fundamentals
We expect cooperation from all participants to help ensure a safe environment for everybody.
We treat everyone with respect, we refrain from using offensive language and imagery, and we encourage to report any derogatory or offensive behavior to a member of the JSLeague community.
We provide a fantastic environment for everyone to learn and share skills regardless of gender, gender identity and expression, age, sexual orientation, disability, physical appearance, body size, race, ethnicity, religion (or lack thereof), or technology choices.
We value your attendance and your participation in the JSLeague community and expect everyone to accord to the community Code of Conduct at all JSLeague workshops and other events.
Code of conduct
Whoami
Alexandru Albu
Trainer @JSLeague
frontend developer @8yo
design: photoshop, illustrator
development: javascript. python, sql, mongo
devops: docker
and gaming and basketball
Overview
Node.JS Fundamentals
Node.JS Fundamentals
Day 1 Agenda
Node.js Framework
Installation and setup
Modules and npm
The Callback pattern
Error handling
File System
Buffers
Streams
Day 2 Agenda
Events
Threads
ExpressJS Middlewares
Exposing publicly APIs
Data Persistency
Day 3 Agenda
Continuous communication
Securing Web APIs
Unit testing
Building the App
Ready for Production
Node.JS Fundamentals
09:30 - 10:00 | Meet && Greet |
10:00 - 10:30 | NodeJS Framework |
10:30 - 11:00 | Installation && Setup |
11:00 - 11:15 | Short break |
11:15 - 12:00 | Modules && NPM |
12:00 - 13:00 | Lunch break |
13:00 - 13:30 | The Callback pattern |
13:30 - 14:00 | Error handling |
14:00 - 14:30 | File System |
14:30 - 15:00 | Buffers |
15:00 - 15:15 | Short break |
15:15 - 16:15 | Streams |
16:15 - 17:30 | Review && Q&A |
Day 1
Node.JS Fundamentals
09:30 - 10:10 | Events |
10:10 - 11:00 | Threads |
11:00 - 11:15 | Short break |
11:15 - 11:40 | ExpressJS Middlewares |
11:40 - 12:00 | Exposing publicly APIs (I) |
12:00 - 13:00 | Lunch break |
13:00 - 13:20 | Exposing publicly APIs (II) |
13:20 - 15:00 | Data persistency (I) |
15:00 - 15:15 | Short break |
15:15 - 16:30 | Data persistency (II) |
16:30 - 17:30 | Review && Q&A |
Day 2
Node.JS Fundamentals
09:30 - 10:30 | Continuous communication |
10:30 - 11:15 | Securing web APIs |
11:15 - 11:30 | Short break |
11:30 - 12:00 | Unit testing (I) |
12:00 - 13:00 | Lunch break |
13:00 - 14:00 | Unit testing (II) |
14:00 - 15:00 | Building the app |
15:00 - 15:15 | Short break |
15:15 - 16:30 | Ready for production |
16:30 - 17:30 | Review && Q&A && Goodbye's |
Day 3
Node.JS Framework
Node.JS Fundamentals
Node.JS Fundamentals
Node.JS Fundamentals
Node.JS Fundamentals
Installation && Setup
Node.JS Fundamentals
Node.JS Fundamentals
Download directly from:
https://nodejs.org/en/download/
or download it with a package manager:
https://nodejs.org/en/download/package-manager/
or on unix systems via NVM:
Node.JS Fundamentals
EXERCISE TIME : #STEP-0
Modules && NPM
Node.JS Fundamentals
Node.JS Fundamentals
What is a Module in Node.JS ?
Module in Node.js is a simple or complex functionality organized in single or multiple JavaScript files which can be reused throughout the Node.js application.
Node.JS Fundamentals
one of the most ancient module systems, initially implemented by the library require.js.
the module system created for Node.js server.
one more module system, suggested as a universal one, compatible with AMD and CommonJS.
Node.JS Fundamentals
// main.js
const Square = require('./square.js');
const mySquare = new Square(2);
console.log(`The area of mySquare is ${mySquare.area()}`);
// square.js
// Assigning to exports will not modify module, must use module.exports
module.exports = class Square {
constructor(width) {
this.width = width;
}
area() {
return this.width ** 2;
}
};
Node.JS Fundamentals
What is NPM ?
- NPM stands for Node Package Manager
- Online repository for open-source NodeJS projects
- Command-line utility for the online repository
Node.JS Fundamentals
Node.JS Fundamentals
package.json
name
version
main
scripts
dependencies
devDependencies
license
Node.JS Fundamentals
node_modules
Node.JS Fundamentals
Node.JS Fundamentals
EXERCISE TIME : #STEP-1 && #STEP-2
The callback pattern
Node.JS Fundamentals
Node.JS Fundamentals
Node.JS async
how does it handle flow?
callbacks!!!
Node.JS Fundamentals
function processData () {
var data = fetchData ();
data += 1;
return data;
}
Node.JS Fundamentals
function processData (callback) {
fetchData(function (err, data) {
if (err) {
console.log("An error has occurred. Abort everything!");
return callback(err);
}
data += 1;
callback(data);
});
}
Node.JS Fundamentals
function asyncOperation ( a, b, c, callback ) {
// ... lots of hard work ...
if ( /* an error occurs */ ) {
return callback(new Error("An error has occurred"));
}
// ... more work ...
callback(null, d, e, f);
}
asyncOperation ( params.., function ( err, returnValues.. ) {
//This code gets run after the async operation gets run
});
Node.JS Fundamentals
Node.JS Fundamentals
EXERCISE TIME : #STEP-3
Error handling
Node.JS Fundamentals
Node.JS Fundamentals
Operational errors
vs.
Programming errors
Node.JS Fundamentals
Error Object
throw new Error(<some error here>)
Node.JS Fundamentals
NodeJS Error Classes
AssertionError
RangeError
SystemError
etc.
Node.JS Fundamentals
try {
doAction(); // do some things
throw 'myException'; // generates an exception
}
catch (e) {
// statements to handle any exceptions
logMyErrors(e); // pass exception object to error handler
} finally {
// do not break gracefully
}
try... catch... finally
Node.JS Fundamentals
const fs = require('fs');
function errorFirstCallback(err, data) {
if (err) {
console.error('There was an error', err);
return;
}
console.log(data);
}
fs.readFile('/some/file/that/does-not-exist', errorFirstCallback);
fs.readFile('/some/file/that/does-exist', errorFirstCallback);
Error first callbacks
Node.JS Fundamentals
// THIS WILL NOT WORK:
const fs = require('fs');
try {
fs.readFile('/some/file/that/does-not-exist', (err, data) => {
// Mistaken assumption: throwing here...
if (err) {
throw err;
}
});
} catch (err) {
// This will not catch the throw!
console.error(err);
}
Node.JS Fundamentals
EXERCISE TIME : #STEP-4
File system
Node.JS Fundamentals
Node.JS Fundamentals
const fs = require('fs');
Node.JS Fundamentals
Async vs. Sync
Node.JS Fundamentals
const fs = require('fs');
fs.unlink('/tmp/hello', (err) => {
if (err) throw err;
console.log('successfully deleted /tmp/hello');
});
Async
Node.JS Fundamentals
const fs = require('fs');
try {
fs.unlinkSync('/tmp/hello');
console.log('successfully deleted /tmp/hello');
} catch (err) {
// handle the error
}
Sync
Node.JS Fundamentals
fs.rename('/tmp/hello', '/tmp/world', (err) => {
if (err) throw err;
console.log('renamed complete');
});
fs.stat('/tmp/world', (err, stats) => {
if (err) throw err;
console.log(`stats: ${JSON.stringify(stats)}`);
});
Concurrency
Node.JS Fundamentals
fs.rename('/tmp/hello', '/tmp/world', (err) => {
if (err) throw err;
fs.stat('/tmp/world', (err, stats) => {
if (err) throw err;
console.log(`stats: ${JSON.stringify(stats)}`);
});
});
Concurrency avoided
Node.JS Fundamentals
Async doesn't mean Promise
fs.promises.<command>
Node.JS Fundamentals
EXERCISE TIME : #STEP-5
Buffers
Node.JS Fundamentals
Node.JS Fundamentals
Why?
While Node.JS works great with binary data as strings, it can sometimes have unforeseen side effects.
Buffers also give a performance improvement.
Node.JS Fundamentals
var buffer = Buffer.alloc(8);
// This will print out 8 bytes of zero:
// <Buffer 00 00 00 00 00 00 00 00>
var buffer = Buffer.from([ 8, 6, 7, 5, 3, 0, 9]);
// This will print out 8 bytes of certain values:
// <Buffer 08 06 07 05 03 00 09>
var buffer = Buffer.from("I'm a string!", "utf-8");
// This will print out a chain of values in utf-8:
// <Buffer 49 27 6d 20 61 20 73 74 72 69 6e 67 21>
Creating Buffers
Node.JS Fundamentals
// Create a size 16 empty buffer
const buffer = Buffer.alloc(16)
// Add string to buffer
buffer.write("Hello", "utf-8")
// returns 5 - number of bytes written to the buffer
// Add another string to buffer
buffer.write(" world!", 5, "utf-8")
// returns 7
Writing to Buffers
Node.JS Fundamentals
buffer.toString('utf-8')
// 'Hello world!\u0000�k\t'
buffer.toString("utf-8", 0, 12)
// 'Hello world!'
Reading from Buffers
Node.JS Fundamentals
EXERCISE TIME : #STEP-6
Streams
Node.JS Fundamentals
Node.JS Fundamentals
What are Streams?
Streams are objects that let you continuously work with data.
Node.JS Fundamentals
Types of Streams:
Writable: streams to which data can be written
Readable: streams from which data can be read
Duplex: streams that are both Readable and Writable
Transform: Duplex streams that can modify or transform the data as it is written and read
Node.JS Fundamentals
const readable = getReadableStreamSomehow();
// When receiving data
readable.on('data', (chunk) => {
console.log(`Received ${chunk.length} bytes of data.`);
});
// End event
readable.on('end', () => {
console.log('There will be no more data.');
});
Readable Streams
Node.JS Fundamentals
const myStream = getWritableStreamSomehow();
myStream.write('some data');
myStream.write('some more data');
myStream.end('done writing data');
Writable Streams
Node.JS Fundamentals
EXERCISE TIME : #STEP-7
Events
Node.JS Fundamentals
Node.JS Fundamentals
Much of Node.JS architecture is build around Events.
Event driven architecture
Node.JS Fundamentals
const EventEmitter = require('events');
// create a new event emitter
const myEmitter = new EventEmitter();
// listening to an event
myEmitter.on('customEvent', () => {
console.log('customEvent was received!')
})
// firing an event
myEmitter.emit('customEvents')
Working with Events
Node.JS Fundamentals
const EventEmitter = require('events');
// create a new event emitter
const myEmitter = new EventEmitter();
// listening to an event
myEmitter.on('customEvent', (...params) => {
console.log('customEvent was received!')
console.log('we also have params: ', params)
})
// firing an event
myEmitter.emit('customEvents', "value1", {"value2": 2});
Sending params
Node.JS Fundamentals
const EventEmitter = require('events');
// create a new event emitter
const myEmitter = new EventEmitter();
// listening to an event async
myEmitter.on('customEvent', () => {
console.log('customEvent was received async!')
})
// listening to an event sync
myEmitter.on('customEvent', () => {
setImmediate(() => {
console.log('customEvent was received sync!')
});
})
// firing an event
myEmitter.emit('customEvent');
Async vs Sync
Node.JS Fundamentals
const EventEmitter = require('events');
// create a new event emitter
const myEmitter = new EventEmitter();
// listening to an event
myEmitter.once('customEvent', () => {
console.log('customEvent was received!')
})
// firing an event
myEmitter.emit('customEvent');
myEmitter.emit('customEvent');
myEmitter.emit('customEvent');
myEmitter.emit('customEvent');
Handling events once
Node.JS Fundamentals
const EventEmitter = require('events');
// create a new event emitter
const myEmitter = new EventEmitter();
// listening to an event
myEmitter.on('error', (err) => {
console.error(err)
})
// firing an event
myEmitter.emit('error', new Error());
Handling error events
Node.JS Fundamentals
const EventEmitter = require('events');
const express = require('express')
const eventEmitter = new EventEmitter();
const app = express();
// set event emitter on express app
app.set('eventEmitter', eventEmitter);
// access it from any module of the application
console.log(app.get('eventEmitter'));
ExpressJS Event handling
Node.JS Fundamentals
EXERCISE TIME : #STEP-8
Threads
Node.JS Fundamentals
Node.JS Fundamentals
JavaScript by design is single threaded.
Node.JS Fundamentals
const {
Worker, isMainThread, parentPort, workerData
} = require('worker_threads');
if (isMainThread) {
module.exports = function parseJSAsync(script) {
return new Promise((resolve, reject) => {
const worker = new Worker(__filename, {
workerData: script
});
worker.on('message', resolve);
worker.on('error', reject);
worker.on('exit', (code) => {
if (code !== 0)
reject(new Error(`Worker stopped with exit code ${code}`));
});
});
};
} else {
const { parse } = require('some-js-parsing-library');
const script = workerData;
parentPort.postMessage(parse(script));
}
Node.JS Fundamentals
EXERCISE TIME : #STEP-9
ExpressJS Middlewares
Node.JS Fundamentals
Node.JS Fundamentals
Middleware functions are functions that have access to the request object (req), the response object (res), and the next middleware function in the application’s request-response cycle. The next middleware function is commonly denoted by a variable named next.
Node.JS Fundamentals
Call the next middleware function in the stack.
End the request-response cycle.
Make changes to the request and the response objects.
Execute any code.
Node.JS Fundamentals
Application level
Router level
Third party
Built-in
Error handling
Node.JS Fundamentals
var express = require('express')
var app = express()
app.use(function (req, res, next) {
console.log('Time:', Date.now())
next()
})
app.use('/user/:id', function (req, res, next) {
console.log('Request Type:', req.method)
next()
})
app.use('/user/:id', function (req, res, next) {
console.log('Request URL:', req.originalUrl)
next()
}, function (req, res, next) {
console.log('Request Type:', req.method)
next()
})
Application level
Node.JS Fundamentals
var express = require('express')
var app = express()
var router = express.Router()
// a middleware function with no mount path.
// This code is executed for every request to the router
router.use(function (req, res, next) {
console.log('Time:', Date.now())
next()
})
// a middleware sub-stack shows request info
// for any type of HTTP request to the /user/:id path
router.use('/user/:id', function (req, res, next) {
console.log('Request URL:', req.originalUrl)
next()
}, function (req, res, next) {
console.log('Request Type:', req.method)
next()
})
Router level
Node.JS Fundamentals
var express = require('express')
var app = express()
app.use(function (err, req, res, next) {
console.error(err.stack)
res.status(500).send('Something broke!')
})
Error handling
Node.JS Fundamentals
Built-in
- express.static serves static assets such as HTML files, images, and so on.
- express.json parses incoming requests with JSON payloads.
- express.urlencoded parses incoming requests with URL-encoded payloads.
Node.JS Fundamentals
var express = require('express')
var app = express()
var cookieParser = require('cookie-parser')
// load the cookie-parsing middleware
app.use(cookieParser())
Third party
Exposing publicly APIs
Node.JS Fundamentals
Node.JS Fundamentals
var express = require('express')
var app = express()
// respond with "hello world" when a GET request is made to the homepage
app.get('/', function (req, res) {
res.send('hello world')
})
Basic route
Node.JS Fundamentals
var express = require('express')
var app = express()
// GET method route
app.get('/', function (req, res) {
res.send('GET request to the homepage')
})
// POST method route
app.post('/', function (req, res) {
res.send('POST request to the homepage')
})
Route methods
Node.JS Fundamentals
app.get('/', function (req, res) {
res.send('root')
})
app.get('/about', function (req, res) {
res.send('about')
})
app.get('/ab*cd', function (req, res) {
res.send('ab*cd')
})
app.get('/ab(cd)?e', function (req, res) {
res.send('ab(cd)?e')
})
app.get(/.*fly$/, function (req, res) {
res.send('/.*fly$/')
})
Route paths
Node.JS Fundamentals
app.get('/users/:userId/books/:bookId', function (req, res) {
res.send(req.params)
})
Route params
Node.JS Fundamentals
Response methods
Method | Description |
---|---|
res.download() | Prompt a file to be downloaded. |
res.end() | End the response process. |
res.json() | Send a JSON response. |
res.jsonp() | Send a JSON response with JSONP support. |
res.redirect() | Redirect a request. |
res.render() | Render a view template. |
res.send() | Send a response of various types. |
res.sendFile() | Send a file as an octet stream. |
res.sendStatus() | Set the response status code and send its string representation as the response body. |
Node.JS Fundamentals
app.route('/book')
.get(function (req, res) {
res.send('Get a random book')
})
.post(function (req, res) {
res.send('Add a book')
})
.put(function (req, res) {
res.send('Update the book')
})
app level router
Node.JS Fundamentals
var express = require('express')
var router = express.Router()
// middleware that is specific to this router
router.use(function timeLog (req, res, next) {
console.log('Time: ', Date.now())
next()
})
// define the home page route
router.get('/', function (req, res) {
res.send('Birds home page')
})
// define the about route
router.get('/about', function (req, res) {
res.send('About birds')
})
module.exports = router
router module
Data persistency
Node.JS Fundamentals
Node.JS Fundamentals
Node.JS Fundamentals
ORMs
Node.JS Fundamentals
Sequelize connection
const { Sequelize } = require('sequelize');
// Option 1: Passing a connection URI
const sequelize = new Sequelize('postgres://user:pass@example.com:5432/dbname')
// Example for postgres
// Option 2: Passing parameters separately
const sequelize = new Sequelize({
dialect: 'postgres',
storage: 'path/to/database.sqlite'
});
// Option 2: Passing parameters separately (other dialects)
const sequelize = new Sequelize('database', 'username', 'password', {
host: 'localhost',
dialect: 'postgres'
});
Node.JS Fundamentals
Sequelize test connection
try {
await sequelize.authenticate();
console.log('Connection has been established successfully.');
} catch (error) {
console.error('Unable to connect to the database:', error);
}
Node.JS Fundamentals
Sequelize model
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize('sqlite::memory:');
const User = sequelize.define('User', {
// Model attributes are defined here
firstName: {
type: DataTypes.STRING,
allowNull: false
},
lastName: {
type: DataTypes.STRING
// allowNull defaults to true
}
}, {
// Other model options go here
});
// `sequelize.define` also returns the model
console.log(User === sequelize.models.User); // true
Node.JS Fundamentals
Sequelize queries
// Create a new user
const jane = await User.create({ firstName: "Jane", lastName: "Doe" });
console.log("Jane's auto-generated ID:", jane.id);
// Find all users
const users = await User.findAll();
// Where clauses
const users = await UserfindAll({
where: { lastName: "Doe" }
})
// Operators
const { Op } = require("sequelize");
Users.findAll({
where: {
[Op.and]: [
{ firstName: "Jane" }, { lastName: "Doe" }
]
}
});
Node.JS Fundamentals
Mongoose connection
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
Node.JS Fundamentals
Mongoose test connection
const mongoose = require('mongoose');
// mongoose module is singleton
console.log(mongoose.connection.readyState);
Node.JS Fundamentals
Mongoose model
const mongoose = require('mongoose');
const schema = new mongoose.Schema({
firstName: 'string',
lastName: 'string'
});
// // The first param defines also the collection name
const User = mongoose.model('User', schema);
Node.JS Fundamentals
Mongoose queries
const mongoose = require('mongoose');
// Create a user
var jane = new User({ firstName: 'Jane', lastName: 'Doe' });
jane.save(function (err) {
if (err) return handleError(err);
// saved!
});
User.create({ firstName: 'Jane', lastName: 'Doe' }, function (err, small) {
if (err) return handleError(err);
// saved!
});
Tank.insertMany([{ lastName: 'Doe' }], function(err) {
// handle error here
});
// Find a user
User.find({ lastName: 'Doe' })
.where('createdDate')
.gt(oneYearAgo)
.exec(callback);
Node.JS Fundamentals
EXERCISE TIME : #STEP-10
Continuous communication
Node.JS Fundamentals
Node.JS Fundamentals
The WebSocket API is an advanced technology that makes it possible to open a two-way interactive communication session between the user's browser and a server. With this API, you can send messages to a server and receive event-driven responses without having to poll the server for a reply.
Node.JS Fundamentals
WebSocket
Node.JS Fundamentals
const socket = new WebSocket('ws://localhost:3000');
socket.onopen(() => {
socket.send('Hello!');
});
socket.onmessage(data => {
console.log(data);
});
WebSocket connection
Node.JS Fundamentals
const socket = io('ws://localhost:3000');
socket.on('connect', () => {
// either with send()
socket.send('Hello!');
// or with emit() and custom event names
socket.emit('salutations', 'Hello!', { 'mr': 'john' });
});
// handle the event sent with socket.send()
socket.on('message', data => {
console.log(data);
});
// handle the event sent with socket.emit()
socket.on('greetings', (elem1, elem2, elem3) => {
console.log(elem1, elem2, elem3);
});
socket.io connection client
Node.JS Fundamentals
const io = require('socket.io')(3000);
io.on('connect', socket => {
// either with send()
socket.send('Hello!');
// or with emit() and custom event names
socket.emit('greetings', 'Hey!', { 'ms': 'jane' });
// handle the event sent with socket.send()
socket.on('message', (data) => {
console.log(data);
});
// handle the event sent with socket.emit()
socket.on('salutations', (elem1, elem2, elem3) => {
console.log(elem1, elem2, elem3);
});
});
socket.io connection server
Node.JS Fundamentals
var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', (socket) => {
console.log('a user connected');
});
http.listen(3000, () => {
console.log('listening on *:3000');
});
express.js with socket.io
Node.JS Fundamentals
EXERCISE TIME : #STEP-11
Securing web APIs
Node.JS Fundamentals
Node.JS Fundamentals
Why?
Node.JS Fundamentals
helmet
npm install --save helmet
Middleware collection of security headers
Node.JS Fundamentals
const express = require("express");
const helmet = require("helmet");
const app = express();
// This...
app.use(helmet());
// ...is equivalent to this:
app.use(helmet.contentSecurityPolicy());
app.use(helmet.dnsPrefetchControl());
app.use(helmet.expectCt());
app.use(helmet.frameguard());
app.use(helmet.hidePoweredBy());
app.use(helmet.hsts());
app.use(helmet.ieNoOpen());
app.use(helmet.noSniff());
app.use(helmet.permittedCrossDomainPolicies());
app.use(helmet.referrerPolicy());
app.use(helmet.xssFilter());
using helmet
Node.JS Fundamentals
secure cookies
npm install --save express-session cookie-session
Session storage in production is best done with a database provider
Node.JS Fundamentals
whitelisting
npm install --save cors
Requests origin white/black listing
Node.JS Fundamentals
const express = require('express')
const cors = require('cors')
const app = express()
app.use(cors())
using cors
Node.JS Fundamentals
audit
npm audit
NodeJS tool to check for security vulnerabilities
Node.JS Fundamentals
Node.JS Fundamentals
EXERCISE TIME : #STEP-12
Unit testing
Node.JS Fundamentals
Node.JS Fundamentals
Node.JS Fundamentals
// Load express module with `require` directive
const express = require('express')
const app = express()
// Define request response in root URL (/)
app.get('/', function (req, res) {
res.send('Hello World')
})
// Launch listening server on port 8080
app.listen(8080, function () {
console.log('App listening on port 8080!')
})
Basic Express App
Node.JS Fundamentals
const chai = require('chai');
const chaiHttp = require('chai-http');
const app = require('../app.js');
const expect = chai.expect;
chai.use(chaiHttp)
it('Should fetch data', (done) => {
chai.request(app)
.get('/')
.end((err, res) => {
if(err) done(err);
expect(res).to.have.status(200);
expect(res).to.be.an('object');
expect(res.body).to.deep.equals('Hello World');
})
});
Basic test
Node.JS Fundamentals
// package.json
"scripts": {
"test": "mocha ./**/*.test.js"
}
// terminal
npm test
Running tests
Node.JS Fundamentals
EXERCISE TIME : #STEP-13
Building Node.JS applications
Node.JS Fundamentals
Node.JS Fundamentals
Node.JS Fundamentals
const path = require('path');
module.exports = {
entry: './path/to/my/entry/file.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
}
};
webpack simple configuration file
Node.JS Fundamentals
const path = require('path')
const webpack = require('webpack')
const nodeExternals = require('webpack-node-externals')
module.exports = {
entry: {
server: './app.js',
},
output: {
path: path.join(__dirname, 'dist'),
publicPath: '/',
filename: '[name].js'
},
target: 'node',
node: {
// Need this when working with express, otherwise the build fails
__dirname: false, // if you don't put this is, __dirname
__filename: false, // and __filename return blank or /
},
externals: [nodeExternals()], // Need this to avoid error when working with Express
}
webpack express configuration file
Node.JS Fundamentals
EXERCISE TIME : #STEP-14
Production ready
Node.JS Fundamentals
Node.JS Fundamentals
Set NODE_ENV=production
Add gzip with compression
Availability through pm2
Dockerize delivery
Node.JS Fundamentals
EXERCISE TIME : #STEP-15
Q&A
Node.JS Fundamentals
Thank you!
Node.js Fundamentals
By Alex Albu
Node.js Fundamentals
- 488