Roc — One solution to JavaScript Fatigue

An open source toolkit for JavaScript development

There has been a lot of talk recently about how hard it is to do web development in this day and age. People are describing the current state of web development as depressing and frustrating, referring to it as JavaScript Fatigue. If you haven’t I would recommend you to go and read this excellent article by Eric Clemmons on the topic: Javascript Fatigue.

We need to do something about this and we need to do it now. Web development should not be frustrating. In fact I believe that it has never been as exciting and fun as it is now.

As mentioned in the article above several people are trying to find a solution to this symptom, all with different goals and ambitions. I would like to go ahead and present one such solution, one that I have personally been involved with, Roc.

Introducing Roc

Roc, named after the mythical bird, is a toolkit under active development that aims to make modern JavaScript development easier and address the pain points that exists with most of the common solutions today. These pain points includes complex boilerplates, confusing configurations and understanding what libraries works well with others.

Roc has the ambitious goal of addressing the following.

Make it easy to get started with a new project quickly.

Offer the best developer experience possible out of the box with minimal configuration.

Work as a great prototyping tool but also support moving to production easily.

Avoid unnecessary boilerplate code by making it easy to share code and configuration between projects.

Not becoming a new framework. Instead make it easier to work with the existing great solutions that we have today using familiar patterns.

Not be opinionated in the sense that it can only do one thing, e.g React, Mocha, but should work with whatever is the best tool for the job through a modular and extendable architecture.

For a longer article about the motivation behind Roc please see Rethinking modern JavaScript development by Andreas Søvik.

Let’s look at an example that uses React to get a better understanding of what Roc has to offer.

Please note that the example will use one of the official packages and templates. It’s easy to create new package and templates that would for example use Angular over React. The core of Roc is unopinionated in terms of libraries and tools. Only extensions have opinions, making Roc both modular and flexible.

Building a React application with Roc

To give an illustration of the power of Roc let’s look at an example where we create a universal React application using libraries like Redux, React Router and Koa for server side rendering. This includes solutions to several common problems like data fetching and how to style the application.

Roc currently only supports Mac and Linux using npm@3 and Node@4+. We hope to support Windows and npm@2 in the near future.

We will start with installing Roc globally for convenience and then create a new project.

$ npm install roc -g

$ roc new my-app web-app-react

That’s it!

Or a bit more visually with Roc already installed.

From here we can start it in development mode using roc dev or build it for production using roc build followed by roc start to launch it.

Is this not just another Yeoman clone or a fancy CLI for a boilerplate?

Let’s look at the files that we have in our project now.

$ cd my-app && ls ├── app

│ ├── components

│ │ ├── ...

│ ├── redux

│ │ ├── clicker.js

│ │ └── reducers.js

│ ├── routes

│ │ └── index.js

│ └── screens

│ ├── ...

├── package.json

├── public

│ └── favicon.png

└── roc.config.js

How would this application structure compare to one created with a boilerplate or a generator like Yeoman?

It might seem that we are missing some files here but this is everything we need when building an application using Roc. Inside your new application directory you will only find code that is directly relevant to your application and nothing else. Gone are things like webpack.config.js and .babelrc along with boilerplate code for configuring React Router, Redux and managing client and server specific rendering. If needed this can of course be configured but it will stay out of your way as a default.

Left: Roc project. Right: Simple Boilerplate / Generated project.

On top of keeping your project clean this also makes it possible to update the code that manages the server rendering for example, something that is not possible in the generated / boilerplate variant.

Makes it easier to maintain multiple similar projects

So what is inside our package.json?

{

“name”: “my-app”,

“version”: “1.0.0”,

“description”: “My application”,

“author”: “Gustaf Dalemar”,

“license”: “MIT”,

“scripts”: {

“build”: “roc build”,

“dev”: “roc dev”,

“start”: “roc start”,

“lint”: “eslint .”,

“test”: “npm run lint”

},

“dependencies”: {

“roc-package-web-app-react”: “^1.0.0-alpha”

},

“devDependencies”: {

“babel-eslint”: “6.0.2”,

“eslint”: “2.6.0”,

“eslint-config-airbnb”: “6.2.0”,

“eslint-plugin-react”: “4.2.3”,

“roc-package-web-app-react-dev”: “^1.0.0-alpha”,

“roc-plugin-style-sass”: “^1.0.0-alpha”

}

}

This might shock some of you, but trust me when I’m telling you that this is everything you need. Instead of having all of these dependencies inside your project, Roc has managed this for you through a few extensions called packages & plugins.

Where is React, Webpack and Babel?

The majority is being taken care of by roc-package-web-app-react and its dev counterpart as seen above. They will provide the commands needed for development, building and starting the application in production mode along with boilerplate code for supporting server side rendering and Redux configuration and more. We also have one plugin here that adds support for writing our styles using Sass.

This might lead you to think that this means that Roc enforces some strange new syntax to use for example React in your project but this is not the case.

An extremely simple component inside a Roc project.

So let’s see exactly what we can do with this project now.

$ roc Commands: build Build the current project.

clean Cleans the current project.

dev Starts the current project in development mode.

start [artifact] Starts the current project. Some commands have been removed here for brevity… General options: -c, — config Path to configuration file, will default to

roc.config.js in current working directory.

-d, — directory Path to working directory, will default to the

current working directory. Can be either

absolute or relative.

-h, — help Output usage information.

-V, — verbose Enable verbose mode.

-v, — version Output version number.

As seen above we can use the following commands with our application:

build — Build for production, both the server and the client part.

— Build for production, both the server and the client part. clean — Removes files from the build step.

— Removes files from the build step. dev — Starts the application in development mode.

— Starts the application in development mode. start — Uses the production build to start the application.

Highly configurable through both a CLI and a configuration file

But it is not only the commands that we can use to configure what Roc should do with our code. Above when we listed the files in our project we had one named roc.config.js.

Let’s take a look at the file.

module.exports = {

settings: {

runtime: {

applicationName: ‘My Roc Application’,

port: 3000,

serve: [‘public’, ‘build/client’],

favicon: ‘favicon.png’,

},

build: {

reducers: ‘app/redux/reducers.js’,

routes: ‘app/routes/index.js’,

},

},

};

Through this file we can configure almost all aspects of what our packages and plugins should do. Here we can see that we have defined what port to start the application on and where Roc can find the reducers for Redux along with the routes definition file for React Router. Thanks to this we can let Roc take care of all the repetitive boilerplate code for this as we talked about earlier. This allows us to focus on what actually creates value in our project.

This is of course not all the options available, several more exist and everything is dynamically based on what packages and plugins we are using in the current project. These options can also be defined using the CLI as can be seen here with the build command.

Help information shown for the build command.

Let’s quickly start the application in development mode using roc dev.

Running our React application using the dev command.

This will automatically open our default browser and show our application. We can now easily modify the code and see the changes taking place live in our browser. Some of the things that currently is available out of the box:

What about tests?

Now lets say that we would like to test our application as well. As we remember from before we did not have any command for doing that. Roc is modular by design so adding support for testing is a quite trivial task and will be managed by a plugin. Let’s add one that will work with Webpack and uses Mocha & Karma.

$ npm install roc-plugin-test-mocha-karma-webpack --save

Let’s now list the commands again.

$ roc Commands: build Build the current project.

clean Cleans the current project.

dev Starts the current project in development mode.

start [artifact] Starts the current project.

test [targets] Runs tests on the current project. Some commands have been removed here for brevity… General options: -c, — config Path to configuration file, will default to

roc.config.js in current working directory.

-d, — directory Path to working directory, will default to the

current working directory. Can be either

absolute or relative.

-h, — help Output usage information.

-V, — verbose Enable verbose mode.

-v, — version Output version number.

The observant reader will see that we now have a new command, test. We are now ready to add some tests to our application. To keep this short I will just create an empty folder that our tests will be added to. With default options the plugin will generate coverage for src/ and look for test files in tests/ named *.test.js. This is of course configurable through the same interface as we have talked about before.

$ mkdir tests && roc test PhantomJS 2.1.1 (Mac OS X): Executed 0 of 0 ERROR (0.014 s / 0 s)

We can see that PhantomJS has been started here and our tests (we have none) have been executed. From here it would be trivial to add some real tests that would be written as you would normally write Mocha tests.

Summary & Road ahead

It’s hard to explain everything Roc can do in a single blogpost, I will not even try. We are planning to write a more technical article in the future that goes into detail on how Roc is structured, and what makes this modularity possible and some of the design goals behind it.

Note that Roc is under active development and we have many more features, improvements, documentation and new packages & plugins planned for the future. The example that we went through in this post should give you an insight into the path that Roc is taking going forward. Please keep in mind that we are still in an early phase of development and things might change rapidly but we will try to keep breaking changes to a minimum. Additionally we are aware that more documentation is needed and that will be a high priority going forward as well.

To highlight the modularity even more I want to mention that the template that we used is one of the default ones but you could easily use another since the templates are all hosted on Github as separate repositories. This makes it easy to create your own, if you want.

The package and the plugins we looked at are only an example of what can be done today and what will be possible in the future. See the Github organisation for all the current ones.

Follow @roc_js on Twitter for the latest news about Roc as we are moving to a stable first release.