Skip to content

About the Build Process

Adam Bosco edited this page Jan 12, 2017 · 7 revisions

By virtue of being an interpreted language, JavaScript code is able to simply be executed "as-is" by a JavaScript interpreter such as the ones in hackmud, Node.js, and in your web-browser. On the other hand, languages such as the C family must first be translated into machine code by a compiler before they can be executed. So if JavaScript doesn't need to be compiled, why then does hackshell need a "build process"?

The short answer is that it doesn't - the hackshell source files can actually be used as-is in environments that support the latest JavaScript feature set. But most JavaScript environments don't support all of the language features that hackshell utilizes, so through a process called "transpilation" the hackshell source files are turned into files which nearly every popular JavaScript interpreter can understand.

More specifically, the hackshell source files in lib are written using relatively new language features implemented in a version of JavaScript referred to as ES6 or ES2015 - this is the same version of JavaScript which the hackmud interpreter was written to support (with many limitations).

Transpiling the source to earlier versions of JavaScript removes a lot of the requirements necessary to run hackshell, and additionally ensures it can be used in Node.js and web-browsers alike (necessary to my own ends since hackshell is used both in the browser as well as server-side to power the hackdev editor).

Build Process

So what happens when you run npm run build or npm run build-cli in the project root?

The build process starts by looking over the source files for potential problems and strange coding practices in a process known as "linting" (here performed by the wonderful ESLint project). It then reports any problems it encounters and where they are allowing contributors to address them if need be. This is a function often provided by IDEs.

If no obvious errors are found which would prevent hackshell from functioning properly, the source files are then passed to the Rollup module bundler.

Rollup starts by taking a look at the file lib/index.js, then recursively grabs all of the referenced source files, transpiles them into more universal forms of JavaScript using Babel, concatenates the transpiled code into one large chunk, then spits out the result into a file called a "bundle" in the dist directory.

Bundles

A "module bundle" is little more than a bunch of source files combined into one. In short, bundling modules improves both the developer and consumer experience - developers can organize their code into logical and deep hierarchies using files and directories, and consumers need only reference a single file to gain access to all that code. This is probably most evident in the context of the web; where a web-browser would normally need to download every individual JavaScript file in a library in order to run a web-app, only a single request is needed if the web-app has been bundled - thus decreasing loading times and improving the end-user experience.

The hackshell build process produces three separate bundles - all of which contain all of the code necessary for hackshell to function.

npm run build creates bundles containing the entire hackshell library in a couple different formats.

  • dist/hackshell.js is transpiled down to what is more or less the "lowest common denomenator" when it comes to JavaScript features, then packaged in a format called UMD, or Universal Module Definition. As the name implies, the intention of UMD is to provide a "container" which every popular JavaScript interpreter can understand. Thus the UMD hackshell bundle should "just work" in any version of Node and most popular web browsers.
  • dist/hackshell.mjs is simply package as a ES2015 module - it retains nearly all of the ES2015 features which hackshell utilizes, making it suitable for the most modern web-browsers and Node v6 and up.

npm run build-cli creates a single bundle (dist/hackshell-cli.js) containing all of the hackshell library code in addition to the lib/CLI.js class which enables hackshell to be used on the command line. In order to interact with the local terminal and filesystem, the hackshell CLI leverages Node's core fs, path, and readline modules; for this reason, the CLI bundle cannot function in a web-browser. The CLI bundle is subsequently packaged in the CommonJS format native to Node.

Sourcemaps

Each build process also creates a .map file in the dist directory for every bundle it produces. These are called "sourcemaps", and they describe how the transpiled and bundled code relates to original sources in lib.

Sourcemaps play an important role in debugging. Without a sourcemap, if an error occurs in transpiled code a developer would have to have a very intimate understanding of their chosen transpiler and bundler in order to determine what part of which source produced the problematic bundled/transpiled code before the error could be corrected. With sourcemaps, developers can execute bundled/transpiled code while debuggers describe errors and execution state in relation to the original source code rather than the garbled translation.

Clone this wiki locally