UniteJS — One CLI To Rule Them All

One CLI to rule them all, well maybe not quite yet, but that is the aim…

In these days of enormous web development investment in brain power, time and money there is a constant need for developers to deliver tangibles. While this is good for competition and moving technology forward it leaves scant amount of time for developers to invest in learning or adopting newer technologies or techniques.

A constant churn of frameworks, tools and libraries all vying to be flavour of the month also leaves developers thinking should I switch or will it take me down an infinite rabbit hole.

You may say this is the nature of web development and you may well be right, but wouldn’t it be nice to have an hour here or there to see if you might be missing out on the next best thing in web development.

CLIs

Some of the newer application frameworks (Angular, Aurelia, Preact, React, Vue etc) have CLIs which allow you to create a boilerplate application with almost no user interaction. These generated applications are ready to build and run using the development stack that the framework developers deem the best combination for use with their technology. While this is great to get you up and running quickly each CLI generates its own unique stack, the technologies within it may or may not be familiar to you. As a developer you might already have favourite tools when it comes to other parts of your workflow (testing, styling etc) but you don’t want to spend any time working out how to incorporate them in to the generated app if it is even possible.

Bundlers

Most of the CLIs use some sort of bundling technology (Webpack, Browserify, SystemJS) to produce a bundled version of your app out of the box. These bundlers also provide hooks to do tasks such as transpilation of your code, linting, styling and more. While these facilities are fantastic, it can make the development process quite brittle if you want to change part of your workflow. Also, if there is not a plugin for your favourite tool you are faced with writing a plugin yourself or abandoning your preferred way of doing a specific task. Bundlers for the most part support hot module reloading so when you are testing the whole bundle doesn’t have to be updated when something small changes, but there is still a lot of overhead in doing so.

Opaque Development

The combination of the CLI and bundlers can make debugging your application problematic. If part of the build workflow fails, do you have enough information to find out which step failed and where to even look to fix it. The same is true of bundling, you code is taken one step beyond transpilation, so is the problem your code, the transpiled code or the bundling process. In both scenarios if the problem turns out to be a problem with the CLI/bundler do you really want to be digging around in their source code or waiting for them to fix an issue that you raise.

The Best Tool For The Job

Some might say that the CLI/bundling opaqueness is not a problem and given enough time all the issues will be resolved, I look forward to that day. Until then I believe in directly using the best tool for the job and not calling them through another layer, this is the approach of UniteJS.

UniteJS CLI

UniteJS is a CLI just like many of the others and has comparable features. The main difference is that is that it supports multiple application frameworks along with a multitude of options for other parts of the development stack.

Another huge difference is that during the development process UniteJS maintains your code in its base module form (AMD, CommonJS, SystemJS) making it quicker and easier to fault find. It is only when you create a bundled build that tools like Webpack, Browserify come in to play, all your code, styling, views will be in a form that can be bundled directly by the bundling tools so they are utilised to do the one job that they should be brilliant at.

To support the wealth of options available in UniteJS a more granular approach is taken to the build workflow making it easier to swap out individual components. The list below will give you some idea of the options currently available in UniteJS, you can pick one item from each line below and generate an app. Of course, if it’s a nonsense combination e.g. JavaScript/TSLint or one that is not currently supported you will be informed, on the whole we try and make every combination work.

  • Application Framework — Angular, Aurelia, PlainApp (no framework), React
  • Source Language — JavaScript, TypeScript
  • Module Type — AMD, CommonJS, SystemJS
  • Bundler — Browserify, RequireJS, SystemJS, Webpack
  • Linter — ESLint, TSLint
  • Unit Test Runner — Jest, Karma
  • Unit Test Framework — Jasmine, Mocha
  • Unit Test Engine — Chrome Headless, JSDom, PhantomJS
  • E2E Test Runner — Protractor, WebdriverIO
  • E2E Test Framework — Jasmine, Mocha
  • CSS Pre-Processor — CSS, Less, Sass, Stylus
  • CSS Post-Processor — None, PostCSS
  • Task Runner — Gulp
  • Package Manager — Npm, Yarn
  • Packaging — Web App, Electron

UniteJS currently creates a build workflow based on Gulp which means that once UniteJS generates your initial boilerplate you might never need to use UniteJS again, there is no UniteJS code as part of the build process just one configuration file. Every application framework is provided with the same set of workflow tasks build, unit, e2e etc so once you have learned the tasks once you can change any option under the sun and the tasks you run are exactly the same.

UniteJS also has some built in profiles which should match the tool stack generated by the default CLIs for each application framework.


Hands On

Before you begin you must install the unitejs-cli as a global package so:

npm install -g unitejs-cli or yarn global add unitejs-cli

Create an Angular app using TypeScript:

unite configure --packageName=my-app --title="My App" --profile=AngularTypeScript --outputDirectory=./my-app

or maybe switch to using less for syling:

unite configure --packageName=my-app --title="My App" --profile=AngularTypeScript --cssPre=Less --outputDirectory=./my-app

once generated you are not limited to your original choice, you can switch for example to use Sass in an already existing setup:

unite configure --cssPre=Sass --outputDirectory=./my-app

How about supplying all the options:

unite configure --packageName=my-app --title="My App" --license=MIT --appFramework=Aurelia --moduleType=SystemJS --bundler=SystemJSBuilder --sourceLanguage=TypeScript --linter=TSLint --unitTestRunner=Karma --unitTestFramework=Jasmine --unitTestEngine=ChromeHeadless --e2eTestRunner=Protractor --e2eTestFramework=Jasmine --cssPre=Sass --cssPost=PostCss --packageManager=Npm --outputDirectory=./my-app

and then changing your mind to use MochaChai:

unite configure --unitTestFramework=MochaChai --outputDirectory=./my-app

You can generate your own configurations using the online generator at http://unitejs.com/#/generator which has some validation built in to allow you to only choose valid option combinations.

Generate Code

In addition to just configuring the development stack UniteJS like the other CLIs can also generate components for your application:

  • Angular: class, component, directive, enum, guard, interface, module, pipe, service
  • Aurelia: attribute, binding-behavior, class, component, element, enum, interface, pipeline-step, value-converter
  • PlainApp: class, enum, interface
  • class, component, enum, interface

The generated code will be tailored to your configured options providing code, view, styling and tests where at all possible. The name will be manipulated to the correct case camel, snake, pascal, human to use in the generated items, it is best to supply the original in human readable form. The generated items will use the recommended naming convention and output location for each application framework.

Examples

unite generate --name="Super Spinner" --type=component
unite generate --name="The Thing " --type=class --subFolder=./myClasses/

Client Packages

UniteJS also support adding 3rd party libraries with a minimum of fuss and integrating them into your application, no need to worry about script includes, module loader configuration etc. Libraries often have different ways of loading and needs assets bundling, hopefully we have catered for the different varieties available but expect this to grow over time.

Examples

unite clientPackage --operation=add --packageName=moment
unite clientPackage --operation=add --packageName=font-awesome --assets=css/**/*;fonts/**/*

We also support profiles for some common libraries, expect this list to grow as well.

unite clientPackage --operation=add --profile=font-awesome

Platform Packaging

When your app is ready to deploy it is nice to be able to create a production release with just the essential components, this is where platform come in. Based on your current setup you can produce a web or Electron packaged build.

Example

First add the platform to your configuration

unite platform --operation=add --platformName=Electron

Then you will have access to some additional build tasks which will provider you a completely standalone version of your application without all the detritus of the development process.

gulp platform-electron-package

Favicons

To reduce the other tasks you need to perform when generating your app we also have built in favicon generation for the different platforms, just provide a couple of SVGs and your accent colour, run the theme-build task and all the required image formats are generated using our own native image generator (that includes generating Apple icons on Windows, and Windows Icons on a Mac).


Future

Native browser support for JavaScript modules will eventually arrive, will this make bundlers redundant, who knows? New frameworks and tools will arrive, will everyone want to switch to them, who knows? Neither of these issues is a problem for UniteJS as we will expand are options and integrate them into a known workflow.

At UniteJS we will endeavour to assimilate all that we can (we already have a lot on the road map) and always open to suggestions.

We have no axe to grind with any specific framework or tool, if something new gains traction and enough adoption we will integrate it. All that being said UniteJS is open source and very modular so adding a new framework/tool is very easy (and in the process of getting easier).

So what are you waiting for, isn’t it worth a few minutes of your time to explore UniteJS, given the time, money and anguish it might save you in the long run!

Martyn Janes @martynjanes
Senior Developer UniteJS

More Information

For more information, documentation and the online CLI generator visit the web site at http://unitejs.com
Npm: https://www.npmjs.com/package/unitejs-cli
GitHub: https://github.com/unitejs
Gitter Chat: https://gitter.im/unitejs/discuss
Twitter: https://twitter.com/UniteJS