JavaScript OOP Course 8: ES6 Tooling

From WikiMLT
Revision as of 10:07, 18 June 2022 by Spas (talk | contribs) (Стадий: 6 [Фаза:Утвърждаване, Статус:Утвърден]; Категория:JavaScript)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Ref­er­ences

ES6 Tool­ing

When we are us­ing mod­ern JavaScript wee need two kinds of tools:

  • Tran­spiler = Trans­la­tor + Com­pil­er – it takes the mod­ern JavaScript code (ES6+) and con­vert it to a JavaScript code that all browsers can un­der­stand (ES5). Ba­bel is an ex­am­ple for such tool.
  • Bundler - is a tool that com­bines all .js files in­to one .js file which we called a bun­dle, it al­so mini­fy the code by elim­i­nat­ing the white­space the com­ments and so on, and fi­nal­ly ugli­fy the code which means it cre­ates short names for the vari­ables, func­tions class­es, iden­ti­fiers, etc. Web­pack is the most pop­u­lar bundler.

If we are us­ing JavaScript in Node.js we don't have to wor­ry about these tools, be­cause the code is not sent via the net­work and we do need to com­press it for fast de­liv­ery or make it com­pat­i­ble with old browsers which doesn't sup­port ES6 code.

Ba­bel and Web­pack are avail­able via the Node.js pack­age man­ag­er – npm. The in­stal­la­tion and the ba­sic us­age of these tools are cov­ered by the last two lec­tures from the Mosh's course The Ul­ti­mate JavaScript Mas­tery Se­ries – Part 2.

In­stall Node.js and NPM

Ba­bel and Web­pack are avail­able at Node.js pack­age man­ag­er – npm. The fol­low­ing ex­am­ples is cre­at­ed and start­ed with­in Ubun­tu on WSL on Win­dows 10.

sudo apt install nodejs && node -v
v10.19.0
sudo apt install npm && npm -v
6.14.4

Ba­bel the most pop­u­lar Tran­spiler

Once Node.js and NPM are avail­able cre­ate a home di­rec­to­ry for the project and go in­side.

mkdir -p ~/tmp/es6-tooling
mkdir -p ~/tmp/es6-tooling/build
cd ~/tmp/es6-tooling

Then in­stall the nec­es­sary Babel's pack­ages.

# npm i babel-cli@6.26.0 babel-core@6.26.0 babel-preset-env@1.6.1 --save-dev
npm i babel-cli babel-core babel-preset-env --save-dev

Cre­ate package.json.

npm init

Then mod­i­fy package.json in the fol­low­ing way.

{
  "name": "es6-tooling",
  "version": "1.0.0",
  "description": "Just test how Babel works",
  "main": "index.js",
  "dependencies": {},
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-core": "^6.26.3",
    "babel-preset-env": "^1.7.0"
  },
  "scripts": {
    "babel": "babel --presets env index.js -o build/index.js"
  },
  "author": "Spas Z. Spasov",
  "license": "ISC"
}

Then cre­ate index.js with re­al­ly sim­ple ES6 con­tent.

index.js
const x = 1;

Then run the ba­bel com­mand that we've de­fined in the package.json "script" sec­tion.

npm run babel

The out­put is the file build/index.js which is ES5 com­pat­i­ble ver­sion of index.js and looks like as fol­low.

build/index.js
"use strict";
var x = 1;

Web­pack the most pop­u­lar Bundler

Once Node.js and NPM are avail­able cre­ate a home di­rec­to­ry for the project and go in­side.

mkdir -p ~/tmp/es6-tooling
mkdir -p ~/tmp/es6-tooling/build
mkdir -p ~/tmp/es6-tooling/src
cd ~/tmp/es6-tooling

Al­so cre­ate the two mod­ules (from the pre­vi­ous sec­tion) index.js and circle.js and the main file index.html.

src/circle.js
const _radius = new WeakMap();
export default class Circle {
    constructor(radius) { _radius.set(this, radius); }
    draw() { console.log('Circle with radius ' + _radius.get(this)); }
}
src/index.js
import Circle from './circle.js';
const c = new Circle(10);
c.draw();
index.html  # note type="module" within the <script> tag
<!DOCTYPE html>
<html lang="en">
<head>
    <!-- head -->
</head>
<body>
    <!-- body -->
    <script type="module" src="src/index.js"></script>
</body>
</html>

Use npm and in­stall Web­pack CLI glob­al­ly (the op­tion -g) so we can ac­cess it in each project.

# npm i -g webpack-cli@2.0.14
sudo npm i -g webpack-cli peer

Now go in­to the project di­rec­to­ry and run the fol­low­ing com­mand to ini­tial­ize the project – it will au­to­mat­i­cal­ly in­stall ba­bel-cli and the oth­er nec­es­sary pack­ages.

webpack-cli init
[webpack-cli] For using this command you need to install: '@webpack-cli/generators' package.
[webpack-cli] Would you like to install '@webpack-cli/generators' package? (That will run 'npm install -D @webpack-cli/generators') (Y/n) y
webpack-cli init
? Which of the following JS solutions do you want to use? ES6
? Do you want to use webpack-dev-server? No
? Do you want to simplify the creation of HTML files for your bundle? No
? Do you want to add PWA support? No
? Which of the following CSS solutions do you want to use? none
? Do you like to install prettier to format generated configuration? Yes
[webpack-cli] ℹ INFO  Initialising project...
   create package.json
 conflict src/index.js
? Overwrite src/index.js? do not overwrite
     skip src/index.js
   create README.md
 conflict index.html
? Overwrite index.html? do not overwrite
     skip index.html
   create webpack.config.js
   create .babelrc
   
npm WARN my-webpack-project@1.0.0 No repository field.
npm WARN my-webpack-project@1.0.0 No license field.

+ prettier@2.5.1
+ webpack-cli@4.9.2
+ babel-loader@8.2.3
+ @babel/core@7.17.5
+ @babel/preset-env@7.16.11
+ webpack@5.69.1
added 218 packages from 111 contributors, removed 328 packages, updated 2 packages, moved 5 packages and audited 292 packages in 14.653s

17 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

[webpack-cli] Project has been initialised with webpack!

The re­sult­ing struc­ture of the above steps is shown at Video 1.

Video 1. The video shows the directory structure generated by the webpack-cli init command.
Video 1. The video shows the di­rec­to­ry struc­ture gen­er­at­ed by the web­pack-cli init com­mand.

Let's see how Web­pack works – go in­to the project home di­rec­to­ry and run the fol­low­ing com­mand.

npm run build

Af­ter the com­mand is fin­ished a new di­rec­to­ry called dist/​​​ is cre­at­ed and in­side is avail­able a the new bun­dle file called main.js.

dist/main.js
(()=>{"use strict";function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}var t=new WeakMap;new(function(){function n(e){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,n),t.set(this,e)}var r,a;return r=n,(a=[{key:"draw",value:function(){console.log("Circle with radius "+t.get(this))}}])&&e(r.prototype,a),Object.defineProperty(r,"prototype",{writable:!1}),n}())(10).draw()})();

Ed­it the rel­e­vant line of the file index.html in the fol­low­ing way, save it and see the re­sult in the browser's con­sole.

<script src="dist/main.js"></script>
# Result in the browser's console
Circle with radius 10           main.js:1

In or­der to force Web­pack to ap­ply our fur­ther changes au­to­mat­i­cal­ly we can run it in watch mode by the com­mand –watch. First mod­i­fy the watch com­mand with­in the script sec­tion of the package.json file in the fol­low­ing way.

{
  "...": "...",
  "scripts": {
    "build": "webpack --mode=production --node-env=production",
    "build:dev": "webpack --mode=development",
    "build:prod": "webpack --mode=production --node-env=production",
    "watch": "webpack --mode=production --node-env=production --watch"
  },
  "....": "...."
}

Then run the com­mand with­in the project's home di­rec­to­ry.

npm run watch
> my-webpack-project@1.0.0 watch /home/spas/tmp/es6-tooling
> webpack --watch

asset main.js 5.21 KiB [emitted] (name: main)
runtime modules 670 bytes 3 modules
cacheable modules 1.17 KiB
  ./src/index.js 67 bytes [built] [code generated]
  ./src/circle.js 1.1 KiB [built] [code generated]
webpack 5.69.1 compiled successfully in 770 ms

Af­ter that change some of the source files, lo­cat­ed in the di­rec­to­ry src/​​​, save the changed and in­spect the browser's con­sole once again.