πŸ“œ ⬆️ ⬇️

How we prepare React, Require and Backbone

As follows from the official documentation, React.js - V is from MVC, and, as a rule, other solutions are applied with it, in this case Backbone.js and Require.js. And Jasmine, Karma and Grunt. Today I will share a draft of the project using these tools.

Link for the impatient.

Wishlist




What have achieved


The β€œtree” of the project looks like this:
')
. β”œβ”€β”€ app β”‚  β”œβ”€β”€ app.js #    β”‚  β”œβ”€β”€ bower_components # ,   bower.json β”‚  β”‚  └── ... β”‚  β”œβ”€β”€ index.html β”‚  β”œβ”€β”€ scripts β”‚  β”‚  β”œβ”€β”€ controllers # Backbone  β”‚  β”‚  β”‚  └── src β”‚  β”‚  β”‚  β”œβ”€β”€ hello.jsx β”‚  β”‚  β”‚  β”œβ”€β”€ main.jsx β”‚  β”‚  β”‚  └── notfound.jsx β”‚  β”‚  β”œβ”€β”€ router.js #   β”‚  β”‚  └── ui-components # React  β”‚  β”‚  └── src β”‚  β”‚  └── panel β”‚  β”‚  β”œβ”€β”€ panel.jsx β”‚  β”‚  └── panel.less β”‚  └── styles #  β”‚  └── src β”‚  └── main.less β”œβ”€β”€ bower.json #   β”œβ”€β”€ Gruntfile.js β”œβ”€β”€ install-deps.bat # , β”œβ”€β”€ install-deps.sh #  β”œβ”€β”€ install-env.bat #  β”œβ”€β”€ install-env.sh #   β”œβ”€β”€ package.json #    node.js,    (,      node.js) β”œβ”€β”€ server └── test #  β”œβ”€β”€ test.config.js └── ui-components └── src └── panel.test.jsx 

And so the code


I don’t see the point of looking at the entire source code in detail ; there is a github for this, I ’ll focus on the key points:

 /* * app/app.js *      index.html,    require *        (Backbone). */ 'use strict'; requirejs.config({ baseUrl: './', paths: { app: './scripts', controllers: './scripts/controllers/dest', // dest -    "" .jsx  .less ui: './scripts/ui-components/dest', //       underscore: './bower_components/underscore/underscore', backbone: './bower_components/backbone/backbone', jquery: './bower_components/jquery/dist/jquery.min', react: './bower_components/react/react' } }); 


Actually, the routing itself. Comments, I think, are superfluous.

 /* * app/scripts/router.js */ 'use strict'; define(function(require) { var Backbone = require('backbone'); var AppRouter = Backbone.Router.extend({ routes: { '': 'MainCtrl', 'hello/:name(/)': 'HelloCtrl', '*actions': 'NotFoundCtrl' }, MainCtrl: require('controllers/main'), HelloCtrl: require('controllers/hello'), NotFoundCtrl: require('controllers/notfound') }); return new AppRouter(); }); 


Ui-components describes the usual React components in the .jsx syntax and style sheets for each individual component. There is something in common with BEM . Each component lies in a separate folder and depends only on React.

Not only interface components, but also controllers are written in the .jsx syntax so that you can do it like this:

 /* * app/scripts/controllers/src/hello.jsx */ 'use strict'; define(['react', 'ui/panel/panel'], function(React, Panel){ /*     */ return function(name){ /* *   , ,    . *    (). */ React.render( <Panel title="Hello controller"> <h1>Hello, {name}!</h1> </Panel>, document.body); }; }); 
.

Tests


Testing the UI is difficult, so Facebook has kindly provided TestUtils specifically for testing React components, tests for which might look something like this:

The code that we will test. A component that draws a bootstrap panel with a title and contents.

 /* * app/scripts/ui-components/src/panel.jsx */ define(['react'], function(React){ 'use strict'; var Panel = React.createClass({ render: function(){ return ( <div className="panel panel-default"> <div className="panel-heading"> <h1>{this.props.title}</h1> </div> <div className="panel-body"> {this.props.children} </div> </div>); } }); return Panel; }); 


And these are tests for the panel, written using Jasmine , you can use any framework that you like, for example, the React developers use Jest . The tests are run with the help of Karma , unfortunately so far, I could not get PhantomJS for these tests, so you have to put up with constantly emerging chrome.

 /* * test/ui-components/src/panel.test.jsx */ 'use strict'; define(['react', 'ui/panel/panel'], function(React, Panel) { describe('Panel behaviour tests', function() { var TestUtils = React.addons.TestUtils; var panel; var p; /* *  this.setUp()  xxxUnit */ beforeEach(function(){ panel = TestUtils.renderIntoDocument(( <Panel title="Test"> <p>Paragraph content</p> </Panel>)); }); /*      */ it('Should render itself into DOM', function(){ expect(TestUtils.isCompositeComponent(panel)).toBe(true); }); /*   ,    */ it('Should render title from props', function(){ var h1 = TestUtils.findRenderedDOMComponentWithTag(panel, 'h1'); expect(h1.getDOMNode().innerHTML).toBe('Test'); }); /*       */ it('Should render children from props', function(){ var paragraph = TestUtils.findRenderedDOMComponentWithTag(panel, 'p'); /* * Specific react feature, it does not render text node directly, * but renders <span ... >Paragraph content</span> */ expect(paragraph.getDOMNode().innerHTML).toContain('Paragraph content'); }); }); }); 


By the way, index.html looks pretty short and neat:

 <html> <head> <title>React+Backbone</title> <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css"> <link rel="stylesheet" href="styles/dest/styles.css"> </head> <body> <div id="main"></div> <script type="text/javascript" src="bower_components/requirejs/require.js"></script> <script type="text/javascript" src="app.js"></script> <script src="//localhost:35729/livereload.js"></script> </body> </html> 


Automation


The grunt which "compiles" less and jsx does an excellent job with it, runs tests, refreshes the page in the browser while saving files and does many more cool things .

Reuse and modularity


In principle, any component of the UI can simply be taken and copied to another project, along with styles and tests (of course, there is also a need for React). And he (the component) will work immediately, without unnecessary gestures. This is especially true for adminok and typical components, there even the styles do not need to change.

And why is all this necessary?


Firstly, I wanted to collect all the necessary tools in one place so that they also worked. Secondly, I really love React, using it with Backbone is probably worth it, both are light, nimble and expandable, and Require can make the structure of the application more transparent. Thirdly, I’ve got (I want to believe) a small β€œtemplate” of a typical project, starting development you can simply pull down the repository and β€œeverything will work right away (c)”.

So, what is next?


All at once does not work yet. In the near future plans to implement the project assembly for production, with minification of everything that can be minimized. In a little more distant - writing yoman generator for scaffolding controllers and components.

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


All Articles