Antonio's Cats Home - Vanilla ES5 JavaScript implementation
Hi,
This is the Vanilla ES5 JavaScript implementation for Antonio's Cats Home. The project is configured with NPM and Gulp with no JavaScript dependencies.
JS (Kb minified) | CSS (Kb minified) | JS imports | CSS imports | Front-end framework | HTTP requests | Routing | Transitions | Other libraries | CSS framework | Building tools | Linting | Tests | Server-side rendering | Server | Readme file | Ready out of the box |
2 | 5 | 1 | 1 (plus fonts) | - (HTML strings with insertAdjacentHTML ) |
XMLHttpRequest | - | - | - | Less using BEM | npm, Gulp | JSHint, HTMLLint and lesshint | Jasmine and Karma on PhantomJS | No | Node.js | In HTML | On dist folder |
CSS code is written using the BEM pattern and LESS.
You do not need to run any npm command or Gulp task since all the processed files are already generated in the dist
folder.
In order to see the project working:
- You can visit https://antonioredondo.github.io/AntoniosCatsHome/vanillaJavaScript/dist.
-
Or you can download the repository and with a browser supporting the
file:///
standard with CORS (like Firefox) opendist/index.htm
. -
Or you can download the repository and run
npm i && npm start
. A Node.js server will start and the system default browser will open automatically at http://localhost:3000/dist/index.htm.
Dependencies
There are no dependencies. No front-end frameworks, no jQuery, no Bootstrap. Internet Explorer 9 and below is not supported. No real need for polyfills like Webshim, or browser compatibility libraries like Modernizr.
The only CSS dependency are the fonts downloaded from Google Fonts.
Due to the small JavaScript and CSS footprint the page loads fast: 4 KB of CSS and 2 KB of JavaScript. See the below screenshot of Firefox Developer Tools showing the minimised version of the project (built with the gulp min
avilabe task).
Best practices
Strict practices and habits are paramount for good software development.
Principles of functional programming have been used to write the business logic for the card list. The JavaScript logic has been encapsulated into the cardList
namespace. This namespace has five functions. sortData()
is a pure function: it does not rely on global variables, does not create side effects on input parameters and always return the same output given the same input. The rest of functions have been coded in a way that always return an expected value and they do not make references to private variables. Like this testing of these functions is an easier and cleaner task.
To create the cardList
namespace I have added extra properties rather than populate its prototype. Libraries like Angular 1.x use this approach, and Douglas Crockford –being once a prototype inheritance championer– has changed his mind and he now rather prefers to simply add properties. Composition over inheritance.
In addition, to create the collapsible cards I have used a modular component-based approach. Tests, JavaScript, template's HTML and CSS for the card list are stored in the components
folder. Then, once the JSON is retrieved it is provided to a mapping function that will take care of writing the data into the right place on the template. I thought of using Moustache.js or Handlebars.js, their footprint is small (9 and 13 KB each respectively), but I am performance junkie and I decided instead to write my own solution with mapping functions.
JavaScript logic takes a total of 1.62 KB of minimised JavaScript.
Testing
To run the tests execute npm test
(you must have executed npm i
before). Tests are executed with Karma and PhantomJS and have been written using Jasmine. npm run-script testautowatch
executes Karma on autoWatch
mode, executing the tests whenever one JavaScript files changes. Ideal for TDD.
The project includes a .spec.js
file which tests the cardList
namespace. There is no tests
folder, .spec.js
test files are next to the code they test.
The project has also configured and working the gulp lint
task for linting which makes use of three packages: gulp-jshint
to lint JavaScript, gulp-htmllint
to lint HTML and gulp-lesshint
to lint CSS. The gulp lint
task is added to the default gulp
task together with the gulp build
task.
Command tools
There are several npm scripts configured dealing with project tasks. The project makes uses of Gulp but it's not necessary to have it installed globally since Gulp tasks are mapped to npm scripts which call Gulp from the node_modules
folder:
Available npm scripts:
-
npm i
(alias fornpm install
): installs all dependencies so that the project can be developed, tested and deployed. Thekarma start
command is attached to thepostinstall
script thus tests are executed once installation has finished. You must executenpm i
before executing any other npm command or Gulp task. -
npm run clean
: removes thedist
folder with all its content. -
npm run lint
: lints JavaScript, HTML and CSS code. -
npm run build
: generates the usable web in thedist
folder. -
npm run build:watch
: executes thedefault
task every time a file from thesrc
folder is modified. This is the script you should run most of the time when developing together with the scriptnpm start
. -
npm run build:prod
: generates the usable web in thedist
folder by minimising the JavaScript, HTML and CSS code. -
npm t
(alias fornpm test
): executes.spec.js
tests with Karma. PhantomJS and Karma will finalise once all the tests are executed. For a command which keeps Karma executing seenpm run-script testautowatch
. -
npm run test:watch
: starts Karma onautoWatch
mode, executing the tests whenever one JavaScript files changes. PhantomJS and Karma won't close once all the tests are executed. Ideal for TDD. -
npm start
: initiates a Node.js server configured onserver.js
and automatically opens the default browser with the project page.
Folder structure
Source code and distributable built code are stored in different folders (src
and dist
folders). There is no tests
folder, .spec.js
test files are next to the code they test.
Screen sizes
The page has two different layouts: one desktop view with a max-width of 1100px, and a mobile view.
Browser compatibility
The page works on Internet Explorer 10 and above and rest of modern browsers. I have not had the chance to try it on Safari.
.
I hope I have explained my approach properly. For sure you have many other doubts that you will like to solve. I am very happy to discuss them with you.
On the project, when you see something weird or wrong I would like to please ask you not to automatically consider that part wrong. There will be a satisfactory explanation so that that code or approach has a reason to exist in peace with the rest of best web coding standards and practices.
Regards,
Antonio