Skip to content

Javascript Development Concept

Benjamin Klaus edited this page Jan 4, 2019 · 9 revisions

Overview

The AsTeRICS Grid uses the following stack of tools and libraries for Javascript development:

  1. npm --> node.js package manager, see https://nodejs.org and https://www.npmjs.com/
  2. webpack --> tool for packing all javascript modules (in our case ES6 modules) to a single file (e.g. https://github.com/asterics/AsTeRICS-Grid/blob/master/package/static/build/asterics-grid.bundle.js), see https://webpack.js.org/
  3. babel --> for transpiling new (ES6) javascript to older one (ES5), see https://babeljs.io/
  4. core-js --> a library providing polyfills, see https://github.com/zloirock/core-js

Decide if a feature can be used

If someone wants to use a certain feature of javascript he/she should follow this flowchart to make a decision if/how to use it:

Flowchart for deciding if its possible to use an javascript feature

Background: Browser compatibility, ES6 vs. ES5

The concept for supporting ES5 while run native ES6 Javascript on modern browsers comes from this article: https://philipwalton.com/articles/deploying-es2015-code-in-production-today/

Use different Javascript code depending on browsers capabilities

Generally the AsTeRICS Grid can run in two different modes on the client:

  1. Normal mode: Runs on a modern browser that supports ES6
  2. Legacy mode: Runs on older browsers which do not support ES6 (or more detailed: do not support ES6 modules)

The distinction between these modes is done by the type=module and nomodule attributes on the <script> tags:

  1. Scripts for normal mode are included like this: <script type="module" src="build/asterics-grid.bundle.js"></script>
  2. Scripts for legacy mode are included like this: <script nomodule src="build_legacy/asterics-grid.bundle.js"></script>
  3. For scripts that should be used in both, normal and legacy mode, a normal script tag without additional attributes is used like this: <script src="polyfill/web-animations.min.js"></script>

That means that modern browsers (supporting ES6 modules) are using the script with type=module and older ones the script with nomodule.

Bundling Javascript using webpack

In the folder https://github.com/asterics/AsTeRICS-Grid/tree/master/src there are the javascript source files that are using the ES6 module system for dependencies (import and export statements). They are bundled using webpack to the file asterics-grid.bundle.js, which has two reasons:

  1. bundling replaces the ES6 module system (import/export) with some webpack-stuff which is ES5 compatible and therefore makes the ES6 modules compatible with older browsers.
  2. Only one file has to be included and loaded within the html-file which can have advantages in performance.

webpack itself is a npm module (see https://www.npmjs.com/package/webpack) and therefore is included in the npm configuration file package.json (see https://github.com/asterics/AsTeRICS-Grid/blob/master/package.json#L16). The bundling of webpack can be started using the command

npm start build

This command bundles everything from the src folder to the folders package/static/build and package/static/build_legacy in the files asterics-grid.bundle.js which is included in the html file (see https://github.com/asterics/AsTeRICS-Grid/blob/master/package/static/index.html#L46).

Transpiling ES6 to ES5 using babel.js

The folder build contains the bundle asterics-grid.bundle.js which includes all the modules in a single file, but with unchanged syntax. So all ES6 syntax like arrow functions (e.g. a => a*a) will stay exaclty the same. However everything written in ES5 syntax (e.g. function(a) {return a*a}) also won't change and stay in this syntax.

The folder build_legacy also contains a bundle asterics-grid.bundle.js, but an transpiled version where all ES6 syntax like arrow functions are replaced by the ES5 equivalent. So any function like a => a*a in this file will be changed to function(a) {return a*a}.

Transpiling for the bundle in build_legacy is done using babel. The webpack plugin babel-loader is used, which can be seen in the webpack.config.js, https://github.com/asterics/AsTeRICS-Grid/blob/master/webpack.config.js#L53:

options: {
	presets: [
		['env', {
			modules: false,
			useBuiltIns: true,
			targets: {
				browsers: [
					'> 1%',
					'last 2 versions',
					'Firefox ESR'
				],
			},
		}],
	],
}

The configuration in the browsers field contains queries to select browsers to transpile the javascript for. See https://github.com/browserslist/browserslist#full-list for valid queries. So in our case the configuration means that babel transpiles the code to be compatible with all browsers that have more than 1% usage, are within the last 2 versions or are a Firefox ESR version. At some day in the future, if these browsers all support ES6 this means, that babel will not transpile ES6 to ES5 anymore but will keep the ES6 syntax.

Using core-js for Polyfills

Babel also could provide polyfills for missing functionalities in older browsers like e.g. Promise. However we decided to not use babel for this issue, because we don't want to load Polyfills on modern browsers and this is currently not possible using babel. Therefore core-js is used, a set of Polyfills, that is also used by babel in the background. core-js is included with this line, see https://github.com/asterics/AsTeRICS-Grid/blob/master/package/static/index.html#L13:

<script nomodule src="polyfill/core_js_shim.min.js"></script>

Using the nomodule attribute means that this file is only loaded if the browser does not support ES6 modules (and therefore in lecacy mode). See https://github.com/zloirock/core-js#features for documentation of the polyfills provided by core-js.

Conculsion

The described solution sums up in:

  1. New browsers which support ES6 modules use the package/static/build/asterics-grid.bundle.js file and therefore run all code written in src (also ES6 code) native.
  2. Older browsers which do not support ES6 modules use the transpiled package/static/build_legacy/asterics-grid.bundle.js file and polyfills of core-js. This should lead to support of nearly all browsers.

See https://caniuse.com/#feat=es6-module to get an idea which browsers will run (1) and which (2).