Talking about future of NodeJS, from Node 7 to Node 10.
NPM 5. N-API, async_hooks, util.promisify().
A big part on the ESM vs CommonJS module loader, and all the problem NodeJS is facing to implement ESM.
2. ES6 / ES7 / ES2015 / ES2016
" ES7 is ES2016"
" ES6 is ES2015 "
" Too long for twitter … "
" How many people here are going to say ES2016 "
" Nobody, good ! "
3. Ecmascript from past to future
ES 8
ES 7
(ES 2016)
ES 6
(ES 2015)
ES 5
ES 3 Core features
1997 ~~ 1999
new functions
strict mode, json
2009
class, promises, generators,
arrow functions, new syntax
and concepts …
2015
Exponential (**),
array.includes,
2016
8. Transpiler vs Compiler
Transpiler
is a specific term for taking source
code written in one language and
transforming into another
language that has a similar level of
abstraction
Compiler
is the general term for taking
source code written in one
language and transforming into
another.
"CoffeeScript is to Ruby as TypeScript is to Java/C#/C++." - Luke Hoban
29. NPM 5.0.0
• --save by default
• Autmaticaly create a package-
lock.json
• npm cache rewrited
• You will have to ree-download all
your package cache
• npm fallback automaticaly to cache
if no network
• -- prefer-offline
• -- prefer-online
• -- offline
• Large package download issue
resolved
32. Nouveautés Node 8
• Say hello to V8 5.8
• Forward compatibility with V8 5.9 and V8 6.0
33. Node.js API (N-API)
• Platform for building native addons.
• Independant from the underlying JavaScript Runtime
• API is Application Binary Interface (ABI) stable accross Node.JS
• Every native addons will be compatible with
• Chrome V8
• ChakraCore (https://github.com/nodejs/node-chakracore/ )
34.
35. Node 8 : async_hooks
async_hooks : nodejs async tracing
“tracking the lifetime of asynchronous resources created inside a
Node.js application”
const async_hooks = require('async_hooks');
const cid = async_hooks.currentId();
const tid = async_hooks.triggerId();
const asyncHook = async_hooks.createHook({ init, before, after, destroy });
asyncHook.enable();
function init(asyncId, type, triggerId, resource) {}
function before(asyncId) {}
function after(asyncId) {}
function destroy(asyncId) {}
36. Node 8 : WHATWG URL Standard
• URL Standard : https://url.spec.whatwg.org/
• The URL Standard defines URLs, domains, IP addresses, the
application/x-www-form-urlencoded format, and their API.
• The URL standard takes the following approach towards making URLs
fully interoperable
import * as urlUtility from 'url';
const myUrl = new urlUtility.URL('/a/path', 'https://example.org/');
console.log(myUrl.toString());
37. Node 8 : util.promisify()
• util.promisify() API that allows standard Node.js callback style APIs to
be wrapped in a function that returns a Promise
• Callback Style : (err, value) => {}
function breeze(a: number, callback: (err: any, value?: number) => void) {
if (a > 10) {
callback(undefined, a * a);
} else {
callback("a must be greater than 10");
}
}
const awaitableBreeze = util.promisify(breeze);
43. ESM vs CJS
export class person {
getFullName() { return `${this.lastName} ${this.firstName}`; }
}
import * as people from './person';
var p = new people.person();
class person {
getFullName() { return `${this.lastName} ${this.firstName}`; }
}
exports.person = person;
const people = require("./person");
var p = new people.person();
44. ESM modules in NodeJS
• https://github.com/nodejs/node-eps/blob/master/002-es-
modules.md
• Implement interoperability for EcmaScript 6 modules (ESM) and
Node’s existing module system (CJS)
• Allow a common module syntax for Browser (ES6 spec) and Server
side
45. EF modules vs NodeJS modules
• CommonJS is a dynamic loader modules system
• Synchronous
• Evaluated during runtime
• ES is a static loader modules system
• Asynchronous
• Evaluated during parse time
46. Example
console.log('entry eval');
require('middle');
console.log('entry done);
export {};
console.log('middle eval');
require('right');
console.log('middle done');
entry eval
middle eval
right eval
right done
middle done
entry done
export {};
console.log('right eval');
console.log('right done');
entry eval
entry done
middle eval
middle done
right eval
right done
sync async
47. What Node wants to :
Node wants to be able to :
• Import a CJS module from ES (import from 'commonjs-module’ )
• Import a ESM module from CJS (require('es6-module’))
48. ESM vs CJS. Solutions evaluated ?
• Does Node.js want to ship a synchronous or asynchronous module
loader?
• Returning a promise (async)
• Returning an object (sync)
• Both ?
• Multiple Solutions investigated:
• Use CJS (require) for actuals .js files / Use ESM (import) with a newly file .mjs
• Use a double parsing time
• Config file
• Obiwan Kenobi
49.
50. Detectiong CJS / ES Modules
• https://github.com/nodejs/node/wiki/ES6-Module-Detection-in-Node
• https://github.com/dherman/defense-of-dot-js/blob/master/proposal.md
52. Michael Jackson Script
• Code compiler must know if it’s a CJS or ES module
• In certain circumstance an import * from ‘foo’ could be a
CJS module or an ES module (same syntax !)
• Node.js will need to have some kind of mechanism for
identifying in advance what kind of file is being loaded
• foo.js will treat foo.js as CommonJS
• bar.mjs will treat bar.mjs as an ESM Module.
console.log(`Module load ${Date()}`)
53. Or ..
Changing ES Modules spec in ECMASCRIPT :
• A module allways requires an import or an export
• All modules are parsed. If it doesn't contain any of these statements,
it is not an ES Module.
54. Or …
Would be recognized as a CommonJS module, while
Would be an ES module.
console.log(`Module load ${Date()}`)
console.log(`Module load ${Date()}`)
export{}
55. But…
•It works within Babel / Typescript !!
•Under the hood, it’s just a
transpilation to CJS Modules
56. Timeline
• At the current point in time, there are still a number of specification
and implementation issues that need to happen on the ES6 and
Virtual Machine side of things before Node.js can even begin working
up a supportable implementation of ES6 modules. Work is in progress
but it is going to take some time —
We’re currently looking at around a year at least.
• Node V10 « around October 2018 »
https://github.com/nodejs/Release
57. ES6 : Modules (ESM)
• TypeScript : Transpiling ESM Syntax in CommonJS modules
• Node.js 9+ : Implementation with flags
import {Person} from "./People";
import {Person, Material as M} from "./People";
import * as People from "./People";
import guy from './People';
Quand vous compilez du TypeScript, vous transformez votre code en JavaScript. Comme TypeScript est trés proche de JavaScript (ES6+), vous pouvez dire que vous Transpillez.
Démo :
Créer un nouveau projet TS avec Node
Montrer l’intelissense
Monter comment créer un server express rapidement
npm install express
npm install @types/express
import * as express from 'express';
var app = express();
app.use("/", (req, res) => {
res.send("Hello World");
});
app.listen(3000);
Créer une classe Person pour montrer le passage de E5, ES6 dans TS
export class Person{
firstName:string;
lastName:string;
constructor(fn:string, ln:string, public age=27){
this.firstName = fn;
this.lastName = ln;
}
getFullName(){
return `Full name : ${this.firstName} ${this.lastName} ${this.age} `
}
}
Montrer comment on lance VS Code avec TS pour l’expérience de débuggage
import fetch from 'node-fetch’;
// Demo 1 créer un waiter à partir d'une promise
async function wait(delay:number){
return new Promise((rs, rj) => {
setTimeout(rs, delay);
});
}
// Démo : Ajouter node-fecth
app.use("/", async (req, res) => {
fetch('http://www.google.com').then((v) => {
let responseText =
`Hello ${p.getFullName()}<br />
${v.statusText}
`;
res.send(responseText);
});
})
Lancer nvs et lancer chakra core
Ajouter dans le rendu de la page
[${process.execPath}]
import * as util from "util";
declare module 'util' {
export function promisify(fn: Function): (...args: any[]) => Promise<any>;
}
function breeze(a: number, callback: (err: any, value?: number) => void) {
if (a > 10) {
callback(undefined, a * a);
} else {
callback("a must be greater than 10");
}
}
const breezeAsync = util.promisify(breeze);
export class Person {
firstName: string;
lastName: string;
constructor(fn: string, ln: string, public age = 27) {
this.firstName = fn;
this.lastName = ln;
}
getFullName() {
return `Full name : ${this.firstName} ${this.lastName} ${this.age} `
}
}
export class Kid {
}
export class adzdazddadadzad {
}
export class people {
kid = () => new Kid();
person = (fn, ln, age) => new Person(fn, ln, age);
az = () => new Kid()
}
var pp = new people();
export default pp;
export class Person {
constructor(fn, ln, age = 27) {
this.firstName = fn;
this.lastName = ln;
this.age = age;
}
getFullName() {
return `Full name : ${this.firstName} ${this.lastName} ${this.age} `
}
}
export class Kid {
}
export class adzdazddadadzad {
}
export class people {
person(fn, ln, age) {
return new Person(fn, ln, age)
}
kid() {
return new Kid()
}
ad() {
return new adzdazddadadzad();
}
}
var pp = new people();
export default pp;