JavaScript technologies

Tools in modern web development

Horváth, Győző
senior lecturer
horvath.gyozo@inf.elte.hu

Financed from the financial support ELTE won from the Higher Education Restructuring Fund of the Hungarian Government

Table of content

  • npm
  • nvm
  • live-server
  • Babel
  • Sandboxes
  • bower
  • Module loaders
  • Webpack for React
  • Redux with webpack
  • Tools for node.js

npm

npm

A package manager for JavaScript.

Based on node.js

Install node.js and you will have npm too.

Installing a package:

npm install <package_name>
npm install -g <package_name>

nvm

nvm

Node Version Manager

In Linux:

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.29.0/install.sh | bash

VAGY

wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.29.0/install.sh | bash

nvm ls
nvm ls-remote
nvm install <version>
nvm use <version>

Live-server

Live-server

A little development server with live reload capability.

Good for development

Saving the source the browser automatically reloads the content.

npm install -g live-server
live-server

Babel

Babel

An ES6 to ES5 transpiler.

You can write ES6 code for ES5 environments (until ES6 is fully supported in all browsers and environments).

Setups

Installing and using on the command-line

npm install --save-dev babel-cli
npm install babel-preset-es2015 --save-dev

echo '{ "presets": ["es2015"] }' > .babelrc

./node_modules/.bin/babel script.js --out-file script-compiled.js
./node_modules/.bin/babel-node script.js

JavaScript sandboxes

Sandboxes

jsbin

  • Add library: jQuery, Backbone
  • (HTML, ) JavaScript, Console panels

jsFiddle

Managing client-side dependencies

Client-side dependencies

  • Browser
  • JavaScript files
  • CSS files
  • Images
  • Static contents

Managing client-side dependencies

Bower

  • Package manager for client-side dependencies
  • npm install bower -g
  • bower command
  • bower install packagename
  • bower init --> bower.json (project definition file)
  • .bowerrc (configuration)
{
    "directory": "lib/"
}

In labs

  • put git in the PATH (C:\Program Files\Git\bin)
  • git config --global url."https://".insteadOf git://

Usage example

Instead of a CDN use bower to install Bootstrap, jQuery and Underscore for a project!

  1. Install bower
  2. Set up .bowerrc
  3. bower init
  4. bower install --save bootstrap jquery underscore

Using modules

Module formats

  • Module pattern (Crockford)
  • AMD
  • CommonJS
  • UMD
  • ES6 modules

Module loaders

  • (Namespaces)
  • RequireJS
  • browserify
  • Webpack
  • SystemJS (JSPM)

Operations

  • Explore dependencies between modules
  • Loading dependencies
  • Bundling

Browserify

browserify main.js -o bundle.js

ES6: babelify

browserify js/app.js -t babelify -o dist/bundle.js

Gulp

npm install -g gulp

gulpfile.js

Project dependencies

package.json

{
  "devDependencies": {
    "babelify": "^6.3.0",
    "browserify": "^11.2.0",
    "gulp": "^3.9.0",
    "gulp-sourcemaps": "^1.6.0",
    "vinyl-buffer": "^1.0.0",
    "vinyl-source-stream": "^1.1.0",
    "watchify": "^3.4.0"
  },
  "dependencies": {
    "backbone": "^1.2.3",
    "backbone.marionette": "^2.4.3",
    "jquery": "^2.1.4",
    "underscore": "^1.8.3"
  }
}

Gulp configuration

gulpfile.js

var gulp = require('gulp');
var sourcemaps = require('gulp-sourcemaps');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var browserify = require('browserify');
var watchify = require('watchify');
var babel = require('babelify');

function compile(watch) {
  var bundler = browserify('./js/main.js', { debug: true }).transform(babel);
  if (watch) {
    bundler = watchify(bundler);
  }

  function rebundle() {
    bundler.bundle()
      .on('error', function(err) { console.error(err); this.emit('end'); })
      .pipe(source('bundle.js'))
      .pipe(buffer())
      .pipe(sourcemaps.init({ loadMaps: true }))
      .pipe(sourcemaps.write('./'))
      .pipe(gulp.dest('./dist'));
  }

  if (watch) {
    bundler.on('update', function() {
      console.log('-> bundling...');
      rebundle();
    });
  }

  rebundle();
}

function watch() {
  return compile(true);
};

gulp.task('build', function() { return compile(); });
gulp.task('watch', function() { return watch(); });

gulp.task('default', ['watch']);

Application directory structure

  • dist folder: serving root for the client
    • bundle.js
  • js folder: client-side source code
    • models/
    • views/
    • collections/
    • app.js
    • main.js

live-server --ignore=js

Setting up webpack for React

Webpack

Installation

npm install --save-dev webpack webpack-dev-server

Folder structure

/dist
/src
index.html
webpack.config

Webpack configuration

module.exports = {
  entry: [
    './src/main.js'
  ],
  output: {
    path: __dirname + '/dist',
    publicPath: '/',
    filename: 'bundle.js'
  },
  devServer: {
    contentBase: './'
  }
};

index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

    <title>React</title>

    <!-- Stylesheets -->
    <link rel="stylesheet" href="lib/bootstrap/dist/css/bootstrap.min.css">
    <link rel="stylesheet" href="css/app.css">
</head>
<body>
    <div id="container">

    </div>

    <script src="bundle.js"></script>
</body>
</html>

src

main.js

var negyzet = require('./mymath');

console.log(negyzet(2));

mymath.js

module.exports = function negyzet(x) {
    return x*x;
};

Bundle and dev-server

webpack
webpack-dev-server

ES6

npm install --save-dev babel-core babel-loader babel-preset-es2015

.babelrc

{
  "presets": ["es2015"]
}

Configuration

webpack.config.js

module.exports = {
  entry: [
    './src/main.js'
  ],
  module: {
    loaders: [{
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loader: 'babel'
    }]
  },
  resolve: {
    extensions: ['', '.js', '.jsx']
  },
  output: {
    path: __dirname + '/dist',
    publicPath: '/',
    filename: 'bundle.js'
  },
  devServer: {
    contentBase: './'
  }
};

src folder

main.js

import { negyzet } from './mymath';

console.log(negyzet(2));

mymath.js

export function negyzet(x) {
    return x*x;
};

React

npm install --save react react-dom

npm install --save-dev babel-preset-react

.babelrc

{
  "presets": ["es2015", "react"]
}

react-hot-loader

npm install --save-dev react-hot-loader
var webpack = require('webpack');

module.exports = {
  entry: [
    'webpack-dev-server/client?http://localhost:8080',
    'webpack/hot/only-dev-server',
    './src/main.js'
  ],
  module: {
    loaders: [{
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loaders: ['react-hot', 'babel'],
    }]
  },
  resolve: {
    extensions: ['', '.js', '.jsx']
  },
  output: {
    path: __dirname + '/dist',
    publicPath: '/',
    filename: 'bundle.js'
  },
  devServer: {
    contentBase: './',
    hot: true
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ]
};

Setting up Redux with webpack and React

Installing redux

npm install --save redux react-redux

How to try the redux store

// Log the initial state
console.log(store.getState())

// Every time the state changes, log it
let unsubscribe = store.subscribe(() =>
  console.log(store.getState())
)

// Dispatch some actions
store.dispatch(addTodo('Learn about actions'))

// Stop listening to state updates
unsubscribe()

Redux devtools

npm install --save-dev redux-devtools
// Redux DevTools store enhancers
import { devTools, persistState } from 'redux-devtools';
// React components for Redux DevTools
import { DevTools, DebugPanel, LogMonitor } from 'redux-devtools/lib/react';

const finalCreateStore = compose(
  // Provides support for DevTools:
  devTools(),
  // Lets you write ?debug_session=<name> in address bar to persist debug sessions
  persistState(window.location.href.match(/[?&]debug_session=([^&]+)\b/))
)(createStore);

let store = finalCreateStore(reducer);

ReactDOM.render(
  <div>
      <Provider store={store}>
        <App />
      </Provider>
      <DebugPanel top right bottom>
        <DevTools store={store} monitor={LogMonitor} />
      </DebugPanel>
  </div>,
  document.getElementById('container')
);

Tools for node.js

Restart on change

Serving static content

npm install http-server -g

http-server

Generate an express application

Express-generator

npm install -g express-generator

express -h

express myapp