πŸ“œ ⬆️ ⬇️

JS module for Java developers

Worldwide, the amount of JS code used in applications is growing very strongly, which has already been emphasized several times; you can see pictures on this topic here or here, for example. Accordingly, as the amount of code grows, it becomes necessary to structure the data, manage dependencies, etc., which are currently solved by a whole bunch of frameworks, for example, RequireJS in composition with Backbone . In the Java world, on the other hand, Maven is used to manage dependencies and control the project build process, which does an excellent job of dividing large projects into modules, running tests at the right time, and so on. Some developers who have long been using Maven to build a project may want to put their well-structured JS code into a separate module, test it during the build and perform all operations that allow plug-ins to be done with it, which will be discussed.


Statement of the problem and the choice of frameworks


The task: to create a Maven project with dependency management, containing structured JS code and static markup, a template engine, the ability to test parts of the code separately. The main idea of ​​creating such a module is that to provide static html and JS files to the user, it is preferable to use nginx or apache http server, which work faster than almost any java web container or application server. Making the automatic copying of resources into the necessary folders after assembly is not difficult, but you need to exclude class files from the java module, which is the case with β€œone-page” sites that use REST services.

After examining the variety of solutions available, the following set was chosen that meets our requirements:

')
You will have to read the detailed description of each of these frameworks yourself, and we will start by creating a Maven project.

Maven project


Maven dictates the rules of the project description and the directory structure in which the sources of our application are located. To create a project, we need to create a pom.xml file and add the project name, version and other standard information to it. Packing choose war, because this is the web part of our application.

In addition to the basic information about the project in the build section, you need to add the announcement of a number of plug-ins:


After describing the project you need to create the desired directory structure. The resulting project procurement has the following structure:

 . β”œβ”€β”€ README.md β”œβ”€β”€ pom.xml //Maven   └── src //  ( Maven) β”œβ”€β”€ main //  ( Maven) β”‚  └── webapp //   ( Maven) β”‚  β”œβ”€β”€ css β”‚  β”‚  β”œβ”€β”€ bootstrap.css β”‚  β”‚  β”œβ”€β”€ style.css β”‚  β”‚  └── styles.css β”‚  β”œβ”€β”€ imgs β”‚  β”‚  └── 334.gif β”‚  β”œβ”€β”€ index.html //  ( ) β”‚  β”œβ”€β”€ js β”‚  β”‚  β”œβ”€β”€ app.js // Backbone  β”‚  β”‚  β”œβ”€β”€ libs // β”‚  β”‚  β”‚  β”œβ”€β”€ backbone β”‚  β”‚  β”‚  β”‚  └── backbone-min.js β”‚  β”‚  β”‚  β”œβ”€β”€ handlebars β”‚  β”‚  β”‚  β”‚  └── handlebars.js β”‚  β”‚  β”‚  β”œβ”€β”€ jasmine β”‚  β”‚  β”‚  β”‚  └── jasmine-jquery-1.3.1.js β”‚  β”‚  β”‚  β”œβ”€β”€ jquery β”‚  β”‚  β”‚  β”‚  β”œβ”€β”€ jquery-min.js β”‚  β”‚  β”‚  β”‚  └── jquery-serialize.js β”‚  β”‚  β”‚  β”œβ”€β”€ require β”‚  β”‚  β”‚  β”‚  β”œβ”€β”€ require.js β”‚  β”‚  β”‚  β”‚  └── text.js β”‚  β”‚  β”‚  └── underscore β”‚  β”‚  β”‚  └── underscore-min.js β”‚  β”‚  β”œβ”€β”€ main.js //  JS -  RequireJS   app.js β”‚  β”‚  β”œβ”€β”€ router.js //  β”‚  β”‚  └── views //Backbone View  β”‚  β”‚  └── layout β”‚  β”‚  β”œβ”€β”€ EmptyContent.js β”‚  β”‚  β”œβ”€β”€ EmptyFooter.js β”‚  β”‚  β”œβ”€β”€ NavigationHeader.js β”‚  β”‚  └── PageLayoutView.js β”‚  └── templates // html  β”‚  └── layout β”‚  β”œβ”€β”€ emptyContentTemplate.html β”‚  β”œβ”€β”€ footerTemplate.html β”‚  β”œβ”€β”€ navigationTemplate.html β”‚  └── simpleTemplate.html └── test //   ( Maven) └── js //Jasmine  └── layout └── AboutLayout.js 


The above structure initially loads the main.js file, which is declared as the only loadable script in index.html. This script initializes the application, which starts with the Backbone router, which defines the components that the application loads when navigating through various application links.

Backbone + RequireJS components



So, the main components that Backbone manipulates are objects that extend the View, Model and Collection. It is assumed that we can put each such set into a separate folder and split it into subfolders based on a certain logic, for example, the pages in which they are used. After that, it will be necessary only to connect dependencies between components correctly, which in our case will look like this:

 //RequireJS   define([ 'jquery', 'underscore', 'backbone', // html   handlebars 'text!templates/layout/emptyContentTemplate.html', //    Handlebars 'handlebars' ], function($, _, Backbone,emptyContentTemplate){ var EmptyContent = Backbone.View.extend({ }); return EmptyContent; 


Templates and Layouts



As you saw in the previous snippet, the static .html markup used by the component as the basis for the template Handlebars is transmitted as one of the dependencies using RequireJS. The markup contains patches of template-specific syntax and looks like this:

 <div class="item"> <a href="#/description?id={{id}}">{{title}}</a> </div> 


This template will be converted to a full markup in the rendering process, for which it needs to pass an object with the support, the values ​​of the parameters id and title.

Since the Layout concept does not provide any of the frameworks present, we will introduce our own and call it a page, which in essence will be an object that extends the View class and contains the composition of several other View. In the initialization method of this component, you will need to check the input parameters, and if any of the aggregated views are overwritten, use an instance of the class passed as a parameter, and not the default one.

 define([ 'jquery', 'underscore', 'backbone', 'views/layout/NavigationHeader', 'views/layout/EmptyContent', 'views/layout/EmptyFooter', 'text!templates/layout/simpleTemplate.html' , 'handlebars' ], function($, _, Backbone,NavigationHeader,EmptyContent,EmptyFooter,simpleTemplate){ var PageLayoutView = Backbone.View.extend({ template : Handlebars.compile(simpleTemplate), //defaults to NavigationHeader view function headerContent : NavigationHeader, //defaults to EmptyContent view function mainContent : EmptyContent, //defaults to EmptyFooter view function footerContent : EmptyFooter, initialize : function(options) { //instantiate appropriate views based on component functions if (options.mainContent != undefined && options.mainContent != null) { this.mainContent = options.mainContent; } if (options.headerContent != undefined && options.headerContent != null) { this.headerContent = options.headerContent; } if (options.footerContent != undefined && options.footerContent != null) { this.footerContent = options.footerContent; } }, render: function(){ //compile handlebars template with appropriate markup of components var html = this.template(); //append appropriate content to root element right away after compilation $(this.el).html(html); this.headerView = new this.headerContent({el : '#header'}); this.mainView = new this.mainContent({el : '#mian'}); this.footerView = new this.footerContent({el : '#footer'}); this.headerView.render(); this.mainView.render(); this.footerView.render(); return this; } }); return PageLayoutView; }); 


Testing



Testing is done using Jasmine and the appropriate plug-in. This framework allows you to write tests that are performed during each build of the project, it is also possible to accomplish the goal of the bdd plugin, which will launch Jetty and allow you to open a page in the browser with a report and run the tests every time you refresh the page without completely rebuilding the project. This method is very convenient during development, especially if you write tests before the code.

The only thing I had to change in the standard description of the script is the addition of a stub to the console, because HtmlUnit, in which the tested code will run, does not support it.

Links


Sources and preparation of the project can be found here .

In the process, the following materials were used:

Source: https://habr.com/ru/post/165085/


All Articles