Babel & WebPack

WebPack

is a JavaScript compiler

Use next generation JavaScript, today.

ES2015 and beyond

class Foo {
  a = 123;
  
  bar() {
    console.log('Foo.bar');
  }
  
  static b = 456;
  static blam() {
    console.log('static Foo.blam')
  }
}

let foo = new Foo();
foo.bar();
Foo.blam();
'use strict';

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var Foo = function () {
  function Foo() {
    _classCallCheck(this, Foo);

    this.a = 123;
  }

  _createClass(Foo, [{
    key: 'bar',
    value: function bar() {
      console.log('Foo.bar');
    }
  }], [{
    key: 'blam',
    value: function blam() {
      console.log('static Foo.blam');
    }
  }]);

  return Foo;
}();

Foo.b = 456;


var foo = new Foo();
foo.bar();
Foo.blam();

ES2015 and beyond

async function get() {
  let people = await $.get("http://services.odata.org/V4/TripPinServiceRW/People");
  let address = [];
  
  for (var p of people.value) {
    let a = await $.get(p['@odata.id']);
    //console.log(a.AddressInfo[0]);
    if (a.AddressInfo.length > 0) {
      address.push(a.AddressInfo[0].Address);
    }
  }
  return address;
}

get().then(function(r) {
  console.log(r);
})
"use strict";

var get = function () {
  var _ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee() {
    var people, address, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, p, a;

    return regeneratorRuntime.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            _context.next = 2;
            return $.get("http://services.odata.org/V4/TripPinServiceRW/People");

          case 2:
            people = _context.sent;
            address = [];
            _iteratorNormalCompletion = true;
            _didIteratorError = false;
            _iteratorError = undefined;
            _context.prev = 7;
            _iterator = people.value[Symbol.iterator]();

          case 9:
            if (_iteratorNormalCompletion = (_step = _iterator.next()).done) {
              _context.next = 18;
              break;
            }

            p = _step.value;
            _context.next = 13;
            return $.get(p['@odata.id']);

          case 13:
            a = _context.sent;

            //console.log(a.AddressInfo[0]);
            if (a.AddressInfo.length > 0) {
              address.push(a.AddressInfo[0].Address);
            }

          case 15:
            _iteratorNormalCompletion = true;
            _context.next = 9;
            break;

          case 18:
            _context.next = 24;
            break;

          case 20:
            _context.prev = 20;
            _context.t0 = _context["catch"](7);
            _didIteratorError = true;
            _iteratorError = _context.t0;

          case 24:
            _context.prev = 24;
            _context.prev = 25;

            if (!_iteratorNormalCompletion && _iterator.return) {
              _iterator.return();
            }

          case 27:
            _context.prev = 27;

            if (!_didIteratorError) {
              _context.next = 30;
              break;
            }

            throw _iteratorError;

          case 30:
            return _context.finish(27);

          case 31:
            return _context.finish(24);

          case 32:
            return _context.abrupt("return", address);

          case 33:
          case "end":
            return _context.stop();
        }
      }
    }, _callee, this, [[7, 20, 24, 32], [25,, 27, 31]]);
  }));

  return function get() {
    return _ref.apply(this, arguments);
  };
}();

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

get().then(function (r) {
  console.log(r);
});

React JSX

class Foo extends Component {
  render() {
    return (
      <div className='my'>Hello world</div>
    );
  }
}
'use strict';

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var Foo = function (_Component) {
  _inherits(Foo, _Component);

  function Foo() {
    _classCallCheck(this, Foo);

    return _possibleConstructorReturn(this, _Component.apply(this, arguments));
  }

  Foo.prototype.render = function render() {
    return React.createElement(
      'div',
      { className: 'my' },
      'Hello world'
    );
  };

  return Foo;
}(Component);

Babel Polyfill

npm install --save babel-polyfill

Install babel-polyfill

How to use

Install & Run

# install babel and necessary presets
npm init -f && \
npm install --save-dev \
            babel-cli \
            babel-preset-env && \
\
# create .babelrc file
echo '{ 
  "presets": ["env"]
}' > .babelrc && \
\
# create test.js
echo 'function * test() {
    yield 1;
    yield 2;
    yield 3;
}' > test.js && \
\
# run babel to compiler test.js
./node_modules/.bin/babel test.js
// Output
"use strict";

var _marked = [test].map(regeneratorRuntime.mark);

function test() {
    return regeneratorRuntime.wrap(function test$(_context) {
        while (1) {
            switch (_context.prev = _context.next) {
                case 0:
                    _context.next = 2;
                    return 1;

                case 2:
                    _context.next = 4;
                    return 2;

                case 4:
                    _context.next = 6;
                    return 3;

                case 6:
                case "end":
                    return _context.stop();
            }
        }
    }, _marked[0], this);
}

Configuration

// via .babelrc
{
  "comments": false,
  "minified": true,
  "presets": [
    "latest",
    "flow",
    "react"
  ],
  "plugins": [
    ["transform-es2015-modules-umd", {
      "exactGlobals": true,
      "globals": {
        "p2m/logger": "p2m.logger"
      }
    }],
    "dotenv"
  ],
  "moduleId": "p2m/logger"
}
// via package.json
{
  "name": "p2m-logger",
  "version": "1.0.0",
  "main": "logger.js",
  "babelrc": {
    "comments": false,
    "minified": true,
    "presets": [
      "latest",
      "flow",
      "react"
    ],
    "plugins": [
      ["transform-es2015-modules-umd", {
        "exactGlobals": true,
        "globals": {
          "p2m/logger": "p2m.logger"
        }
      }],
      "dotenv"
    ],
    "moduleId": "p2m/logger"
  }
}

Doc

Preset & Plugin

#! bin/bash
# install babel and presets
npm init -f && \
npm install --save-dev \
            babel-preset-env \
            babel-preset-flow \
            babel-plugin-transform-es2015-modules-umd && \
\
# create .babelrc file
echo '{ 
  "presets": ["env", "flow"],
  "plugins": ["transform-es2015-modules-umd"]
}' > .babelrc && \
\
# create test.js
echo '// @flow
function * test(v: number): Iterator<number> {
  for (let i = 0; i < v; i++) {
    yield i;
  }
}
test("abc");
export default test' > test.js && \
\
# init flow config
./node_modules/.bin/flow init && \
\
# run babel with flow to compiler test.js
./node_modules/.bin/babel test.js && \
\
# run flow for static type checking
./node_modules/.bin/flow
// Output from babel
(function (global, factory) {
  if (typeof define === "function" && define.amd) {
    define(["exports"], factory);
  } else if (typeof exports !== "undefined") {
    factory(exports);
  } else {
    var mod = {
      exports: {}
    };
    factory(mod.exports);
    global.test = mod.exports;
  }
})(this, function (exports) {
  "use strict";

  var _marked = [test].map(regeneratorRuntime.mark);

  function test(v) {
    return ...; // generated function content, just same with above example.
  }

  // @flow
  test("abc");
  exports.default = test;
});

// Output from flow
test.js:7
  7: test("abc");
          ^^^^^ string. This type is incompatible with the expected param type of
  2: function * test(v: number): Iterator<number> {
                        ^^^^^^ number

Found 1 errors

Doc

import bar from './bar';

bar();
/******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/          ...
/******/        }
/******/        ...
/******/        ...
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = bar;
function bar() {
  //
}


/***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__bar__ = __webpack_require__(0);


__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__bar__["a" /* default */])();


/***/ })
/******/ ]);

Package all in one

app.js

export default function bar() {
  //
}

bar.js

bundle.js

module.exports = {
  entry: './app.js',
  output: {
    filename: 'bundle.js'
  }
}

webpack.config.js

npm install -g webpack
webpack

shell

import './main.css';
import bar from './bar';

bar();
/* 2 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__main_css__ = __webpack_require__(1);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__main_css___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0__main_css__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__bar__ = __webpack_require__(0);



__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_1__bar__["a" /* default */])();


/***/ }),
/* 3 */
/***/ (function(module, exports, __webpack_require__) {

exports = module.exports = __webpack_require__(4)(undefined);
// imports


// module
exports.push([module.i, "._1tT8zerOsEqGcq4YV1s2cI {\n  background-color: 'red';\n}\n", ""]);

// exports
exports.locals = {
	"test": "_1tT8zerOsEqGcq4YV1s2cI"
};

/***/ }),

Package css

app.js

.test {
  background-color: 'red';
}

main.css

bundle.js

module.exports = {
  entry: './app.js',
  output: {filename: 'bundle.js'},
  module: {
    rules: [{
      test: /\.css$/,
      use: [
        'style-loader',
        'css-loader?modules'
      ]
    }]
  }
}

webpack.config.js

import s from './main.css';
import s2 from 'style-loader!css-loader?modules!less-loader!./another.less';
import log from './log.svg';

Loader

app.js

webpack --module-bind 'svg=url-loader'

shell

module.exports = {
  entry: './app.js',
  output: {filename: 'bundle.js'},
  module: {
    rules: [{
      test: /\.css$/,
      use: [
        'style-loader',
        // 'css-loader?modules',
        {
            loader: 'css-loader',
            options: { modules: true }
        }
      ]
    }]
  }
}

webpack.config.js

Thanks

For your time

WebPack

Babel & WebPack

By Colin Han

Babel & WebPack

Introduce web development tools babel and webpack.

  • 964