[Fuente: http://www.thegameofcode.com/2013/05/front-end-with-iris-nodejs-gruntjs.html]
¿Por qué utilizar Iris?
Los motores de Javascript actuales están evolucionando rápidamente y se están volviendo más rápidos y potentes.
Sin embargo por otro lado es común encontrar códigos fuente de Javascript realmente feos y liosos. El framework de Iris te guía en la buena dirección y te ayuda a programar aplicaciones web complejas:
- Buena organización del código fuente: All our JS code is split into small files providing scalability & maintainability. Don’t worry about the large number of files created because you can concatenate them using grunt, thus avoiding a large number of HTTP requests.
- Solución single-page: Navigation is performed without reloading the page using hash-URLs, e.g. gmail. The navigation system is resolved in a simple way using JS, therefore performance is improved.
- Motor rápido de templates: With Iris templates you can easily add multilanguage texts into screens and UIs using @@ annotations. In the same way you can print formatted strings as currencies, dates, numbers, etc…
- Muy ligero de peso con lo que se carga rápido: Iris is very light, about 16KB, and only depends on jQuery. All files are HTML or JS, therefore your front-end code is independent of server technology. This allows Iris components to be cached by the browser.
- Buena documentación:
- API Doc: https://github.com/thegameofcode/iris/blob/master/docs/api.md
- Tutorial: http://thegameofcode.github.io/iris/tutorials/todo/
- Guide (Spanish): https://github.com/thegameofcode/iris/blob/master/docs/es/README.md
- Video Tutorial (Spanish): http://www.youtube.com/watch?v=6evSeCDXjSQ
About Iris
Iris te proporciona la estructura las aplicaciones web proporcionando templates , componentes UI , screens and resources.
Todos los paths de los componentes deben ser definidos previamente en iris.path ,por ejemplo.: iris.path.ui = “path/to/my/ui.js”
- Templates are written in HTML files. These are stored in separate *.html files, therefore a layout designer can edit them easily.
<div> <!-- All templates must have a root element --> <!-- The (@@...@@) annotations will print translated text --> <b>@@name@@</b>: <!-- The (##...##) annotations will be replaced by template params --> <b>##user.name##</b> <!-- The button element can be used by a UI or Screen due the data-id attr --> <button data-id="accept_button">@@ok@@</button> </div>
- UIs are graphical components written in JS that can be reused. UIs uses a template to add functionality and manage events. These objects are stored in separate *.js files.
iris.ui( // "self" is equal to "this" but can be used // inside private functions function(self) { // function called automatically once when a UI // of this kind is instanced self.create = function() { // set the template self.tmpl(iris.path.ui.html); // return the jq element with data-id=button self.get("button").on("click", function (){ alert( "Hi " + self.setting("name") + "!"); }); }; } );
- You can use UIs to create an HTML element into a template:
<!-- The "name" setting will be "Jonh" --> <div data-id="my_ui" data-name="Jonh"></div>
- The <div> element will be replaced by the template
template.html
- :
<div> <b>UI Example</b> <button data-id="button">Say Hi!</button> </div>
- Finally, you can create a UI instance inside screens or other UIs:
self.ui("my_ui", iris.path.ui.js);
- The result:
- Screens are navigable elements, bound to a unique hash fragment (#screen), and are stored in separate *.js files. Screens use a template to add functionality and manage events like UI does. You can also instantiate UI objects within screens. Screens’s declaration are very similar to the UI’s declaration, use iris.screen() instead ofiris.ui()
iris.screen( // "self" is equal to "this" but can be used // inside private functions function(self) { // function called automatically once when this screen is instanced self.create = function() { // set the template self.tmpl(iris.path.screen.html); // created a UI component, the setting "name" will be "Anonymous" self.ui("my_ui", iris.path.ui.js, { name : "Anonymous" }); }; } );
- The content of the screen will be
iris.path.screen.html
- .
<div> <b>My Screen</b><br /> <div data-id="my_ui"></div> </div>
- Finally, you can create this screen navigating to them, use
iris.navigate()
- or type the URL into your browser:
iris.navigate("#/my_screen");
- The result is a web page like:
UI Example
Grunt advantages
The most important advantage of Grunt is automation. With hundreds of plugins to choose from, you can do repetitive tasks like minification, compilation, unit testing, linting, etc. After you’ve configured it, a task runner can do most of that mundane work for you with a minimum of effort.
To run Grunt you need to install NodeJS, for more information please visit http://gruntjs.com/getting-started.
Complete example
I have written a complete example based on the famous todomvc, using Iris and Grunt.
If you want to learn more about the iris-todomvc please check out this tutorial.
Project structure
- dist/: Final destination folder, all content will be generated by Grunt
- src/: Development folder that contains all source code and application resources
- Gruntfile.js: Grunt’s configuration file
- package.json: Specifics of npm’s package.json handling
Gruntfile.js
All of the configuration for our Grunt build process sits inside our Gruntfile (Gruntfile.js) in our project directory.
module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), jshint: { all: ['Gruntfile.js', 'src/app/**/*.js'] }, uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { src: '<%= pkg.iris.baseUri %>**/*.js', dest: '<%= pkg.iris.init %>' } }, connect: { dev: { options: { base: 'src' } }, dist: { options: { base: 'dist' } } }, watch: { scripts: { files: ['src/**/*.js'], tasks: ['jshint'], options: { nospawn: true } } }, copy: { main: { files: [ {expand: true, cwd: 'src/', src: ['**'], dest: 'dist/'} ] } }, clean: ['dist'] }); // Custom task to concatenate Iris templates grunt.registerTask('iris-tmpl', function() { grunt.log.writeln('Concatenate Iris templates...'); var pkg = grunt.file.readJSON('package.json'); var irisBaseUri = pkg.iris.baseUri; var destFile = pkg.iris.init; grunt.log.writeln('Configurations: baseUri['+ irisBaseUri +'] init['+ destFile +']'); var templates = ''; grunt.file.expand({cwd : irisBaseUri}, '**/*.html').forEach(function(file){ var source = grunt.file.read(irisBaseUri + file, {encoding : "utf8"}) .replace(/[\r\n\t]/g, '').replace(/\"/g, '\\"'); templates += 'iris.tmpl("' + file + '", "' + source + '");\n'; }); var irisTmpl = grunt.file.read(destFile, {encoding : "utf8"}) + templates; grunt.file.write(destFile, irisTmpl); grunt.log.writeln('File "' + destFile + '" saved.'); }); // Load tasks grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-connect'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-contrib-clean'); // Register Grunt tasks grunt.registerTask('default', ['jshint', 'clean', 'copy', 'uglify', 'iris-tmpl']); grunt.registerTask('devserver', ['jshint', 'connect:dev', 'watch']); grunt.registerTask('distserver', ['default', 'connect:dist', 'watch']); };
package.json
To run this example, first install Nodejs and Grunt, after go to project’s root folder and execute $ npm install then you can run the Grunt tasks.
{ "name": "todomvc-iris", "description": "TodoMVC - Iris", "version": "1.0.0", "private": true, "iris" : { "init" : "dist/app/init.js", "baseUri" : "src/app/" }, "devDependencies": { "grunt": "0.4.1", "grunt-contrib-uglify": "0.2.0", "grunt-contrib-connect": "0.3.0", "grunt-contrib-watch": "0.3.1", "grunt-contrib-jshint": "0.4.3", "grunt-contrib-concat": "0.2.0", "grunt-contrib-copy": "0.4.1", "grunt-contrib-clean": "0.4.1" } }
Grunt tasks
$ grunt
Use this command to build the application.$ grunt Running "jshint:all" (jshint) task >> 5 files lint free. Running "clean:0" (clean) task Cleaning "dist"...OK Running "copy:main" (copy) task Created 4 directories, copied 12 files Running "uglify:build" (uglify) task File "dist/app/init.js" created. Running "iris-tmpl" task Concatenate Iris templates... Configurations: baseUri[src/app/] init[dist/app/init.js] File "dist/app/init.js" saved. Done, without errors.
How it works?
- First, Grunt checks code style and validates it using JSHint, if all goes well, it will copy all files from
/src
to/dist
folder. - The next step is to concatenate and compress the source code of our application (
src/app/**.js
files). - Thereafter, all iris components (screens, UIs & resources) have been concatenated into a single file (dist/app/init.js).
... uglify: { ... build: { src: '<%= pkg.iris.baseUri %>**/*.js', dest: '<%= pkg.iris.init %>' } }, ...
- Finally, all Iris templates are concatenated using the custom task
iris-tmpl
. All HTML have been appended to dist/app/init.js.
You can change this packaging settings in package.json:
... "iris" : { "init" : "dist/app/init.js", "baseUri" : "src/app/" } ...
All application files are a single file of 5.33 kb. This is perfect for slow connections like 3G networks.
- First, Grunt checks code style and validates it using JSHint, if all goes well, it will copy all files from
$ grunt devserver
Use this command to test and develop the web application.$ grunt devserver Running "jshint:all" (jshint) task >> 5 files lint free. Running "connect:dev" (connect) task Started connect web server on localhost:8000. Running "watch" task Waiting...
- This command checks code style and validates it using JSHint
- It starts a local web server and sets its root folder to
/src
and waits for file changes. You can test the web in your browser and, at the same time, change the files with some text editor.
$ grunt distserver
Execute this command to test the build$ grunt distserver Running "jshint:all" (jshint) task >> 5 files lint free. Running "clean:0" (clean) task Cleaning "dist"...OK Running "copy:main" (copy) task Created 4 directories, copied 12 files Running "uglify:build" (uglify) task File "dist/app/init.js" created. Running "iris-tmpl" task Concatenate Iris templates... Configurations: baseUri[src/app/] init[dist/app/init.js] File "dist/app/init.js" saved. Running "connect:dist" (connect) task Started connect web server on localhost:8000. Running "watch" task Waiting...
- Grunt executes the default task (like
$ grunt
) - It initializes a local server to test the generated website at
/dist
folder. You can test the final application typing into your browser: http://localhost:8000/
- Grunt executes the default task (like
Download the Iris todo-list example and learn how to create your own Iris + Grunt + Nodejs applications.
You can find the demo here.
Enjoy it!