Skip to content

Instantly share code, notes, and snippets.

@jbmoelker
Last active March 9, 2016 15:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jbmoelker/7f08d840c4d560c6c6c9 to your computer and use it in GitHub Desktop.
Save jbmoelker/7f08d840c4d560c6c6c9 to your computer and use it in GitHub Desktop.
[WIP] Opinionated RiotJS Style Guide

Note: These are just my personal notes. Rules which are formalised are moved to voorhoede/riotjs-style-guide

RiotJS Style Guide

Opinionated RiotJS Style Guide for teams by De Voorhoede.

Purpose

This guide provides a uniform way to structure your RiotJS code. Making it

  • easier for developers / team mebers to understand and find things.
  • easier for IDEs to interpret the code and provide assistance.
  • easier to (re)use build tools you already use.
  • easier to cache and serve bundles of code separately.

This guide is inspired by AngularJS Style Guide by John Papa.

Module based development

Riot fits well in the "Module based development" philosophy, applied in all Voorhoede projects.

Modules should be

  • Focused (single responsibility)
  • Independent
  • Reusable
  • Small
  • Testable

(https://addyosmani.com/first/)

UI components only

  • custom component tags
  • view logic
  • UI, not services, not data models, not presentational / appearance components like .panel.

Component / tag names

  • spec compliant, include hyphen -.
  • meaningful (not overspecific, not overly abstract)
  • keep it short: 2 or 3 words
  • pronouncable, as we want to be able talk about them
  • avoid: tag, container, wrapper, etc.

1 component = 1 directory

Why?

Bundle all files which construct a component into a single place. This makes them easy to find, move and reuse.

How?

Use component name as directory name and file basename. The file extension depends on the purpose of the file.

modules/
	my-example/
		my-example.tag.html
		...
		README.md

Use *.tag.html extension

Why?

  • improves IDE support (signals how to interpret)

Keep tag expressions simple

Why?

  • Inline expressions can't be reused elsewehere. This can lead to code duplication and code rot.
  • Complex inline expressions are hard to read.
  • IDEs typically don't have support for expression syntax, so your IDE can't autocomplete or validate.

How?

/* recommended */
<datetime>{ this.timestamp() }</datetime>

/* avoid */
<datetime>
	{ ((new Date()).getUTCMonth()+1) + ' ' + (new Date()).getUTCFullYear() }
</datetime>

Use <script>

Why?

  • prevents markup being interpreted as script.
  • improves IDE support (signals how to interpret)
  • tells developers where markup stops and scripting starts

How?

/* recommended */
<my-example>
	<h1>The year is { this.year }</h1>
	
	<script>
		this.year = (new Date()).getUTCFullYear();
	</script>
</my-example>

/* avoid */
<my-example>
	<h1>The year is { this.year }</h1>
	
	this.year = (new Date()).getUTCFullYear();
</my-example>

this is tag instance

Within the scope of a Riot tag element, this is bound to the tag instance. Therefore when you need to reference it in a different scope, ensure this is available as tag.

Why?

By assigning this to a variable named tag the variable tells developers it's bound to the tag instance wherever it's used.

How?

/* recommended */
// ES5: assign `this` to `tag`
var tag = this;
window.onresize = function() { 
	tag.adjust();
}

// ES6: you may still use `this`
window.onresize = () => {
	this.adjust();
}

/* avoid */
var self = this;
var _this = this;
// etc

Tag script signature

function myExampleTag(opts) {}

Avoid tag.parent

Riot exposes the parent tag on a tag instance through tag.parent.

Why?:

  • modules should be isolated. Accessing tag.parent breaks this rule.

How?:

  • Pass values a tag needs from its parent to a child (via expression)
  • Use callback expression

[examples]

Use each ... in syntax

Styles in external files

Why?

  • can use pre-processors
  • can use your own build tools
  • can minify, serve and cache separately

How?

Component name as style scope

Why?

How?

Use the component tag name as selector, as parent selector or as namespace prefix:

my-example { }
my-example li { }
.my-example__item { }

Considerations

  • If a component can just as easily be build without any vendor framework - including RiotJS, then do so. This promotes reusability across projects.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment