MODERN
WEB APPS
THE ESSENTIALS
> node
> var x = { a: 5 };
undefined
> console.log(x.a)
5
undefined
> x.b = function(){...}
[Function]
> x.c("Hello!")
TypeError: undefined is not a function
var greets = ['World!', 'Kitty', ', Its Me'];
greets.forEach(function hello(greet) {
console.log('Hello' + greet);
});
> node hello.js
Hello World!
Hello Kitty
Hello, It's Me
var fs = require('fs');
fs.readFile('myFile.txt', function(err, result){
console.log(result);
});
> node fileReader.js
Lorem Ipsum Dolor
Sit Amet Hodor.
Hodor hodor hodor,
hodor.
var hulkStatus = require('./hulk.js');
var ironMan = require('./ironMan.js');
console.log('Hulk is ' + hulkStatus);
console.log(ironMan.name() + ' is Iron Man');
> node avengers.js
Hulk is MAD
Tony Stark is Iron Man
var radiation = 10000;
module.exports = 'MAD'
function getName() {
return 'Tony Stark';
}
exports.name = getName;
exports.age = 48;
Module Systems
CommonJS
var moduleA = require('./fileA.js');
console.log(moduleA.name());
if(moduleA.size) {
var moduleB = require('./fileB.js');
console.log(moduleB);
}
exports.name = function(){...}
exports.size = 10;
var moduleC = require('./fileC.js')
module.exports = ...;
Module Systems
AMD
require(['./moduleA'], function(moduleA){
console.log(moduleA.name());
if(moduleA.size){
require(['./moduleB'], function(moduleB){
console.log(moduleB);
})
}
})
define('moduleA', [], function(){
return {...}
});
define('moduleB', ['moduleC'], function(){
return ...
});
PACKAGE
MANAGER
> node -v
v8.5.0
> npm -v
v5.3.0
{
"name": "my-package",
"version": "1.0.0",
"author": "Liad",
"scripts": {},
"main": "avengers.js",
"dependencies": {},
"devDependencies": {}
}
avengers.js
hulk.js
ironman.js
package.json
{ }
{
"name": "my-package",
"version": 1.0.0,
"description": "A Cool Package",
"author": "Liad Yosef",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/liady/my_package.git"
},
"keywords": [],
"main": "index.js"
}
{
"name": "my-package",
"version": 1.0.0,
"description": "A Cool Package",
"author": "Liad Yosef",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/liady/my_package.git"
},
"keywords": [],
"main": "index.js"
}
$ npm install {package}
node_modules
avengers.js
lodash
marvel
lodash
marvel
my-package
hulk.js
avengers.js
hulk.js
leftpad
.
.
.
$ npm install {package}
MY CODE
NPM
var moduleA = require('./moduleA');
var moduleB = require('./subFolder/moduleB');
var lodash = require('lodash');
var express = require('express');
var moduleA = require('./moduleA');
var moduleB = require('./subFolder/moduleB');
var lodash = require('node_modules/lodash');
var express = require('node_modules/express');
node_modules
lodash
marvel
marvel
leftpad
my-package
express
galaxy
leftpad
express
galaxy
$ npm install {package} --save
$ npm install {package} --save-dev
{
"name": "avengers",
"version": 1.0.0,
"description": "Better than DC",
"author": "Liad Yosef",
"license": "MIT",
"dependencies": {
"lodash": "^3.2.1",
"marvel": "^4.4.1"
},
"devDependencies": {
"webpack": "3.2.4"
}
}
{
"name": "avengers",
"version": 1.0.0,
"description": "Better than DC",
"author": "Liad Yosef",
"license": "MIT"
}
{
"name": "avengers",
"version": 1.0.0,
"description": "Better than DC",
"author": "Liad Yosef",
"license": "MIT",
"dependencies": {
"lodash": "^3.2.1",
"marvel": "^4.4.1"
}
}
$ npm install
3.9.x
Update only with bug fixes
3.x.x
Update with bug fixes, API additions, any non-breaking changes
"lodash": "~3.9.0"
"lodash": "^3.9.0"
Tilde ~
Caret ^
{
"name": "avengers",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
},
"ansi-styles": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
},
"asn1": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
},
"assert-plus": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
"integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ="
},
"async": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz",
"integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==",
"requires": {
"lodash": "4.17.4"
}
},
{
"name": "chalk",
"version": "2.3.0",
"description": "Terminal string styling done right",
"main": "./index.js",
"scripts": {
"build": "node ./build.js",
"test": "mocha *.test.js"
},
"dependencies": {
"lodash": "^4.17.4",
"console": "^1.1.0"
},
"devDependencies": {
"mocha": "^3.1.10"
},
"keywords": [ "Chalk", "Log", "Cool" ],
"author": "sindresorhus",
"license": "MIT",
"bugs": {
"url": "https://github.com/chalk/chalk/issues"
},
"homepage": "https://github.com/chalk/chalk#readme"
}
$ npm run {scriptName}
{
"name": "chalk",
"version": "2.3.0",
"description": "Terminal string styling done right",
"main": "./index.js",
"scripts": {
"build": "node ./build.js",
"test": "mocha *.test.js"
},
"dependencies": {
"lodash": "^4.17.4",
"console": "^1.1.0"
},
"devDependencies": {
"mocha": "^3.1.10"
},
"keywords": [ "Chalk", "Log", "Cool" ],
"author": "sindresorhus",
"license": "MIT",
"bugs": {
"url": "https://github.com/chalk/chalk/issues"
},
"homepage": "https://github.com/chalk/chalk#readme"
}
$ npm run {scriptName}
// auto-bind
::console.log = console.log.bind(console)
// partial application
const addOne = add(1, ?);
addOne(2); // 3
// decorators
@logged
class Element {...}
// private fields
class Element {
#x = 5
getNum() { return this.#x }
}
ES5
ES6
ES2015
ES2016
ES2017
ES2018
ES7
Object.create
JSON
Modules
Classes
Arrow Functions
Proxies
Generators
Exponent
Async / Await
Object.entries
?
ES8
The best import and export since Pablo
ES6 MODULES
import { name, size } from './moduleA';
import moduleB from './moduleB';
console.log(name());
if(size){
console.log(moduleB);
}
export const name = function(){}
export const size = ...
export default const x = 5;
ES6 MODULES
import { name } from './moduleA';
function run() {
console.log(name);
}
import moduleB from './moduleB';
export name = 'Deadpool';
var name = require('./moduleA').name;
function run() {
console.log(name);
}
var moduleB = require('./moduleB');
exports.name = 'Deadpool';
Module Systems
CommonJS
AMD
ES6
Synchronous
Cyclic deps.
Immutable
On demand
Reference based
Default/named
ES2015
STAGE-0
stage-0
es2015
jsx
modules
import { AVENGERS } from './Consts' ;
class Avenger {
constructor (type, power) {
this.type = type;
this.power = power || 'Nothing';
this.groups = {
[AVENGERS]: true
}
}
reportPower() {
console.log(`I can do ${this.power} !`);
}
}
const thor = new Avenger('God', 'A Thunder');
thor.reportPower();
var _Consts = require('./Consts');
var Avenger = function () {
function Avenger(type, power) {
var _groups;
this.type = type;
this.power = power || 'Nothing';
this.groups = (_groups = {}, _groups[_Consts.AVENGERS] = true, _groups);
}
Avenger.prototype.reportPower = function reportPower() {
console.log('I can do ' + this.power + ' !');
};
return Avenger;
}();
var thor = new Avenger('God', 'A Thunder');
thor.reportPower();
class Avenger {
constructor (type, power) {
this.type = type;
this.power = power || 'Nothing';
this.groups = {
[AVENGERS]: true
}
}
reportPower() {
console.log(`I can do ${this.power} !`);
}
}
const thor = new Avenger('God', 'A Thunder');
thor.reportPower();
var Avenger = function () {
function Avenger(type, power) {
var _groups;
this.type = type;
this.power = power || 'Nothing';
this.groups = (_groups = {}, _groups[AVENGERS] = true, _groups);
}
Avenger.prototype.reportPower = function reportPower() {
console.log('I can do ' + this.power + ' !');
};
return Avenger;
}();
var thor = new Avenger('God', 'A Thunder');
thor.reportPower();
class Avenger {
constructor (type, power) {
this.type = type;
this.power = power || 'Nothing';
this.groups = {
[AVENGERS]: true
}
}
reportPower() {
console.log(`I can do ${this.power} !`);
}
}
const thor = new Avenger('God', 'A Thunder');
thor.reportPower();
var Avenger = function () {
function Avenger(type, power) {
var _groups;
this.type = type;
this.power = power || 'Nothing';
this.groups = (_groups = {}, _groups[AVENGERS] = true, _groups);
}
Avenger.prototype.reportPower = function reportPower() {
console.log('I can do ' + this.power + ' !');
};
return Avenger;
}();
var thor = new Avenger('God', 'A Thunder');
thor.reportPower();
var a = 3;
a + 5
var bar = [1, 2, 3]
var foo = { bar: 1 }
const x = new Hero("Hulk", [1, 2, 3]);
[1, 2, 3]
utils.vector("1", "2", "3")
USING
$ npm install --save-dev babel-cli
$ npm install --save-dev babel-preset-env ...
{
"plugins": ["decorators"],
"presets": [
"react",
"stage-0",
// automatically select the plugins
["env", {
"targets": {
"browsers": ["last 2 versions", "safari >= 7"]
}
}]
]
}
$ npm install --save-dev babel-plugin-decorators ...
{
"scripts": {
"build": "babel src --out-dir dist"
}
}
$ npm run build
source
dist
where our actual coding takes place
the code that can actually run
{
"main": "dist/avengers.js"
}
<html>
<head>
<script src="/editor/ed/src/common/ed._prototypeExtensions.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/ed.common.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/ed.convertUtils.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/modules/ed.module.batchRequests.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/modules/ed.module.events.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/modules/ed.module.cache.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/modules/ed.module.cookies.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/modules/ed.module.lockables.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/modules/ed.module.locks.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/modules/ed.module.performance.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/modules/ed.module.spotlight.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/modules/ed.module.storage.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/modules/ed.module.widgetEditor.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/ed.dmAjaxUtils.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/ed.dmx.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/ed.editableUtils.js?version=2017-12-19T13_03_41" ></script>
<script src="/editor/ed/src/common/ed.layoutNavigationUtils.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/ed.measureUtils.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/ed.stacktraceUtils.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/ed.cssUtils.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/ed.spinner.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/ed.editorColors.js?version=2017-12-19T13_03_41"></script>
<script src="/editor/ed/src/common/framework/ed.super.fw.js?version=2017-12-19T13_03_41"></script>
import ironMan from './ironMan.js';
import hulk from './hulk.js';
console.log('Got Them');
var styles = require('./styles.scss');
if(Math.random()) {
var _ = require('lodash');
_.find('Tony Stark');
}
import ironMan from './ironMan.js';
import hulk from './hulk.js';
console.log('Got Them');
var utils = require('./utils.js');
utils.smash();
.captain-america {
display: none;
}
var styles = require('./styles.scss');
if(Math.random()) {
var _ = require('lodash');
_.find('Tony Stark');
}
var utils = require('./utils.js');
utils.smash();
import ironMan from './ironMan.js';
import hulk from './hulk.js';
console.log('Got Them');
exports.smash = function() {😤}
exports.sick = function() {🤢}
exports.angry = function() {😡}
.captain-america {
display: none;
}
var styles = require('./styles.scss');
if(Math.random()) {
var _ = require('lodash');
_.find('Tony Stark');
}
var utils = require('./utils.js');
utils.smash();
import ironMan from './ironMan.js';
import hulk from './hulk.js';
console.log('Got Them');
exports.smash = function() {😤}
exports.sick = function() {🤢}
exports.angry = function() {😡}
.captain-america {
display: none;
}
var styles = require('./styles.scss');
if(Math.random()) {
var _ = require('lodash');
_.find('Tony Stark');
}
var utils = require('./utils.js');
utils.smash();
import ironMan from './ironMan.js';
import hulk from './hulk.js';
console.log('Got Them');
exports.smash = function() {😤}
exports.sick = function() {🤢}
exports.angry = function() {😡}
.captain-america {
display: none;
}
var styles = require('./styles.scss');
if(Math.random()) {
var _ = require('lodash');
_.find('Tony Stark');
}
var utils = require('./utils.js');
utils.smash();
import ironMan from './ironMan.js';
import hulk from './hulk.js';
console.log('Got Them');
exports.smash = function() {😤}
exports.sick = function() {🤢}
exports.angry = function() {😡}
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
var ironMan = __webpack_require__(1);
var hulk = __webpack_require__(2);
/***/ }),
/* 1 */
/***/ (function(module, exports) {
if(Math.random()) {
var _ = {};
_.find('Tony Stark');
}
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
var utils = __webpack_require__(3);
utils.smash();
/***/ }),
/* 3 */
/***/ (function(module, exports) {
exports.smash = function() {}
exports.sick = function() {}
exports.angry = function() {}
/***/ })
/******/ ]);
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
var ironMan = __webpack_require__(1);
var hulk = __webpack_require__(2);
/***/ }),
/* 1 */
/***/ (function(module, exports) {
if(Math.random()) {
var _ = {};
_.find('Tony Stark');
}
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
var utils = __webpack_require__(3);
utils.smash();
/***/ }),
/* 3 */
/***/ (function(module, exports) {
exports.smash = function() {}
exports.sick = function() {}
exports.angry = function() {}
/***/ })
/******/ ]);
<html>
<head>
<script src="public/bundle.js"></script>
...
</head>
</html>
module.exports = {
entry: './avengers.js',
output: {
path: 'dist',
filename: 'bundle.js'
}
};
import Icon from './Icon.jsx';
...
.scene {
background: url("./all.png");
}
styles = require('./styles.scss');
...
return (
<Button>{styles.name}</Button>
)
.scss
.css
.js
.jsx
.js
.png
.js
.png
Icon.jsx
styles.scss
all.png
.js
.png
dist
module.exports = {
entry: './avengers.js',
output: {
path: 'public',
filename: 'bundle.js'
},
module: {
rules: [
{ test: /\.js$/, use: ['eslint-loader'] },
{ test: /\.jsx$/, use: ['babel-loader'] },
{ test: /\.png$/, use: [ 'url-loader'] },
{ test: /\.css$/, use: [ 'style-loader', 'css-loader'] }
]
}
};
Asset
Size
bundle.js
15.7MB
// will be bundled in THIS CHUNK
import ironMan from './ironMan.js';
// will be bundled in THIS CHUNK
const spiderman = require('./spiderman.js');
// will create a NEW SPLIT POINT - new async chunk
const hulk = await import('./hulk.js');
import { Apps } from 'consts';
export default function(appName) {
switch(appName) {
case Apps.DESIGN_EDITOR:
return import('apps/designEditor?chunkName=designEditor');
case Apps.CONTENT_EDITOR:
return import('apps/contentEditor?chunkName=contentEditor');
case Apps.MOBILE_CONTENT_EDITOR:
return import('apps/mobileContentEditor?chunkName=mobileContentEditor');
case Apps.SHELL:
return import('apps/shell?chunkName=shell');
default:
return Promise.reject(`The app loader does not have a handler defined for app ${appName}`);
}
}
module.exports = {
entry: './avengers.js',
output: {
path: 'public',
filename: 'bundle.js'
},
module: {
rules: [
{ test: /\.js$/, use: ['eslint-loader'] },
{ test: /\.jsx$/, use: ['babel-loader'] },
{ test: /\.png$/, use: [ 'url-loader'] },
{ test: /\.css$/, use: [ 'style-loader', 'css-loader'] }
]
},
plugins: [new UglifyPlugin()],
resolve: {
alias: {
"home": "./src/index.js"
}
}
};
$ npm install --save-dev webpack
$ npm install --save-dev babel-loader ...
{
"scripts": {
"build": "webpack",
"watch": "webpack --watch"
}
}
$ npm install --save-dev plugin-uglify ..
QUESTIONS?