{"id":2187,"date":"2015-07-21T16:34:28","date_gmt":"2015-07-21T23:34:28","guid":{"rendered":"https:\/\/www.microsoft.com\/reallifecode\/index.php\/2015\/07\/21\/a-framework-to-bootstrap-enterprise-single-page-applications-with-continuous-azure-integration\/"},"modified":"2020-03-18T19:55:17","modified_gmt":"2020-03-19T02:55:17","slug":"a-framework-to-bootstrap-enterprise-single-page-applications-with-continuous-azure-integration","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/ise\/a-framework-to-bootstrap-enterprise-single-page-applications-with-continuous-azure-integration\/","title":{"rendered":"Bootstrap Enterprise Single Page Applications with Continuous Azure Integration"},"content":{"rendered":"<p>When developers embark on a new web application project, they often seek technical guidance for where to start, which technologies to use, how to work through platform integration issues, etc. New technologies are emerging at a record pace, so developers spend a lot of time and energy deciding which frameworks are the most trusted and well-established in the web community. As an example, many startups favor open source solutions, and follow some form of agile SDLC methodology to stand up a full-stack local web environment on-demand. Developers need an environment that provides the flexibility to easily swap frameworks while still allowing them to develop rapidly.<\/p>\n<p>Another problem developers often face is the lack or delay of a stable test environment after development is complete. This leaves the sustainability of an app at a vulnerable state; code often needs to be refactored to be testable in a production-ready environment.<\/p>\n<h2 id=\"the-audience\"><\/h2>\n<h2 id=\"the-solution\">The Solution<\/h2>\n<p>The goal of this project was to provide developers with a framework to simplify the process of creating a modern web platform that includes the most common core requirements (listed below). After extensive research, prototyping and performance benchmarking, the following technologies were selected for each of the core requirements:<\/p>\n<ul>\n<li><strong>Task management:<\/strong> <em><a href=\"http:\/\/gruntjs.com\/\">Grunt<\/a><\/em><\/li>\n<li><strong>A lightweight and robust front-end rendering toolset option:<\/strong> <em>Bootstrap 3 + <a href=\"https:\/\/facebook.github.io\/react\/\">ReactJS<\/a><\/em><\/li>\n<li><strong>Web engine<\/strong>: <em><a href=\"https:\/\/www.airpair.com\/javascript\/node-js-tutorial\">NodeJS<\/a><\/em><\/li>\n<li><strong>Http Request \/ Socket Routing Management:<\/strong> <a href=\"http:\/\/socket.io\/docs\/\">Socket.io<\/a> \/ <a href=\"http:\/\/expressjs.com\/\">Express<\/a><\/li>\n<li><strong>Easy and reliable integration with ECMA 6:<\/strong> <em><a href=\"https:\/\/babeljs.io\/\">Babel<\/a><\/em><\/li>\n<li><strong>Web API Generation:<\/strong> <em><a href=\"https:\/\/github.com\/balderdashy\/sails-docs\/blob\/master\/reference\/blueprint-api\/blueprint-api.md\">Sails Blueprints<\/a><\/em><\/li>\n<li><strong>Asset Minification \/ Unification:<\/strong> <em><a href=\"https:\/\/github.com\/jmreidy\/grunt-browserify\">Browserify<\/a><\/em><\/li>\n<li><strong>Package management:<\/strong> <em><a href=\"https:\/\/docs.npmjs.com\/getting-started\/what-is-npm\">NPM<\/a><\/em><\/li>\n<li><strong>Continuous integration:<\/strong> <em><a href=\"http:\/\/docs.travis-ci.com\/\">Travis CI<\/a><\/em><\/li>\n<li><strong>Automated unit testing:<\/strong> <em><a href=\"http:\/\/mochajs.org\/\">Mocha<\/a>, <a href=\"http:\/\/phantomjs.org\/\">PhantomJS<\/a>, <a href=\"https:\/\/angular.github.io\/protractor\/#\/\">Protractor<\/a><\/em><\/li>\n<li><strong>Code Coverage Reporting:<\/strong> <em><a href=\"https:\/\/github.com\/gotwarlost\/istanbul\">Istanbul<\/a><\/em><\/li>\n<li><strong>Code Quality Checks:<\/strong> <em><a href=\"http:\/\/eslint.org\/docs\/about\/\">ESLint<\/a><\/em><\/li>\n<li><strong>One-Click Deployment<\/strong>: <em><a href=\"http:\/\/www.cptloadtest.com\/2013\/12\/03\/Git-And-Grunt-Deploy-To-Windows-Azure.aspx\">Kudu\/Azure<\/a><\/em><\/li>\n<\/ul>\n<p>An additional goal was to create a framework that is agnostic to any particular front-end strategy(s), and make it easy for developers to customize and plug in their open source platform(s) of choice.<\/p>\n<h2 id=\"tags\"><\/h2>\n<h2 id=\"github-code-repo\">Github Code Repo<\/h2>\n<p><a href=\"https:\/\/github.com\/erikschlegel\/sails-generate-reactjs\">https:\/\/github.com\/erikschlegel\/sails-generate-reactjs<\/a><\/p>\n<h2 id=\"overview-of-the-solution\">Overview of the solution<\/h2>\n<p>Sails has a concept called \u201cgenerators\u201d, which allow developers to extend and create a templated solution to fit their needs. This project\u2019s custom generator uses ReactJS as the toolset to create front-end components; also plugged in are other battle-tested open source products to cover testing, web asset management and continuous integration.<\/p>\n<p>This project solves the need for developers to have a consistent working environment. The framework offers a powerful starting point that is easily extensible, and enables developers to reconfigure the project generator to plug in the tech stack they choose. This repo also comes packaged with Bootstrap 3 and LESS for CSS pre-processing, so you have the option available for a responsive and user-friendly front-end layout template to start with. Some noteworthy Bootstrap 3 sites are showcased in the <a href=\"http:\/\/expo.getbootstrap.com\/\">Bootstrap Expo<\/a>.<\/p>\n<p>This repo supports test driven development practices, which encourages simple design and inspires confidence and reliability. The TDD cycle entails an iterative process of first writing unit tests that validate user features, then writing production code that\u2019s continuously being validated (<em>against unit tests<\/em>); real-time testing results are provided throughout development. Test-driven development offers more than just simple validation, but can also drive the design of a service and\/or program and makes refactoring a whole lot easier. By focusing on unit tests first, developers must think up front about how users will use their program. This also helps avoid conflicts where one developer\u2019s local change(s) breaks another developer\u2019s build. Mocha, Protractor, Istanbul and PhantomJS are bundled with this project as the test harness.<\/p>\n<p>Because the framework uses Travis CI for build management, all unit tests are executed for each GIT commit and the team can be notified of any failed builds via Slack or email. We will also took a look at Deis as an exploration exercise to identify opportunities to take continuous integration one step further.<\/p>\n<p>Potential future extensions using Microsoft Kudu to synchronize an Azure web site with a successful Travis CI build.<\/p>\n<p>The steps to use this framework on your local environment are listed below.<\/p>\n<h2 id=\"installation\">Installation<\/h2>\n<ul>\n<li>Update your .sailsrc file<\/li>\n<li>Create a file named .sailsrc\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code><span class=\"p\">{<\/span>\r\n  <span class=\"nt\">\"generators\"<\/span> <span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"nt\">\"modules\"<\/span> <span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n          <span class=\"nt\">\"frontend\"<\/span> <span class=\"p\">:<\/span> <span class=\"s2\">\"sails-generate-reactjs\"<\/span>\r\n      <span class=\"p\">}<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<\/div>\n<\/li>\n<\/ul>\n<p><strong>Note<\/strong>: for Linux or Ubuntu environments, you\u2019ll need to run all the commands below with sudo (<em>i.e. sudo npm install vs npm install<\/em>).<\/p>\n<p><strong>On the command line<\/strong><\/p>\n<ol>\n<li>Install the project from the published NPM module.<\/li>\n<\/ol>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>$ (Windows) npm install -g sails\r\n$ (Windows) npm install -g sails-generate-reactjs\r\n$ (Linux) sudo npm install -g sails\r\n$ (Linux) sudo npm install -g sails-generate-reactjs\r\n<\/code><\/pre>\n<\/div>\n<p>3.This command will create your Sails Site<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>$ (Windows) sails new &lt;%-newAppName&gt; --force\r\n$ (Linux) sudo sails new &lt;%-newAppName&gt; --force\r\n<\/code><\/pre>\n<\/div>\n<ol>\n<li>This command will install all packages and dependencies.<\/li>\n<\/ol>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>$ cd &lt;%-newAppName&gt;\r\n$ (Windows) npm install\r\n$ (Linux) sudo npm install\r\n<\/code><\/pre>\n<\/div>\n<ol>\n<li>Fire up your web server<\/li>\n<\/ol>\n<p><code class=\"highlighter-rouge\">$ sails lift<\/code><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/cse\/wp-content\/uploads\/sites\/55\/2020\/03\/2015-07-21-Building-an-enterprise-web-app-with-continuous-azure-integration_images-image001.jpg\" alt=\"Figure 1\" \/><\/p>\n<p>You should see this message coming back from Sails to confirm that your site is ready for use.<\/p>\n<p>You can access your new site by accessing it at <code class=\"highlighter-rouge\">http:\/\/localhost:1337<\/code>.<\/p>\n<h2 id=\"implementation\">Implementation<\/h2>\n<p>Sails is delivered with a baseline site generator, and a standard set of GRUNT tasks for building and packaging the assets of your web site. This framework is an extension of that baseline, and provides a bower template and NPM package template file that can be overridden by the developer.<\/p>\n<p>Asset Packages<\/p>\n<p>Bower template file \u2013 <strong>templates\/bower.ejs<\/strong><\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code><span class=\"p\">{<\/span>\r\n  <span class=\"nt\">\"name\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"&lt;%= appName %&gt;\"<\/span><span class=\"p\">,<\/span>\r\n  <span class=\"nt\">\"version\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"0.0.0\"<\/span><span class=\"p\">,<\/span>\r\n  <span class=\"nt\">\"authors\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span>\r\n    <span class=\"s2\">\"&lt;%= author %&gt;\"<\/span>\r\n  <span class=\"p\">],<\/span>\r\n  <span class=\"nt\">\"moduleType\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span>\r\n    <span class=\"s2\">\"globals\"<\/span>\r\n  <span class=\"p\">],<\/span>\r\n  <span class=\"nt\">\"license\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"MIT\"<\/span><span class=\"p\">,<\/span>\r\n  <span class=\"nt\">\"dependencies\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nt\">\"bootstrap\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"~3.3.4\"<\/span><span class=\"p\">,<\/span>\r\n    <span class=\"nt\">\"fontawesome\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"~4.3.0\"<\/span><span class=\"p\">,<\/span>\r\n    <span class=\"nt\">\"sails.io.js\"<\/span> <span class=\"p\">:<\/span> <span class=\"s2\">\"*\"<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<\/div>\n<p>The default provided bower file includes dependencies for fontawesome and bootstrap, which will be installed when you run Sails new.<\/p>\n<p>Node Package Dependencies<\/p>\n<p>Node Package.json template \u2013 <strong>templates\/package.json<\/strong><\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>   \"dependencies\": {\r\n    \"sails\": \"~0.11.0\",\r\n    \"sails-disk\": \"~0.10.0\",\r\n    \"rc\": \"^0.5.5\",\r\n    \"include-all\": \"~0.1.3\",\r\n    \"ejs\": \"~0.8.4\",\r\n    \"grunt\": \"^0.4.2\",\r\n    \"grunt-sync\": \"0.0.8\",\r\n    \"grunt-contrib-copy\": \"^0.5.0\",\r\n    \"grunt-contrib-clean\": \"^0.5.0\",\r\n    \"grunt-contrib-concat\": \"^0.3.0\",\r\n    \"grunt-sails-linker\": \"^0.9.6\",\r\n    \"grunt-contrib-jst\": \"*\",\r\n    \"grunt-contrib-watch\": \"^0.5.3\",\r\n    \"grunt-contrib-uglify\": \"^0.4.1\",\r\n    \"lodash\" : \"*\",\r\n    \"grunt-contrib-cssmin\": \"^0.9.0\",\r\n    \"grunt-contrib-less\": \"^0.11.1\",\r\n    \"react\": \"^0.13.3\",\r\n    \"react-bootstrap\": \"^0.20.3\",\r\n    \"grunt-babel\": \"^5.0.0\",\r\n    \"grunt-browserify\": \"^3.8.0\",\r\n    \"grunt-react\": \"^0.12.2\",\r\n    \"grunt-shell\": \"^1.1.2\",\r\n    \"grunt-contrib-coffee\": \"^0.10.1\"\r\n  },\r\n  \"scripts\": {\r\n    \"start\": \"node app.js\",\r\n    \"debug\": \"node debug app.js\",\r\n    \"test\": \"mocha -b\"\r\n  },\r\n<\/code><\/pre>\n<\/div>\n<p>These are the default node packages installed with your app, and can be overridden by the developer. The baseline comes included with grunt modules necessary for build management tasks, testing(<em>mocha<\/em>) and code quality checks_(ESLint_).<\/p>\n<p>Continuous Integration<\/p>\n<p>Travis configuration template &#8211; <strong>.travis.yml<\/strong><\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>language: node_js\r\nnode_js:\r\n  - \"0.12\"\r\nsudo: false\r\n\r\nbefore_install:\r\n  - \"export DISPLAY=:99.0\"\r\n  - \"npm install -g sails\"\r\n  - \"npm install -g sails-generate-reactjs\"\r\n  - \"sleep 10\" # give server time to start\r\n  - \"npm install -g grunt\"\r\n  - \"sails new travisSite --force\"\r\n\r\ninstall:\r\n - \"cd travisSite\"\r\n - \"npm install\"\r\n\r\nscript:\r\n - \"sails lift\"\r\n\r\nbranches:\r\n  only:\r\n    - master\r\nmatrix:\r\n  fast_finish: true\r\n<\/code><\/pre>\n<\/div>\n<ul>\n<li>To enable continuous integration with Travis, your app will need two things. One, a .travis.yml file and two, an enabled account on the <a href=\"https:\/\/travis-ci.org\/\">Travis portal<\/a> (<em>this part cannot be automated<\/em>). You\u2019ll find a .travis.yml file in your working directory that a developer controls. By default, Travis will invoke npm test (<em>listed above<\/em>) on every code commit, build your app on its VM, and a development team is notified of the results. Travis supports .NET builds as well.<\/li>\n<\/ul>\n<p>Front End Assets \/ Layout (<em>Bootstrap 3 + ReactJS Option is available<\/em>)<\/p>\n<p>The site will come bundled with a starter <a href=\"http:\/\/getbootstrap.com\/examples\/cover\/\">bootstrap template<\/a>, which is fully customizable. The template location can be found within \u2018working directory\/views\/homepage.ejs\u2019. You\u2019re free to use any other templating library, like Semantic UI, in place of bootstrap.<\/p>\n<p><strong>App.js<\/strong> (<em>this is only an example to illustrate a sample react component<\/em>)<\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>var React = require('react');\r\nvar LikeButton = React.createClass({\r\n  getInitialState: function() {\r\n    return {liked: false};\r\n  },\r\n  handleClick: function(event) {\r\n    this.setState({liked: !this.state.liked});\r\n  },\r\n  render: function() {\r\n    var text = this.state.liked ? 'like' : 'haven't liked';\r\n    return (\r\n&lt;p onClick={this.handleClick}&gt;\r\n        You {text} this. Click to toggle.\r\n&lt;\/p&gt;\r\n);\r\n  }\r\n});\r\n\r\nReact.render(\r\n  &lt;LikeButton \/&gt;,\r\n  document.getElementById('example')\r\n);\r\n<\/code><\/pre>\n<\/div>\n<p>If a developer chooses to use ReactJS as its component framework, Browserify is setup to pull in React components referenced at \u2018working directory\/assets\/app\/app.js\u2019 . A sample app.js file with a component defined is shown above. The Browserify location can be configured within \u2018working directory\/tasks\/pipeline.js\u2019<\/p>\n<p>Test Driven Development<\/p>\n<p>All unit tests are re-invoked when any of your source files change, and the result of the test run will be available on the node console. Mocha is flexible with providing fine-grained controls to developers with its reporting capabilities of test results.<\/p>\n<p><strong>\/test\/components\/LikeButton.js<\/strong><\/p>\n<div class=\"highlighter-rouge\">\n<pre class=\"highlight\"><code>var assert = require(\"assert\");\r\nvar React = require('react\/addons');\r\nvar LikeButtonComponent = require('.\/components\/LikeButton');\r\nvar TestUtils = React.addons.TestUtils;\r\n\r\ndescribe('TestSet1', function(){\r\n  describe('#React Like Button Feature Test Suite()', function(){\r\n    it('Changes the text after click', function(){\r\n       \/\/ Render a sample like button onto te dom\r\n       var button = TestUtils.renderIntoDocument(\r\n          &lt;LikeButton \/&gt;\r\n       );\r\n\r\n       var buttonComp = TestUtils.findRenderedDOMComponentWithTag(button);\r\n\r\n       assert.equal(buttonComp.getDOMNode().textContent.indexOf('You havent''t liked')&gt;-1, true);\r\n\r\n       TestUtils.Simulate.click(button);\r\n\r\n       buttonComp = TestUtils.findRenderedDOMComponentWithTag(button);\r\n\r\n       assert.equal(buttonComp.getDOMNode().textContent.indexOf('You like this')&gt;-1, true);\r\n    })\r\n  })\r\n})\r\n<\/code><\/pre>\n<\/div>\n<h2 id=\"challenges\">Challenges<\/h2>\n<p>Sails is a powerful framework that scaffolds a fully functional enterprise Node app that\u2019s easily configurable. The main challenge I faced when working with Sails was the limited documentation. This forced me to crawl through the source code to answer questions and address issues I encountered. There were also only a couple examples where other engineers built custom Sails Generators. I tried to simplify some of the SailsJS issues that I ran into by abstraction and customizable hooks into Sails that can be leveraged in the sails-generate-reactjs project.<\/p>\n<h2 id=\"technologies-used-in-this-project\">Technologies used in this project<\/h2>\n<p>SailsJS, Socket.io, Express, Bower, NodeJS, NPM, Browserify, Handlerbars, ESLint, Babel, Kudu, Azure, Travis CI, Mocha, Protractor, Istanbul, ReactJS, Bootstrap<\/p>\n<h2 id=\"opportunities-for-reuse\">Opportunities for Reuse<\/h2>\n<p>This project provides developers with a starting point to scaffold a Node JS Web application, plug in additional packages, and customize the base install so the development environment fits the needs of their project.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Creating a framework to bootstrap enterprise single page applications with continuous Azure integration.<\/p>\n","protected":false},"author":21362,"featured_media":12660,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[16],"tags":[60,112,171,173,191,217,230,260,275,277,298,307,317,362,383],"class_list":["post-2187","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops","tag-azure","tag-browserify","tag-eslint","tag-express","tag-grunt","tag-istanbul","tag-kudu","tag-mocha","tag-node","tag-npm","tag-protractor","tag-reactjs","tag-sailsjs","tag-travis-ci","tag-web-development"],"acf":[],"blog_post_summary":"<p>Creating a framework to bootstrap enterprise single page applications with continuous Azure integration.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts\/2187","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/users\/21362"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/comments?post=2187"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts\/2187\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/media\/12660"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/media?parent=2187"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/categories?post=2187"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/tags?post=2187"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}