<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>React on dwmkerr.com</title><link>https://dwmkerr.com/tags/react/</link><description>Recent content in React on dwmkerr.com</description><generator>Hugo -- gohugo.io</generator><language>en-uk</language><managingEditor>Dave Kerr</managingEditor><copyright>Copright &amp;copy; Dave Kerr</copyright><lastBuildDate>Mon, 03 Apr 2017 11:14:58 +0000</lastBuildDate><atom:link href="https://dwmkerr.com/tags/react/index.xml" rel="self" type="application/rss+xml"/><item><title>Tips and Tricks for Beautifully Simple Mobile App CI</title><link>https://dwmkerr.com/tips-and-tricks-for-beautifully-simple-mobile-app-ci/</link><pubDate>Mon, 03 Apr 2017 11:14:58 +0000</pubDate><guid>https://dwmkerr.com/tips-and-tricks-for-beautifully-simple-mobile-app-ci/</guid><description>&lt;p&gt;In this article I&amp;rsquo;m going to demonstrate some simple tips and tricks which will help you build and maintain beautifully simple mobile build pipelines. These techniques can be applied to different mobile app technologies and integrated into almost any build system:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/0-sample-index.png" alt="Sample App Index"&gt;&lt;/p&gt;
&lt;p&gt;Each tip is demonstrated in the sample apps in the &lt;a href="https://github.com/dwmkerr/beautifully-simple-app-ci"&gt;dwmkerr/beautifully-simple-app-ci&lt;/a&gt; repo.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="#TheChallengesOfMobileAppCI"&gt;The Challenges of Mobile App CI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#Tip1EmbraceMakefilesForConsistency"&gt;Tip 1 - Embrace Makefiles for Consistency&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#Tip2ControlVersionNumbersWithATouchCommand"&gt;Tip 2 - Control Version Numbers with a &amp;lsquo;Touch&amp;rsquo; Command&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#tip3controlappiconswithalabelcommand"&gt;Tip 3 - Control App Icons with a &amp;lsquo;Label&amp;rsquo; Command&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#Tip4SupportConfigurableAppIds"&gt;Tip 4 - Support Configurable App Ids&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#Tip5DocumentDocumentDocument"&gt;Tip 5 - Document, Document, Document&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#/conclusion"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="the-challenges-of-mobile-app-ci"&gt;The Challenges of Mobile App CI&lt;/h2&gt;
&lt;p&gt;Conceptually, a mobile app CI pipeline is pretty simple:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/1-basic-ci.png" alt="Basic CI Pipeline"&gt;&lt;/p&gt;
&lt;p&gt;We take our code, perform some kind of validation (such as testing, linting, whatever), generate our artifacts and then deploy them to some devices.&lt;/p&gt;
&lt;p&gt;Often though there&amp;rsquo;s a bit more to it than that:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/2-basic-not-basic-1.png" alt="Basic CI is not Basic"&gt;&lt;/p&gt;
&lt;p&gt;Our source code has some metadata associated with it at the point in time you create your binaries, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The SHA, which uniquely identifies your exact location in the source history.&lt;/li&gt;
&lt;li&gt;The branch, which may have some &lt;em&gt;semantic&lt;/em&gt; meaning for your project, for example &lt;code&gt;master&lt;/code&gt; meaning &amp;lsquo;production&amp;rsquo; or &lt;code&gt;alpha&lt;/code&gt; meaning your current unstable public build.&lt;/li&gt;
&lt;li&gt;A tag, which may represent something like a semver, or may have more project-specific meaning.&lt;/li&gt;
&lt;li&gt;A version, which might be in something like a &lt;code&gt;package.json&lt;/code&gt; or embedded in your project files for iOS or Android.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When we build we have to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Think about how we test and validate&lt;/li&gt;
&lt;li&gt;Think about how we sign&lt;/li&gt;
&lt;li&gt;Handle package names and bundle ids, which can cause headaches if you are going to install multiple &lt;em&gt;versions&lt;/em&gt; of an app (e.g. dev and UAT builds)&lt;/li&gt;
&lt;li&gt;Consider build numbers and version number&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So even the &amp;lsquo;basic&amp;rsquo; CI isn&amp;rsquo;t all that basic. The rest of this article is a set of tips and techniques which I have found useful when developing mobile apps.&lt;/p&gt;
&lt;h2 id="tip-1---embrace-makefiles-for-consistency"&gt;Tip 1 - Embrace Makefiles for Consistency&lt;/h2&gt;
&lt;p&gt;There are a raft of platform and framework specific tools and interfaces we will have to use in mobile projects. XCode, Gradle, NPM, framework specific CLIs, tools such as Fastlane, etc etc.&lt;/p&gt;
&lt;p&gt;If you ensure that your main &amp;rsquo;entrypoint&amp;rsquo; to key operations is a recipe in a makefile, you can provide a degree of consistency to mobile projects. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;make build&lt;/code&gt; - Creates an IPA and APK, saving them to the &lt;code&gt;./artifacts&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;make test&lt;/code&gt; - Runs all test suites.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;make deploy&lt;/code&gt; - Deploys the binaries.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A &lt;code&gt;makefile&lt;/code&gt; for such commands might look like this:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;test:
# Run all the tests.
npm test
build:
# Create the apk, copy to artifacts.
cd android &amp;amp;&amp;amp; ./gradlew assembleRelease &amp;amp;&amp;amp; cd ..
cp -f ./android/app/build/outputs/apk/myapp.apk ./artifacts
# Create the ipa, copy to artifacts.
cd ./ios; fastlane gym --scheme &amp;#34;app&amp;#34; --codesigning_identity &amp;#34;$(CODE_SIGNING_IDENTITY)&amp;#34;; cd ../;
cp -f ./ios/myapp.ipa ./artifacts
deploy:
# Push to TestFairy.
curl https://app.testfairy.com/api/upload \
-F api_key=&amp;#39;$(API_KEY)&amp;#39; \
-F &amp;#34;file=@./artifacts/myapp.apk&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is a slightly shortened snippet, you can see a variety of working examples in the git repo:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/dwmkerr/beautifully-simple-app-ci"&gt;github.com/dwmkerr/beautifully-simple-app-ci&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The first sample in the above repo demonstrates using makefiles to handle key commands for a React Native app. In the example, CircleCI is used to handle automatic builds on code changes, and the apps themselves are distributed automatically to testers&amp;rsquo; devices with TestFairy.&lt;/p&gt;
&lt;p&gt;The nice feature is that the bulk of the logic is in the main repo source, in the &lt;code&gt;makefile&lt;/code&gt; - the CI tool simply orchestrates it. Developers can run &lt;em&gt;exactly&lt;/em&gt; the same commands on their local machine.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://github.com/dwmkerr/beautifully-simple-app-ci/blob/master/1_react_native_app/README.md"&gt;&lt;code&gt;README.md&lt;/code&gt;&lt;/a&gt; immediately draws attention to the makefile commands:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/3-tip1-readme.png" alt="Screenshot of the README.md file"&gt;&lt;/p&gt;
&lt;p&gt;The makefiles do most of the work, that makes setting up CircleCI almost trivial. Here&amp;rsquo;s a snippet of its config:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# Tell Circle where we keep our artifacts.
general:
artifacts:
- ./artifacts
# When we test, we build the android app and test it.
test:
override:
- make build-android
- make test
# If there are any changes to the master branch, push a new version
# of the app.
deployment:
master:
branch: [master]
commands:
- make deploy-android
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Our commands are android specific at this stage as Circle don&amp;rsquo;t support iOS builds on their free plan&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;. Later samples which use other build systems demonstrate Android &lt;em&gt;and&lt;/em&gt; iOS.&lt;/p&gt;
&lt;p&gt;The CI automatically tests and builds whenever we have new code commits:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/4-tip1-circle.png" alt="Screenshot of CircleCI and the artifacts"&gt;&lt;/p&gt;
&lt;p&gt;Also, if a commit is made to the &lt;code&gt;master&lt;/code&gt; branch, our new app is automatically pushed to TestFairy, which can be configured to automatically update the test team:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/5-tip1-testfairy.png" alt="Screenshot of TestFairy"&gt;&lt;/p&gt;
&lt;p&gt;Makefile syntax is close enough to shell scripting that simple operations are generally straightforward&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt; to implement. The approach is also perfectly valid for server side code and almost any project.&lt;/p&gt;
&lt;p&gt;Teams with many projects can build consistent patterns and syntax for building. Take a look at the image below:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/Simple-Docker-Image-CI.png" alt="Docker Workflow"&gt;&lt;/p&gt;
&lt;p&gt;This is from my article on &lt;a href="http://www.dwmkerr.com/simple-continuous-integration-for-docker-images/"&gt;Simple Continuous Integration for Docker Images&lt;/a&gt; - where exactly the same principles are applied.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In Summary&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Makefiles allow you to provide an entrypoint for common app CI tasks which is framework and toolkit agnostic&lt;/li&gt;
&lt;li&gt;Being able to run the individual &lt;em&gt;steps&lt;/em&gt; of a CI build on a local machine makes it easier for developers to work with the pipeline&lt;/li&gt;
&lt;li&gt;By having a CI platform only need to handle the orchestration of these simple steps, we are less tied to specific platforms and can reduce lock-in&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We&amp;rsquo;ll see more interesting makefile recipes as we get into the other tips.&lt;/p&gt;
&lt;h2 id="tip-2---control-version-numbers-with-a-touch-command"&gt;Tip 2 - Control Version Numbers with a &amp;lsquo;Touch&amp;rsquo; command&lt;/h2&gt;
&lt;p&gt;iOS and Android apps have both a &lt;em&gt;version number&lt;/em&gt; and a &lt;em&gt;build number&lt;/em&gt;. We might have other files in our project with version numbers too (such as a &lt;code&gt;package.json&lt;/code&gt; file).&lt;/p&gt;
&lt;p&gt;It can be very useful to have a way of keeping these version numbers in sync. Again, we can use a makefile recipe:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;make touch
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This command will vary in implementation depending on your platform. For example, this would be all that is needed for a Cordova based project:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# The version in package.json is the &amp;#39;master&amp;#39; version.
VERSION ?= $(shell cat package.json | jq --raw-output .version)
BUILD_NUM ?= 0
touch:
$(info &amp;#34;Touching to version $(VERSION) and build number $(BUILD_NUM).&amp;#34;)
sed -i &amp;#34;&amp;#34; -e &amp;#39;s/android-versionCode=\&amp;#34;[0-9]*\&amp;#34;/android-versionCode=\&amp;#34;$(BUILD_NUM)\&amp;#34;/g&amp;#39; ./config.xml
sed -i &amp;#34;&amp;#34; -e &amp;#39;s/ios-CFBundleVersion=\&amp;#34;[0-9]*\&amp;#34;/ios-CFBundleVersion=\&amp;#34;$(BUILD_NUM)\&amp;#34;/g&amp;#39; ./config.xml
sed -i &amp;#34;&amp;#34; -e &amp;#39;s/version=\&amp;#34;[.0-9a-zA-Z]*\&amp;#34;/version=\&amp;#34;$(VERSION)&amp;#34;/g&amp;#39; ./config.xml
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Notice we don&amp;rsquo;t really need complex tools for a job like this, &lt;code&gt;sed[^3]&lt;/code&gt; is sufficient to quickly make changes to config files.&lt;/p&gt;
&lt;p&gt;This works very nicely with build systems, many of which provide a build number as an environment variable. For example, we can add a build number with TravisCI like so:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;env:
- BUILD_NUM=$TRAVIS_BUILD_NUMBER
script:
- make touch
- make test
- make build-android
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To go into more detail, we&amp;rsquo;ll look at the second sample in the git repo, which is a Cordova App. This sample will always set the build number in both apps and the build version to whatever is present in the &lt;code&gt;package.json&lt;/code&gt; file. That means you can do things like this:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ npm version minor # Bump the version
v0.1.0
$ BUILD_NUM=3 make build &amp;amp;&amp;amp; make deploy # Build and deploy the apps
...
done
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And all of the version numbers and build numbers are updated and the apps are deployed. In this example project, they&amp;rsquo;re deployed to HockeyApp:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/6-hockey-app.png" alt="Screenshot of the newly versioned apps in HockeyApp"&gt;&lt;/p&gt;
&lt;p&gt;This build runs on TravisCI, so only builds the Android version. You can clone the code and build the iOS version (and deploy it) using the makefile.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In Summary&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There will come a point in your project development where you&amp;rsquo;ll need to handle version numbers, having a command to explicitly deal with this adds rigour to this process&lt;/li&gt;
&lt;li&gt;Build numbers are just as important as version numbers during development, ensuring your CI build number is baked into your artifacts is critical for troubleshooting and control&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="tip-3---control-app-icons-with-a-label-command"&gt;Tip 3 - Control App Icons with a &amp;lsquo;Label&amp;rsquo; Command&lt;/h1&gt;
&lt;p&gt;When you are working in a larger team, it can be very useful to label your app icon so that team members know exactly what version of the app they are using. This is often the case if you are working in a team where features or bugfixes are being deployed rapidly.&lt;/p&gt;
&lt;p&gt;You might label your icons with build numbers, SHAs, branch names, versions, tags, or even something custom such as &amp;lsquo;QA&amp;rsquo; or &amp;lsquo;UAT&amp;rsquo; for different versions of your app. Here are a few examples:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/8-framed-labelled-icons.png" alt="Labelled Icons Screenshot"&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve found this to be very useful, so created a command-line tool called &amp;lsquo;&lt;a href="github.com/dwmkerr/app-icon"&gt;app-icon&lt;/a&gt;&amp;rsquo; to help with the task:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/dwmkerr/app-icon"&gt;github.com/dwmkerr/app-icon&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This tool has a &lt;code&gt;label&lt;/code&gt; command to add a label, and a &lt;code&gt;generate&lt;/code&gt; command to generate icons of all different sizes. This means you can add recipes like this to your &lt;code&gt;makefile&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;VERSION ?= $(shell cat package.json | jq --raw-output .version)
BUILD_NUM ?= 0 # This might come from Circle, Travis or Whatever...
label:
$(info Labeling icon with &amp;#39;$(VERSION)&amp;#39; and &amp;#39;$(BUILD_NUM)&amp;#39;...)
app-icon label -i base-icon.png -o icon.png --top $(VERSION) --bottom $(BUILD_NUM)
app-icon generate -i icon.png
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Each sample app labels its icon in a different way:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The &lt;a href="./1_react_native_app/"&gt;React Native App&lt;/a&gt; puts the short Git SHA on the bottom of the icon.&lt;/li&gt;
&lt;li&gt;The &lt;a href="./2_ionic_app/"&gt;Ionic App&lt;/a&gt; puts the &lt;code&gt;package.json&lt;/code&gt; version at the top of the icon.&lt;/li&gt;
&lt;li&gt;The &lt;a href="./3_native_app"&gt;Native App&lt;/a&gt; puts an environment label at the top of the icon, and the build number at the bottom.&lt;/li&gt;
&lt;li&gt;The &lt;a href="./4_xamarinapp"&gt;Xamarin App&lt;/a&gt; includes the configurable app environment (this is detailed in the next tip) and build number&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There are references to each sample and the associated code in the &lt;code&gt;README.md&lt;/code&gt; at:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/dwmkerr/beautifully-simple-app-ci"&gt;github.com/dwmkerr/beautifully-simple-app-ci&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As a quick example, the Pure Native App runs this code prior to each build:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;BUILD_NUM&lt;span style="color:#f92672"&gt;=&lt;/span&gt;BUDDYBUILD_BUILD_NUMBER make label
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This app uses BuddyBuild as a build system, meaning we can just drop this line in the &lt;a href="./buddybuild_postclone.sh"&gt;&lt;code&gt;buddybuild_postclone.sh&lt;/code&gt;&lt;/a&gt; script. You can see the labeled icons directly in the BuddyBuild UI:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/12-buddybuild-icons.png" alt="BuddyBuild Icons"&gt;&lt;/p&gt;
&lt;p&gt;The Android build is currently having some issues due to fonts being accessible by the labelling tool (which uses ImageMagick under the hood), with any luck this issue will be fixed soon. This seems to be an issue with the BuddyBuild ImageMagick installation rather than the labelling code itself, which is running fine on all of the other builds!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In Summary&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A little bit of time invested in managing your app icon can potentially save many hours if you are rapidly iterating on apps&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://github.com/dwmkerr/app-icon"&gt;&lt;code&gt;app-icon&lt;/code&gt;&lt;/a&gt; tool can help you quickly label and generate icons&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="tip-4---support-configurable-app-ids"&gt;Tip 4 - Support Configurable App Ids&lt;/h1&gt;
&lt;p&gt;Another trick I&amp;rsquo;ve found useful is to have a command which automatically updates your iOS Bundle ID or Android Application ID. This can be handy when you have multiple versions of an app (such as a QA build, dev build, UAT build or whatever).&lt;/p&gt;
&lt;p&gt;If you have users who need to have different versions of your app on their phones then this is actually a necessary step (at least for iOS), as you cannot have multiple versions of an app with the same ID installed.&lt;/p&gt;
&lt;p&gt;Often, I will aim to have a standard &amp;lsquo;base id&amp;rsquo;, such as:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;com.dwmkerr.myapp
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and then simply append whatever the &amp;lsquo;flavour&amp;rsquo; of my app is to the end of the id:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;com.dwmkerr.myapp_qa # The QA build...
com.dwmkerr.myapp_uat # The UAT build...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The base id is then reserved for the master build, which is what goes into production.&lt;/p&gt;
&lt;p&gt;Just like with all of the other tricks, I tend to use a recipe in the &lt;code&gt;makefile&lt;/code&gt; to do the heavy lifting, and then leave the build system to orchestrate the commands (we&amp;rsquo;ll see more of this later). Here&amp;rsquo;s how a recipe will typically look (this comes from the fourth sample, which is a Xamarin App):&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ENV ?= production
# Set the app id, with the &amp;#39;production&amp;#39; environment implying the unaltered &amp;#39;base&amp;#39; id.
ifeq ($(ENV),production)
APP_ID=com.dwmkerr.xamarinapp
else
APP_ID=com.dwmkerr.xamarinapp_$(ENV)
endif
name:
$(info Naming app &amp;#39;$(APP_ID)&amp;#39;...)
sed -i.bak &amp;#39;s/com.dwmkerr.xamarinapp.*&amp;lt;/$(APP_ID)&amp;lt;/&amp;#39; iOS/Info.plist
sed -i.bak &amp;#39;s/com.dwmkerr.xamarinapp.*\&amp;#34;/$(APP_ID)\&amp;#34;/&amp;#39; Droid/Properties/AndroidManifest.xml
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This small recipe can be very useful in combination with other techniques. Ensuring your build respects the &lt;code&gt;ENV&lt;/code&gt; variable (or whatever you name your &amp;lsquo;flavour&amp;rsquo;) means that you can have different configurations for different environments, build multiple versions of the app, each with a distinct app icon, and distribute them to your team.&lt;/p&gt;
&lt;p&gt;In the screenshots below, you can see how the presence of the &lt;code&gt;ENV&lt;/code&gt; environment variable automatically updates the App ID (this is taken from the &lt;a href="./4_xamarinapp"&gt;Xamarin Sample&lt;/a&gt;, which orchestrates builds with Bitrise&lt;sup id="fnref1:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/9-bitrise.png" alt="The ENV Environment variable in Bitrise"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="images/10-bitrise-apps.png" alt="The built apps in Bitrise"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In Summary&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Configurable App Ids allow you to maintain isolated builds of your app for specific environments, even on the same physical device&lt;/li&gt;
&lt;li&gt;This tip must be used with caution, some features (such as iOS push notifications) will not work if the bundle id is changed (it can also cause issues if your provisioning profile does not use a wildcard)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="tip-5---document-document-document"&gt;Tip 5 - Document, Document, Document&lt;/h2&gt;
&lt;p&gt;Even teams which are great at documenting complex application code can sometimes be a bit lax when it comes to documenting build related code.&lt;/p&gt;
&lt;p&gt;Unfortunately, build related code will often need &lt;em&gt;more&lt;/em&gt; documentation than usual. Why is this?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is often &lt;em&gt;complex&lt;/em&gt; (spend any time working with the XCode commandline or provisioning profiles and you&amp;rsquo;ll likely agree)&lt;/li&gt;
&lt;li&gt;It is &lt;em&gt;rarely changed&lt;/em&gt; (often worked on heavily at the early stages of a project then not touched)&lt;/li&gt;
&lt;li&gt;It is &lt;em&gt;critical&lt;/em&gt; (when it breaks, teams are often blocked)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When something goes wrong with a build process, or needs to be changed, it is a real pain when only one person knows how the code works. Be rigorous with this code, make sure it is documented and reviewed, and share the knowledge around your team. I tend to like to have a table of commands as a quick index in the README.md file, and then heavily comment the code itself:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/11-document.png" alt="TODO"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In Summary&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Be rigorous with documentation, when things go wrong with CI code then people are often blocked&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Most of these tips are fairly explicit, there are detailed examples in the sample project. Familiarity with these patterns and techniques can be useful, but perhaps the most valuable takeaway would be to embrace the following principles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Developers should be able to run all of the key CI steps on their local machine, to be able to understand, adapt and improve the process&lt;/li&gt;
&lt;li&gt;When building more complex features, we should create small, simple units of work which can be composed into larger pipelines&lt;/li&gt;
&lt;li&gt;Complexity, if needed, should be in in code - not in &amp;lsquo;black box&amp;rsquo; CI tools (such as esoteric features for specific CI providers or Jenkins plugins). For example, CircleCI offers a Git Short SHA environment variable - but you can grab a short SHA with &lt;code&gt;git log -1 --format=&amp;quot;%h&amp;quot;&lt;/code&gt;, and the second approach works anywhere&lt;/li&gt;
&lt;li&gt;Use CI platforms to &lt;em&gt;orchestrate&lt;/em&gt; work, use makefiles and scripts to handle logic&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope this article has been useful, any thoughts or comments are always welcome!&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Footnotes&lt;/strong&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;I have successfully used this approach to build Android &lt;em&gt;and&lt;/em&gt; iOS from the same OSX build agent on their paid plan on a number of projects. The most straightforward way to do this is to have a single build run on OSX and create the Android app as well as the iOS app.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;Perhaps straightforward is an overstatement, but getting those who are familiar with shell scripting will have few difficulties. Those who are not will find a learning curve, but it is &lt;em&gt;very&lt;/em&gt; useful to at least get the basics of shell scripting learnt.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&amp;#160;&lt;a href="#fnref1:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>CodeProject</category></item><item><title>Moving from React + Redux to Angular 2</title><link>https://dwmkerr.com/moving-from-react-redux-to-angular-2/</link><pubDate>Mon, 25 Apr 2016 09:45:00 +0000</pubDate><guid>https://dwmkerr.com/moving-from-react-redux-to-angular-2/</guid><description>&lt;p&gt;I&amp;rsquo;ve just finished working on a very large project written in React and Redux. The whole team were new to both and we loved them.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m going to share my experiences of experimenting in Angular 2 with you, from the point of view of someone who needs a pretty compelling reason to move away from my JSX and reducers.&lt;/p&gt;
&lt;h1 id="the-journey-so-far"&gt;The Journey So Far&lt;/h1&gt;
&lt;p&gt;Let me highlight a few key moments in my UI development experiences, to give a bit of context to my ramblings.&lt;/p&gt;
&lt;p&gt;&lt;img src="images/Journey.jpg" alt="The Journey So Far"&gt;&lt;/p&gt;
&lt;p&gt;Reading about redux was a lightbulb moment for me - rather than a complex framework it&amp;rsquo;s a simply library to help apply a few common sense functional programming principles - state is immutable, functions apply predictable transformations to data to produce new data.&lt;/p&gt;
&lt;p&gt;Learning React took a little bit of getting used to, but not too much, it was quite a bit more simple than Angular anyway.&lt;/p&gt;
&lt;p&gt;Long story short, simple React components and rigorous state management has so far resulted in the most manageable and well written very large scale UIs I&amp;rsquo;ve worked on so far - can Angular 2 compete with this?&lt;/p&gt;
&lt;h1 id="first-step-with-angular-2---folder-structure-typescript-sublime-text"&gt;First Step with Angular 2 - Folder Structure, Typescript, Sublime Text&lt;/h1&gt;
&lt;p&gt;I checked out &lt;a href="https://angular.io/docs/ts/latest/quickstart.html"&gt;the pretty neat &amp;lsquo;Getting Started&amp;rsquo; guide from Angular&lt;/a&gt; which promised to get me started in five minutes.&lt;/p&gt;
&lt;p&gt;It didn&amp;rsquo;t take five minutes, there&amp;rsquo;s a few gotchas, so I&amp;rsquo;m going to give a condensed guide here.&lt;/p&gt;
&lt;h2 id="step-1-the-folder-structure"&gt;Step 1: The Folder Structure&lt;/h2&gt;
&lt;p&gt;The first few steps of the angular guide creates the following folder structure:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;|-- angular2-starter
|-- tsconfig.json
|-- typings.json
|-- package.json
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is the standard &lt;code&gt;package.json&lt;/code&gt; with some scripts ready to go. We also have &lt;code&gt;tsconfig.json&lt;/code&gt; to configure the typescript compiler and &lt;code&gt;typings.json&lt;/code&gt; to provide info to the compiler on where to get type information.&lt;/p&gt;
&lt;p&gt;You can check the code at this stage here:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/dwmkerr/angular2-starter/tree/step1"&gt;https://github.com/dwmkerr/angular2-starter/tree/step1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="images/Step1.png" alt="Step 1 GitHub Screenshot"&gt;&lt;/p&gt;
&lt;h2 id="node--npm-issues"&gt;Node &amp;amp; NPM Issues&lt;/h2&gt;
&lt;p&gt;At this stage the quickstart says you can run &lt;code&gt;npm install&lt;/code&gt; and all will be well:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/npm-install.png" alt="npm install screenshot"&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;npm ERR! cb() never called!
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Not so good! For the record I&amp;rsquo;m using NPM 3.7.3 installed via homebrew. This looks like a bug in Beta 15 (see &lt;a href="https://github.com/angular/angular/issues/8053"&gt;Issue #8053&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I fixed this by using &lt;em&gt;n&lt;/em&gt; to upgrade my node version:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ node -v
v5.9.0
$ npm install -g n # install &amp;#39;n&amp;#39; node version manager
$ sudo n latest
installed : v5.11.0
$ node -v
v5.11.0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now it &lt;code&gt;npm install&lt;/code&gt; runs OK.&lt;/p&gt;
&lt;h2 id="step-2-adding-components-and-configuring-sublime"&gt;Step 2: Adding Components and Configuring Sublime&lt;/h2&gt;
&lt;p&gt;The next steps of the walkthrough take us through adding an app component, a &lt;code&gt;main.ts&lt;/code&gt; file to bootstrap the application and an index file. You can check the updates here:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/dwmkerr/angular2-starter/tree/step2"&gt;https://github.com/dwmkerr/angular2-starter/tree/step2&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Essentially we now have:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;|-- angular2-starter
|-- tsconfig.json
|-- typings.json
|-- package.json
|-- index.html
|-- styles.css
|-- app
|-- main.ts
|-- app.component.ts
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;At this stage, running &lt;code&gt;npm start&lt;/code&gt; gives us a browerserified app to play with:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/Step2.png" alt="Step 2 Screenshot"&gt;&lt;/p&gt;
&lt;p&gt;Clear enough so far, although the code in Sublime is not looking so pretty:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/Step2Sublime.png" alt="Step 2 Sublime Text Screenshot"&gt;&lt;/p&gt;
&lt;p&gt;Quickly installing the &lt;a href="https://github.com/Microsoft/TypeScript-Sublime-Plugin"&gt;TypeScript plugin&lt;/a&gt; from Microsoft[^n] seems to do the trick:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/Step2SublimeFormatted.png" alt="Step 2 Sublime Text with TypeScript plugin"&gt;&lt;/p&gt;
&lt;p&gt;If you need more details, here&amp;rsquo;s a gist with the full setup for Sublime 3, assuming you&amp;rsquo;ve got nothing installed.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/dwmkerr/04fa8b8c15d049d0381e7798a79bcc45"&gt;https://gist.github.com/dwmkerr/04fa8b8c15d049d0381e7798a79bcc45&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;At this stage the app will run, we can see the basics of the Angular 2 syntax and start experimenting.&lt;/p&gt;
&lt;h2 id="step-3-adding-some-components"&gt;Step 3: Adding some components&lt;/h2&gt;
&lt;p&gt;At this stage the quick started guide starts going into more detail, guiding you through the process of creating multiple components. I decided to go off on my own here, with the rough plan of being able to write a set of goals for the day and turn it into a check-list[^n].&lt;/p&gt;
&lt;p&gt;Within not much time I had the some basic components, input and output, bindings and so on. Some screenshots:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/Goals-Screenshot-1.png" alt="Goals Screenshot 1"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="images/Goals-Screenshot-2-1.png" alt="Goals Screenshot 2"&gt;&lt;/p&gt;
&lt;p&gt;You can take a look at the code at this stage by checking out the &amp;lsquo;step3&amp;rsquo; branch:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/dwmkerr/angular2-starter/tree/step3"&gt;github.com/dwmkerr/angular2-starter/tree/step3&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="thoughts-so-far"&gt;Thoughts so far&lt;/h1&gt;
&lt;p&gt;For now, that&amp;rsquo;s all I&amp;rsquo;ve got time for. I&amp;rsquo;ve had a chance to get a feel for Angular 2, I&amp;rsquo;m going to come back to this in a few weeks and integrate Redux, maybe swap out System.JS for Webpack and do some experimenting.&lt;/p&gt;
&lt;p&gt;Opinions[^n] so far?&lt;/p&gt;
&lt;h3 id="not-sold-on-typescript"&gt;Not Sold on TypeScript&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ve used TypeScript in my mess around, rather than plain &amp;lsquo;ol JavaScript, to keep the experience authentic to the angular team&amp;rsquo;s goals of using TypeScript to help.&lt;/p&gt;
&lt;p&gt;So far, I&amp;rsquo;m not seeing an enormous benefit. Some of the extra information available to auto-completion in nice, but this is a tooling thing.&lt;/p&gt;
&lt;p&gt;JavaScript is not a static language, the TypeScript annotations I find slowing me down a little.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There&amp;rsquo;s so much extra domain specific &lt;em&gt;stuff&lt;/em&gt; in Angular 2 that people might be lost without it. But if your stuff is so complex you need to adapt the base language, is it &lt;strong&gt;too&lt;/strong&gt; complex?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="explicit-component-surface-areas-are-a-nice-idea"&gt;Explicit Component Surface Areas are a Nice Idea&lt;/h3&gt;
&lt;p&gt;When defining a component, you specify explicitly what comes &lt;em&gt;in&lt;/em&gt; (data) and what goes &lt;em&gt;out&lt;/em&gt; (events).&lt;/p&gt;
&lt;p&gt;This means that the surface area of a component (i.e. the part you touch if you interact with it programmatically) is well defined. This is a good thing.&lt;/p&gt;
&lt;p&gt;However, this is all handled with some pretty framework-specific stuff[^n]:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// e.g.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;GoalsBoxComponent&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Event we fire when the goals change.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;@&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Output&lt;/span&gt;() &lt;span style="color:#a6e22e"&gt;goalsChanged&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;EventEmitter&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Goal&lt;/span&gt;[]&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;EventEmitter&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// e.g.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;GoalListComponent&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Input is a set of goals to render.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;@&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Input&lt;/span&gt;() &lt;span style="color:#a6e22e"&gt;goals&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Goal&lt;/span&gt;[] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In a nutshell&amp;hellip;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Explicit component surface area is a cool idea.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;React does this too with the optional &lt;code&gt;propTypes&lt;/code&gt;, but it is not enforced. &lt;em&gt;However&lt;/em&gt;, how this is done in Angular has already gone through a few radical changes with some &lt;a href="https://github.com/angular/angular/pull/4435#issuecomment-144789359"&gt;lively debate&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="not-ready-for-production-yet"&gt;Not ready for production&amp;hellip; yet&lt;/h3&gt;
&lt;p&gt;There&amp;rsquo;s no standardised, documented way to test a component - nuff said. But things are evolving quickly.&lt;/p&gt;
&lt;h3 id="framework-fatigue"&gt;Framework Fatigue&lt;/h3&gt;
&lt;p&gt;Comparing React to Angular is unfair, one is a view library, one is a framework. But it&amp;rsquo;s worth pointing out this is a pretty complex framework. There&amp;rsquo;s a &lt;strong&gt;lot&lt;/strong&gt; of very domain specific stuff. See this documentation for an example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;li&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;ngFor&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;#hero of heroes&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From &lt;a href="https://angular.io/docs/ts/latest/tutorial/toh-pt2.html"&gt;the documentation&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The (*) prefix to ngFor indicates that the &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; element and its children constitute a master template.&lt;/p&gt;
&lt;p&gt;&amp;hellip;&lt;/p&gt;
&lt;p&gt;The # prefix before &amp;ldquo;hero&amp;rdquo; identifies the hero as a local template variable. We can reference this variable within the template to access a hero’s properties.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You&amp;rsquo;ll get used to it (if you have to), but I think it&amp;rsquo;s harder to &lt;em&gt;reason&lt;/em&gt; about than:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;render&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;div&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;props&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;goals&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;((&lt;span style="color:#a6e22e"&gt;goal&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;li&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;goal&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;}&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/li&amp;gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/div&amp;gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;OK fair enough, JSX is very specific, but the &lt;strong&gt;logic&lt;/strong&gt; (mapping an iterable) is JavaScript.&lt;/p&gt;
&lt;h1 id="wrapping-up"&gt;Wrapping Up&lt;/h1&gt;
&lt;p&gt;That&amp;rsquo;s it, for now. Next steps are to experiment more, see if it will play nice with Redux and share the next set of opinions.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d love to hear what you think, so drop your comments below!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Footnotes&lt;/strong&gt;&lt;/p&gt;</description><category>CodeProject</category></item><item><title>Getting Started with React &amp; ES6</title><link>https://dwmkerr.com/getting-started-with-react/</link><pubDate>Mon, 07 Sep 2015 19:44:54 +0000</pubDate><guid>https://dwmkerr.com/getting-started-with-react/</guid><description>&lt;p&gt;Feeling like having a go with Facebook&amp;rsquo;s hugely popular &lt;a href="http://facebook.github.io/react/"&gt;React&lt;/a&gt; framework but not sure where to start?&lt;/p&gt;
&lt;p&gt;In this post I&amp;rsquo;m going to build a simple React application from scratch - using &lt;a href="http://es6-features.org/"&gt;ECMAScript 6&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll put together the bare minimum skeleton of a site and keep the folder structure free of noise and clutter so that you can focus on the app code and not the tooling!&lt;/p&gt;
&lt;p&gt;The simple app we&amp;rsquo;ll build is at &lt;a href="https://github.com/dwmkerr/react-es6-starter"&gt;github.com/dwmkerr/react-es6-starter&lt;/a&gt;, or see &lt;a href="https://react-es6-starter.herokuapp.com"&gt;it live&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="building-the-code"&gt;Building the Code&lt;/h2&gt;
&lt;p&gt;Our goal will be to have a single &lt;code&gt;index.html&lt;/code&gt; file which includes our Javascript files. We&amp;rsquo;re aiming for something like this:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/Build-Process.png" alt="Build Process 1"&gt;&lt;/p&gt;
&lt;p&gt;But browsers don&amp;rsquo;t handle ES6 yet. So our loose files, which reference each other, are going to have to be transpiled into ES5 and bundled into a single file. We need a build process:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/Build-Process-2.png" alt="Build Process 2"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="webpack.github.io"&gt;Webpack&lt;/a&gt; can handle all of this for us. Given an entrypoint file, webpack will traverse all of the &lt;code&gt;require&lt;/code&gt; and &lt;code&gt;import&lt;/code&gt; statements and build a single bundle file. It also allows us to configure &amp;rsquo;loaders&amp;rsquo;, which let us pass these files through other tools:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/Build-Process-3.png" alt="Build Process 3"&gt;&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll need the following libraries:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="webpack.github.io"&gt;Webpack&lt;/a&gt; - the tool that handles the build process.&lt;/li&gt;
&lt;li&gt;&lt;a href="babeljs.io"&gt;Babel&lt;/a&gt; - an excellent ES6/ES7/JSX to ES5 transpiler.&lt;/li&gt;
&lt;li&gt;&lt;a href="github.com/babel/babel-loader"&gt;Babel Loader&lt;/a&gt; - the component which integrates Babel into our Webpack build.&lt;/li&gt;
&lt;li&gt;&lt;a href="github.com/ampedandwired/html-webpack-plugin"&gt;Html Webpack Plugin&lt;/a&gt; - a simple Webpack plugin which will copy our index file to our build folder and add a link to our Webpack bundle.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let&amp;rsquo;s install these modules:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm install --save webpack babel babel-loader html-webpack-plugin
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We&amp;rsquo;ll also need a webpack config file. By default webpack expects a file named &lt;code&gt;webpack.config.js&lt;/code&gt; to be in the root of the project. But every tool under the sun wants to stick its config file in the root of our project, and most of the time they&amp;rsquo;re just in the way.&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s put everything to do with our tooling in a &lt;code&gt;tooling&lt;/code&gt; folder instead. Create the file &lt;code&gt;webpack.config.js&lt;/code&gt; in a &lt;code&gt;tooling&lt;/code&gt; folder in the root of the project:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;path&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;require&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;path&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;module&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;exports&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Defines the entrypoint of our application.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;entry&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;path&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;resolve&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;__dirname&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;../src/app.js&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Bundle to a ./build/public/bundle.js file.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;output&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;path&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;path&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;resolve&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;__dirname&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;../build/public&amp;#39;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;filename&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;bundle.js&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Use babel for anything that is *.js or *.jsx.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;module&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;loaders&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;test&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/\.jsx?$/&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;loader&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;babel-loader&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;include&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;path&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;resolve&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;__dirname&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;../src&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;First we define our entry point - the first file which will actually be run if we run the final bundled script. This is the &lt;code&gt;app.js&lt;/code&gt; file we&amp;rsquo;ll create shortly. If &lt;code&gt;app.js&lt;/code&gt; includes other modules, Webpack will pick them up, if those modules include other modules, they will be picked up and so on.&lt;/p&gt;
&lt;p&gt;Next we specify that everything should be bundled into a &lt;code&gt;./build/public/bundle.js&lt;/code&gt; file (we&amp;rsquo;re going to use the convention that everything we can produce with our tools goes into &lt;code&gt;./build&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Finally, we specify that every file in &lt;code&gt;src&lt;/code&gt; which matches the &lt;code&gt;\.jsx?$&lt;/code&gt; regex will go through the babel loader.&lt;/p&gt;
&lt;h3 id="using-es6"&gt;Using ES6!&lt;/h3&gt;
&lt;p&gt;We&amp;rsquo;ve actually got enough now to use ES6. Create a file in &lt;code&gt;src&lt;/code&gt; called &lt;code&gt;index.html&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then create a &lt;code&gt;src/app.js&lt;/code&gt; file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;PI&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3.14&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;vals&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;].&lt;span style="color:#a6e22e"&gt;map&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; =&amp;gt; &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;document.&lt;span style="color:#a6e22e"&gt;body&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;innerText&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Pi is &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3.14&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34; and vals is &amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;vals&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Run the command &lt;code&gt;./node_modules/.bin/webpack --config ./tooling/webpack.config.js&lt;/code&gt; and our code is built, transpiled an moved to the build folder.&lt;/p&gt;
&lt;p&gt;Now we could serve this folder using any basic webserver. We are already using webpack, so the webpack dev server will do the trick. It uses exactly the same config file as the webpack tool:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;npm install --save-dev webpack-dev-server
./node_modules/.bin/webpack-dev-server --config ./tooling/webpack.config --inline
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The inline reloads the page when the source changes. We don&amp;rsquo;t need to tell the server where the files are, it knows that from the webpack config.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s stick these commands in our &lt;code&gt;package.json&lt;/code&gt; for convenience:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;scripts&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;start&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;webpack-dev-server --config ./tooling/webpack.config.js --inline --quiet&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;webpack&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;webpack --config tooling/webpack.config.js&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we can manually build with &lt;code&gt;npm run webpack&lt;/code&gt; and start our dev server with &lt;code&gt;npm start&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="adding-some-react"&gt;Adding some React&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s add a React component. Create a folder under &lt;code&gt;app&lt;/code&gt; called &lt;code&gt;home&lt;/code&gt; and add a &lt;code&gt;home.js&lt;/code&gt; file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;React&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;react&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;default&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Home&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;React&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Component&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;render&lt;/span&gt; () {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;div&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;h1&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;React&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ES6&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Starter&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/h1&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Welcome&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;to&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;the&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;React&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ES6&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Starter&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;home&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;page&lt;/span&gt;&lt;span style="color:#f92672"&gt;!&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/p&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/div&amp;gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is our first react component, which does nothing more than render some basic markup. We&amp;rsquo;ll use this as the starting point for our application.&lt;/p&gt;
&lt;p&gt;We can now take our &lt;code&gt;app.js&lt;/code&gt; file and render our Home component into the div. Here&amp;rsquo;s &lt;code&gt;app.js&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;React&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;react/addons&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Home&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;./home/home&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;React&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;render&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Home&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;, document.&lt;span style="color:#a6e22e"&gt;body&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s all there is to it! We&amp;rsquo;ve got a clean and simple starting point to begin playing with React. Before we look into things like state management and routing, let&amp;rsquo;s look into testing what we have so far.&lt;/p&gt;
&lt;h3 id="testing"&gt;Testing&lt;/h3&gt;
&lt;p&gt;Even the most simple app would be incomplete without looking into how we will deal with the testing.&lt;/p&gt;
&lt;p&gt;Many will recommend the &lt;a href="https://facebook.github.io/jest/"&gt;Jest&lt;/a&gt; framework to test React applications. However, it&amp;rsquo;s a bit more to learn and has some problems with NodeJS v0.12, so until we get Node v4 I&amp;rsquo;m going to keep things simple.&lt;/p&gt;
&lt;p&gt;First, we&amp;rsquo;ll install &lt;a href="http://karma-runner.github.io/"&gt;Karma&lt;/a&gt; as a test runner. We&amp;rsquo;ll use &lt;a href="http://jasmine.github.io/"&gt;Jasmine&lt;/a&gt; as as framework to write test cases and &lt;a href="http://phantomjs.org/"&gt;PhantomJS&lt;/a&gt; as a headless browser in which our tests will run. This means we&amp;rsquo;ll need to add some more dev dependencies:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm install --save-dev karma jasmine karma-webpack karma-jasmine karma-phantomjs-launcher
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can now create a &lt;code&gt;karma.config.js&lt;/code&gt; file in our &lt;code&gt;tooling&lt;/code&gt; folder:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;path&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;require&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;path&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;module&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;exports&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;config&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;config&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;set&lt;/span&gt;({
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;browsers&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;PhantomJS&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;files&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// We need to polyfill as PhantomJS doesn&amp;#39;t support &amp;#39;bind&amp;#39;.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;../node_modules/babel-core/browser-polyfill.js&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;../**/*.spec.js&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;frameworks&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;jasmine&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;preprocessors&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;../**/*.spec.js&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;webpack&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;reporters&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;progress&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;singleRun&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;webpack&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;module&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;loaders&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;test&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/\.jsx?$/&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;loader&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;babel-loader&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;include&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;path&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;resolve&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;__dirname&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;../src&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;webpackServer&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;noInfo&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So here we are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Loading a polyfill from babel core (sorry guys, one more &lt;code&gt;npm install --save-dev babel-core&lt;/code&gt;) which gives PhantomJS the &lt;code&gt;bind&lt;/code&gt; function (along with some others). This is needed as some of the testing code in the browser needs these features.&lt;/li&gt;
&lt;li&gt;Specifying that anything that ends in &lt;code&gt;.spec.js&lt;/code&gt; should be loaded.&lt;/li&gt;
&lt;li&gt;Running anything that ends in &lt;code&gt;.spec.js&lt;/code&gt; through webpack.&lt;/li&gt;
&lt;li&gt;Telling webpack to use babel.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Quite a bit of config, but we&amp;rsquo;re re-using the same webpack tooling as before. We run the code through webpack, which sends it through babel and builds ES5 we can test in the browser.&lt;/p&gt;
&lt;p&gt;With this in place, we can write a spec. Add &lt;code&gt;home.spec.js&lt;/code&gt; to the &lt;code&gt;home&lt;/code&gt; folder:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;React&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;react&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;$&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;jquery&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;import&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Home&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;from&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;./home.js&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;describe&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;Home&amp;#39;&lt;/span&gt;, () =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;it&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;should render to the DOM&amp;#39;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Create the &amp;lt;Home /&amp;gt; react component.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;component&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;React&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;render&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Home&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;, document.&lt;span style="color:#a6e22e"&gt;body&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Find the DOM element for the created component.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;node&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;React&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;findDOMNode&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;component&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Check the DOM looks how we&amp;#39;d expect it to.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;expect&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;$&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;node&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;children&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;h1&amp;#39;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;text&lt;/span&gt;()).&lt;span style="color:#a6e22e"&gt;toEqual&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;React Redux Starter&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What&amp;rsquo;s going on here? We just ask React to render our Home component directly into the DOM. We get a component back from this call. We can then ask React to give us the DOM associatefd with the component and use familiar tools (jQuery!) to test the shape of the generated DOM.&lt;/p&gt;
&lt;p&gt;All that&amp;rsquo;s missing is the last of the dev dependencies we&amp;rsquo;ve missed:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm install --save-dev jquery phantomjs
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can run tests directly on a Mac or Unix with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./node_modules/.bin/karma start ./tooling/karma.config.js
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For Windows use:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;node_modules&lt;span style="color:#ae81ff"&gt;\.&lt;/span&gt;bin&lt;span style="color:#ae81ff"&gt;\k&lt;/span&gt;arma start tooling&lt;span style="color:#ae81ff"&gt;\k&lt;/span&gt;arma.config.js
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In fact, we&amp;rsquo;ll update our &lt;code&gt;package.json&lt;/code&gt; scripts so that this is the &lt;code&gt;test&lt;/code&gt; command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;scripts&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;test&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;./node_modules/.bin/karma start ./tooling/karma.config.js&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Done! This means we can run tests on any platform with NodeJS&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; using the same command - &lt;code&gt;npm test&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We now have a very simple setup which allows us to run tests. You can build on this - perhaps adding Jest later or a more sophisticated or React specific set of tools.&lt;/p&gt;
&lt;h3 id="adding-code-coverage"&gt;Adding Code Coverage&lt;/h3&gt;
&lt;p&gt;You might want to add some code coverage information to your project. This can be a little tricky when using ES6, as we need to make sure we report coverage of the original ES6 code, rather than the actual transpiled code which is instrumented.&lt;/p&gt;
&lt;p&gt;Fortunately, with the clean and simple setup we have built, adding code coverage is a snap.&lt;/p&gt;
&lt;p&gt;Our test runner, Karma, is built to quickly integrate with the code coverage tool &lt;a href="https://github.com/gotwarlost/istanbul"&gt;Istanbul&lt;/a&gt;, we just need to use the &lt;a href="https://github.com/karma-runner/karma-coverage"&gt;Karma Coverage&lt;/a&gt; plugin. Let&amp;rsquo;s install the two modules:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm install --save-dev istanbul karma-coverage
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now with a small addition to our &lt;code&gt;karma.config.js&lt;/code&gt; file we will get a nice HTML coverage report. We need to update our &lt;code&gt;reporters&lt;/code&gt; config to include &lt;code&gt;coverage&lt;/code&gt; and specify coverage options in the &lt;code&gt;coverageReporter&lt;/code&gt; config.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;reporters&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;&amp;#39;progress&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;coverage&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;coverageReporter&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;dir&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;../build/coverage/&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;html&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you run &lt;code&gt;npm test&lt;/code&gt; now, you&amp;rsquo;ll get an HTML coverage report generated. The only problem is that it is for the transpiled code, which makes it almost useless. A customer instrumenter called isparta will help us here. We use isparta to get a report of the coverage of the original ES6 code. Two more modules:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm install --save-dev isparta isparta-instrumenter-loader
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then in our karma config we pass the orignal code through the insrtrumenter, before babel transpiles it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;webpack&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;module&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;preLoaders&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;test&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/\.jsx?$/&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;exclude&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; [&lt;span style="color:#e6db74"&gt;/node_modules/&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;/\.spec\.js/&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;loader&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;isparta-instrumenter-loader&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// everything else stays the same...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Anything that is not a spec or from &lt;code&gt;node_modules&lt;/code&gt; gets instrumented. Now we have a ES6 code coverage report:&lt;/p&gt;
&lt;p&gt;&lt;img src="images/CapturFiles_8.png" alt="Code Coverage Report"&gt;&lt;/p&gt;
&lt;p&gt;With this in place, you can go even further and integrate with other CI or publish to code quality systems (for example this repo integrates to &lt;a href="https://coveralls.io"&gt;coveralls.io&lt;/a&gt;). This is often used to show badges for repos:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://coveralls.io/github/dwmkerr/react-es6-starter?branch=master"&gt;&lt;img src="images/badge.svg" alt="Coverage Status"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Another use case is to gate checkins unless they maintain a certain code coverage threshhold.&lt;/p&gt;
&lt;h3 id="wrapping-up"&gt;Wrapping Up&lt;/h3&gt;
&lt;p&gt;This provides a very lean starting point for learning React. There&amp;rsquo;s no moving parts at the moment - no state management. We&amp;rsquo;ll get into that in later articles but right now you have a playground.&lt;/p&gt;
&lt;p&gt;You can set up CI in a flash, just sign up for a &lt;a href="https://travis-ci.org/"&gt;Travis&lt;/a&gt; account and use a &lt;code&gt;travis.yml&lt;/code&gt; like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;language&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;node_js&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;node_js&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;0.12&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This repo is all ready to push to &lt;a href="todo"&gt;Heroku&lt;/a&gt;, no Procfile is needed. Check out &lt;a href="todo"&gt;react-es6-starter.herokuapp.com&lt;/a&gt; to see the code in action.&lt;/p&gt;
&lt;p&gt;I hope you&amp;rsquo;ve found this article useful! Next time we&amp;rsquo;ll be getting into the details of managing state in React.&lt;/p&gt;
&lt;p&gt;Please fork the repo and have a play, let me know of any suggestions or improvements!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/dwmkerr/react-es6-starter"&gt;github.com/dwmkerr/react-es6-starter&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="glossary-of-conventions"&gt;Glossary of Conventions&lt;/h3&gt;
&lt;p&gt;There are a few conventions that I personally use in most Javascript projects. The conventions used in this article which I think are valuable to consider using in many projects are:&lt;/p&gt;
&lt;h4 id="always-support-installteststart"&gt;Always support install/test/start&lt;/h4&gt;
&lt;p&gt;Everyone should always be able to checkout, install, test and run the code with the following commands:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm install &lt;span style="color:#75715e"&gt;# installs everything needed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm test &lt;span style="color:#75715e"&gt;# lets the user know the code works right on their system!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;npm start &lt;span style="color:#75715e"&gt;# starts the code, lets the user know what to do next&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Install should setup everything, and if code needs to be built to be testable, this should be a post-install hook.&lt;/p&gt;
&lt;p&gt;Test should be run next, as a user should be able to verify that the code works as expected on their system.&lt;/p&gt;
&lt;p&gt;Finally, when the user runs start, a dev server (as convention dictates we are in a dev mode by default (and production mode is set with a flag or environment variable) the server should start and a console message should show the user where to browse to.&lt;/p&gt;
&lt;hr&gt;
&lt;h5 id="footnotes"&gt;Footnotes&lt;/h5&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a href="https://www-03.ibm.com/press/us/en/pressrelease/47474.wss"&gt;IBM Mainframes&lt;/a&gt; anyone?&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><category>CodeProject</category></item></channel></rss>