$30 off During Our Annual Pro Sale. View Details »

Elegantly Produce & Consume Compiled Packages (NIE16)

Benjamin Lupton
September 16, 2016

Elegantly Produce & Consume Compiled Packages (NIE16)

My talk, Elegantly Produce & Consume Compiled Packages, presented at Node.js Interactive 2016.

Link to the video recording of me presenting this talk:

Link to the example foreach-elegant package:

Link to complete talk notes:

## Abstract

JavaScript production use to be as easy as publishing your source code, which worked across all environments, with a few minor tweaks. Consumption was as easy as downloading and requiring the package.

These days, code may be run anywhere, in all sorts of browsers, desktops, and devices, with varying capabilities, not always known by the producer. JavaScript has evolved, incorporating new features that save developers time, although not supported across all possible environments - with requires either abstinence of time saving features, or reducing environment support, or compiling on the producer or consumer side, all of which is complex and difficult.

Editions solves this problem elegantly in a standardised way. Producers produce their packages in their ideal configurations, then publish the package with multiple editions for the consumers to consume at their digression. Consumers are made aware of this through automated README updates, can select the exact edition that meets their exact needs - or by default, have the best edition for their environment loaded automatically. All the complexity of modern JavaScript publishing is solved, for the consumer and publisher.

## Benefits to the Ecosystem

If this gains popularity, it will greatly reduce the complexity and difficulty of consuming and producing compiled packages, which is becoming ever increasingly common thanks to accepted power of tools like Babel, TypeScript, JSX, and traditional tools like CoffeeScript.

Currently most people are publishing their compiled code, that may not target all environments, may not mention this, and will need to be recompiled and repackaged, ineffective for runtime by bundlers like rollup, webpack, and browserify. Consumers often have no power over this, and if a hickup occurs, they have to delve into the package, of which none of this was documented, and figure out what overrides and recompilations need to occur.

By publishing multiple editions, with optional autoloader and readme updater - the power stays with the producer and the consumer. We've implemented this over at https://www.npmjs.com/package/editions (see dependents) and it has worked terrifically well for our use cases. Editions range from Babel, JSX, Flow Type, and CoffeeScript.

## Technical Requirements

Nothing extra needed. Topic is mostly theory with some demonstrations that will be useful to first time node.js javascript developers through to more seasoned ones.

Benjamin Lupton

September 16, 2016

More Decks by Benjamin Lupton

Other Decks in Technology


  1. Elegantly
 Produce & Consume Compiled Packages Benjamin Lupton, Bevry

  2. Elegantly
 Produce & Consume Compiled Packages Talk notes and details:

  3. a little about me • Node.js dev since 0.3 /

    2010 • 260 open-source projects, 20,000 stars • 180 npm packages, 4 million downloads a month • projectz (3 years, 110 packages) • editions (1 year, 600,000 downloads a month)
  4. value • battle tested solutions over my many packages to

    • save time producing and maintaining packages through automation, aka never maintain a readme badge again • use your favourite modern tech with less regressions, aka never have modern tech and break old tech again • inform consumers with information they need to optimise and control their consumption and bundles, aka never be surprised by package tech again • same effort for producers, less effort for consumers, aka win win
  5. 4 steps • use a meta builder to automate meta

    file maintenance
 to automate the synchronisation between meta data files like package.json and meta readme files like readme.md • publish at least source edition and compiled edition
 to support highest common and lowest denominators • use the editions standard with a meta builder
 to inform user of editions so they can pick best package, and no tech surprises • use the editions standard with an editions autoloader
 to save consumer time auto selecting best edition by default
  6. step 0 make our project a foreach that supports objects

    and arrays
 provides value, and key/index
 breaks on return false
  7. github.com/new

  8. # foreach-elegant An elegant foreach loop that handles objects and

    arrays README.md MIT License Copyright (c) 2016 Bevry Permission is hereby granted, free of ch of this software and associated document in the Software without restriction, inc to use, copy, modify, merge, publish, di copies of the Software, and to permit pe furnished to do so, subject to the follo The above copyright notice and this perm copies or substantial portions of the So THE SOFTWARE IS PROVIDED "AS IS", WITHOU IMPLIED, INCLUDING BUT NOT LIMITED TO TH FITNESS FOR A PARTICULAR PURPOSE AND NON AUTHORS OR COPYRIGHT HOLDERS BE LIABLE F LIABILITY, WHETHER IN AN ACTION OF CONTR OUT OF OR IN CONNECTION WITH THE SOFTWAR SOFTWARE. LICENSE # Logs logs *.log npm-debug.log* # Runtime data pids *.pid *.seed # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage # nyc test coverage .nyc_output # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt # node-waf configuration .lock-wscript # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release .gitignore
  9. npm init

  10. step 1 meta builder use a meta builder to automate

    meta file maintenance
  11. None
  12. features meta data files • package.json • bower.json • component.json

    • jquery.json meta readme files • README.md • LICENSE.md • CONTRIBUTING.md • BACKERS.md • HISTORY.md
  13. None
  14. readme

  15. None
  16. package.json

  17. None
  18. license

  19. <!-- LICENSEFILE -->

  20. "badges": { "list": [ "travisci", "npmversion", "npmdownloads", "daviddm", "daviddmdev", "---",

    "slackin", "patreon", "gratipay", "flattr", "paypal", "bitcoin", "wishlist" ], "config": { "patreonUsername": "bevry", "gratipayUsername": "bevry", "flattrUsername": "balupton", "paypalURL": "https://bevry.me/paypal", "bitcoinURL": "https://bevry.me/bitcoin", "wishlistURL": "https://bevry.me/wishlist", "slackinURL": "https://slack.bevry.me" } }, <!-- BADGES/ --> <span class="badge-travisci"><a href="http://travis-ci.org/bevry/p <span class="badge-npmversion"><a href="https://npmjs.org/package/ <span class="badge-npmdownloads"><a href="https://npmjs.org/packag <span class="badge-daviddm"><a href="https://david-dm.org/bevry/pr <span class="badge-daviddmdev"><a href="https://david-dm.org/bevry <br class="badge-separator" /> <span class="badge-slackin"><a href="https://slack.bevry.me" title <span class="badge-patreon"><a href="http://patreon.com/bevry" tit <span class="badge-gratipay"><a href="https://www.gratipay.com/bev <span class="badge-flattr"><a href="https://flattr.com/profile/bal <span class="badge-paypal"><a href="https://bevry.me/paypal" title <span class="badge-bitcoin"><a href="https://bevry.me/bitcoin" tit <span class="badge-wishlist"><a href="https://bevry.me/wishlist" t <!-- /BADGES --> badges npmjs.com/package/badges <!-- BADGES/ --> <!-- /BADGES -->
  21. "contributors": [ "Benjamin Lupton <b@lupton.cc> (http://balupton.com)", "Peter Flannery (https://github.com/pflannery)", "Rob

    Loach <robloach@gmail.com> (http://robloach.net)", "Zearin (https://github.com/Zearin)", "vsopvsop (https://github.com/vsopvsop)", "Shahar Or <mightyiampresence@gmail.com> (http://mightyi.am)" ], <h3>Contributors</h3> These amazing people have contributed code to this project: <ul><li><a href="http://balupton.com">Benjamin Lupton</a> — <a href="https://github.com/bevry/projectz/com <li><a href="https://github.com/pflannery">Peter Flannery</a> — <a href="https://github.com/bevry/projectz <li><a href="http://robloach.net">Rob Loach</a> — <a href="https://github.com/bevry/projectz/commits?autho <li><a href="https://github.com/Zearin">Zearin</a> — <a href="https://github.com/bevry/projectz/commits?au <li><a href="https://github.com/vsopvsop">vsopvsop</a> — <a href="https://github.com/bevry/projectz/commit <li><a href="http://mightyi.am">Shahar Or</a> — <a href="https://github.com/bevry/projectz/commits?author= <a href="https://github.com/bevry/projectz/blob/master/CONTRIBUTING.md#files">Discover how you can contrib <!-- /BACKERS --> contributors
  22. install & include "preferGlobal": true, “browser”: truthy,

  23. step 2 two editions publish at least source edition and

    compiled edition
  24. problem

  25. items = ['a', 'b', 'c'] for item in items console.log(item)

    coffeescript es5 var i, item, items, len; items = ['a', 'b', 'c']; for (i = 0, len = items.length; i < len; i++) { item = items[i]; console.log(item); } babel var items = ['a', 'b', 'c'] for ( var item of items ) { console.log(item) } es2015 'use strict'; var items = ['a', 'b', 'c']; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = items[Symbol.iterato (_iteratorNormalCompletion = (_step = _iterat _iteratorNormalCompletion = true) { var item = _step.value; console.log(item); }
  26. legacy

  27. why? operational parity use polyfill instead

  28. bundles double compiles esnext consumer app your dep source compiled

    esnext es2015 es2016 mainstream es2016 optimal — bundle — — packages — es2015 es2016
  29. analysis typescript, flow-type another talk for another day

  30. fix

  31. add babel + flow

  32. "main": "es2015/index.js", "browser": "es2015/index.js", "scripts": { "setup": "npm install", "clean":

    "rm -Rf ./docs ./es2015", "compile": "npm run compile:es2015", "compile:es2015": "babel ./source --out-dir ./es2015 --presets es2015", "meta": "npm run meta:projectz", "meta:projectz": "projectz compile", "prepare": "npm run compile && npm run test && npm run meta", "release": "npm run prepare && npm run release:publish && npm run release:tag && npm run release:push", "release:publish": "npm publish", "release:tag": "git tag v$npm_package_version -a", "release:push": "git push origin master && git push origin --tags", "pretest": "npm run test:eslint && npm run test:flow", "test:eslint": "eslint ./source", "test:flow": "flow check", "test": "node ./es2015/test.js" },
  33. None
  34. None
  35. no more double compile!

  36. require(“foreach-elegant”) require(“foreach-elegant/2015”) require(“foreach-elegant/2015/index.js”) require(“foreach-elegant/source”) require(“foreach-elegant/source/index.js”) manual requires for best editions

  37. step 3 rendered editions use the editions standard with a

    meta builder to inform user of editions
  38. add editions standard

  39. "editions": [ { "description": "Source + ESNext + Require +

    Flow Type Comments", "entry": "source/index.js", "directory": "source", "syntaxes": [ "javascript", "esnext", "require", "const", "let", "flow type comments" ] }, { "description": "Babel Compiled + ES2015 + Require", "entry": "es2015/index.js", "directory": "es2015", "syntaxes": [ "javascript", "es2015", "require" ] } ],
  40. renders like so <!-- INSTALL -->

  41. step 4 autoloaded editions use the editions standard with an

    editions autoloader to save consumer time auto selecting best edition by default
  42. npm install --save editions // index.js module.exports = require('editions').requirePackage(__dirname, require)

    "main": “index.js”, "scripts": { "test": "node --harmony -e '
 '" add edition autoloader
  43. None
  44. next • edition autoloader perhaps to use feature detection over

    blacklist • tighter integration with bundlers for easier config • projectz abstracted into plugin system
 <!— [EXAMPLE:./example.js] —> • projectz automatically pulls in sponsors
  45. thanks github.com/bevry/projectz github.com/bevry/editions github.com/bevry/base balupton.com / bevry.me github.com/balupton twitter.com/balupton