<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: orangejellyfish</title>
    <description>The latest articles on DEV Community by orangejellyfish (@orangejellyfish).</description>
    <link>https://dev.to/orangejellyfish</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F316%2F1efefcc1-009f-4b44-b242-253b56615242.png</url>
      <title>DEV Community: orangejellyfish</title>
      <link>https://dev.to/orangejellyfish</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/orangejellyfish"/>
    <language>en</language>
    <item>
      <title>Setting up CloudWatch alarms with Serverless</title>
      <dc:creator>James Allardice</dc:creator>
      <pubDate>Tue, 18 Aug 2020 07:42:43 +0000</pubDate>
      <link>https://dev.to/orangejellyfish/setting-up-cloudwatch-alarms-with-serverless-497i</link>
      <guid>https://dev.to/orangejellyfish/setting-up-cloudwatch-alarms-with-serverless-497i</guid>
      <description>&lt;p&gt;Monitoring and alerting are essential aspects to any production software system. An effective monitoring solution aggregates data across a range of metrics and presents it in a readable, human-friendly manner. A useful monitoring dashboard might allow you to quickly answer questions around high-level statistics such as "how many users have signed up for our application today" or "how many Lambda invocations have resulted in errors over the last hour". On the other side of the coin, a good alerting system will allow you to respond to changes in these metrics, perhaps by notifying an on-call engineer that something has gone wrong.&lt;/p&gt;

&lt;p&gt;In the fast-paced development environment of the &lt;a href="https://serverless.com/"&gt;Serverless Framework&lt;/a&gt;, our preferred tool of choice for applications deployed to &lt;a href="https://aws.amazon.com/lambda/"&gt;AWS Lambda&lt;/a&gt; with &lt;a href="https://aws.amazon.com/api-gateway/"&gt;API Gateway&lt;/a&gt;, it's easy to forget about building a robust monitoring or alerting solution. Fortunately, it is also relatively straightforward to do so, thanks to the vast array of metrics available by default in &lt;a href="https://aws.amazon.com/cloudwatch/"&gt;AWS CloudWatch&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  CloudWatch metrics
&lt;/h2&gt;

&lt;p&gt;A good set of metrics forms the basis of any monitoring or alerting system. CloudWatch exposes metrics from a wide range of AWS services, including those commonly used in a Serverless application such as API Gateway, Lambda, Cognito and DynamoDB. You can experiment with various representations of the available metrics from the CloudWatch console. Note that you do not have to do anything to get these metrics flowing into CloudWatch. AWS handles it all for you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_Aut6Oix--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9um5lsm06obzk40bs537.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_Aut6Oix--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9um5lsm06obzk40bs537.png" alt="A graph of a metric in CloudWatch"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The AWS CloudWatch console graphing an API Gateway metric&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Metrics can be visualised in a number of ways, including graphs as shown in the above screenshot, and these visualisations can be added to CloudWatch dashboards for quick at-a-glance monitoring. However, this requires you to be physically watching the screen to spot any possible anomalies. There must be a better way!&lt;/p&gt;
&lt;h2&gt;
  
  
  CloudWatch alarms
&lt;/h2&gt;

&lt;p&gt;Alarms are the mechanism exposed by CloudWatch to build an automated alerting system. They can be configured to respond to changes in any of the metrics we previously explored by notifying an &lt;a href="https://aws.amazon.com/sns/"&gt;SNS&lt;/a&gt; topic of the change. SNS topics are flexible and allow a range of automatic responses, such as sending an email to a specific address, and custom handlers built on AWS Lambda.&lt;/p&gt;

&lt;p&gt;CloudFormation has good support for CloudWatch so it's possible to write your alerting system infrastructure as code in the "custom resources" section of a Serverless Framework project. The following example configures a CloudWatch alarm that will trigger when any number of 5xx errors are detected by a specific API Gateway stage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;ApiGatewayAlarm5xx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::CloudWatch::Alarm&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;AlarmDescription&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5xx errors detected at API Gateway&lt;/span&gt;
      &lt;span class="na"&gt;Namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS/ApiGateway&lt;/span&gt;
      &lt;span class="na"&gt;MetricName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5XXError&lt;/span&gt;
      &lt;span class="na"&gt;Statistic&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Sum&lt;/span&gt;
      &lt;span class="na"&gt;Threshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
      &lt;span class="na"&gt;ComparisonOperator&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GreaterThanThreshold&lt;/span&gt;
      &lt;span class="na"&gt;EvaluationPeriods&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
      &lt;span class="na"&gt;Period&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt;
      &lt;span class="na"&gt;Dimensions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ApiName&lt;/span&gt;
          &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="s"&gt;Fn::Join:&lt;/span&gt;
              &lt;span class="s"&gt;- "-"&lt;/span&gt;
              &lt;span class="s"&gt;-&lt;/span&gt;
                &lt;span class="s"&gt;- Ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ApiGatewayStage&lt;/span&gt;
                &lt;span class="s"&gt;- ${self:service}&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Stage&lt;/span&gt;
          &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;Ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ApiGatewayStage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Some of the important properties here can be explained as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Namespace&lt;/code&gt; - the AWS service namespace whose metric you want to alert on. The available namespaces &lt;a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/aws-services-cloudwatch-metrics.html"&gt;are listed in the documentation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;MetricName&lt;/code&gt; - the specific metric you want to alert on. These are usually listed somewhere in the documentation for the service in question. For example, API Gateway &lt;a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-metrics-and-dimensions.html"&gt;lists them here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;Statistic&lt;/code&gt;, &lt;code&gt;Threshold&lt;/code&gt; and &lt;code&gt;ComparisonOperator&lt;/code&gt; properties define a change in metric state that will trigger the alarm. In this case the alarm will trigger if the &lt;code&gt;5XXError&lt;/code&gt; metric exceeds a total of &lt;code&gt;0&lt;/code&gt; over the &lt;code&gt;Period&lt;/code&gt; (a value in seconds).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Dimensions&lt;/code&gt; property effectively restricts the alarm to a subset of available metrics. In this example the alarm will only trigger for a specific stage of a specific API Gateway. If you have multiple stages or APIs deployed in a single account it will be important to ensure your alarms are specific enough to not trigger false positives.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding actions to alarms
&lt;/h3&gt;

&lt;p&gt;With the example configuration above we have a CloudWatch alarm configured and it will successfully transition between states as the value of the underlying metric changes. To make this alarm a useful part of our monitoring and alerting strategy we need to add an action to it.&lt;/p&gt;

&lt;p&gt;In a Serverless application it is likely that the action will always be a notification to an SNS topic. Other actions include certain EC2 and Auto Scaling actions which are outside the scope of this article. Like the CloudWatch alarm itself, an SNS topic can be codified in CloudFormation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;TopicCloudwatchAlarm&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::SNS::Topic&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;TopicName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${self:service}-${self:custom.stage}-topic-cloudwatch-alarm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;An SNS topic needs a "subscription" to be useful. SNS topics are capable of automatically sending emails to a given address for every message published to them. We can add a subscription in CloudFormation too. In this example the &lt;code&gt;TopicArn&lt;/code&gt; property references the &lt;code&gt;TopicCloudwatchAlarm&lt;/code&gt; resource defined above via the &lt;code&gt;Ref&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;TopicCloudwatchAlarmSubscription&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::SNS::Subscription&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Endpoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;alerts@example.com&lt;/span&gt;
      &lt;span class="na"&gt;Protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;email&lt;/span&gt;
      &lt;span class="na"&gt;TopicArn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;Ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TopicCloudwatchAlarm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With these resources deployed to AWS any message published to the new SNS topic will be sent to the email address specified by the SNS subscription. All that remains is for us to connect the CloudWatch alarm to the SNS topic. The &lt;code&gt;AlarmActions&lt;/code&gt; property on the CloudWatch alarm resource takes the ARN of the&lt;br&gt;
SNS topic. Add the following to the original example to wire it all up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;AlarmActions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TopicCloudwatchAlarm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;All that remains is to trigger the alarm and check your inbox!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XFhQYgUl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4ojaulmoebvy8ilw0ea2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XFhQYgUl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4ojaulmoebvy8ilw0ea2.png" alt="An alert email"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;An email sent in response to a CloudWatch alarm&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;p&gt;The alarm we've looked at in this article barely scratches the surface of what's possible with CloudWatch. You can create alarms that take many metrics into account at once. You can create alarms to warn you when an AWS resource is costing more money than you would like. You can even configure alarms based on "anomaly detection" where CloudWatch will analyse past metric data to create a model of expected values and alert on deviations from that baseline. As with most AWS services, the &lt;a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html"&gt;CloudWatch documentation&lt;/a&gt; is helpful and is definitely recommended reading if you'd like to learn more about these more advanced alarms.&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>aws</category>
      <category>cloudwatch</category>
      <category>monitoring</category>
    </item>
    <item>
      <title>Custom icon fonts with React Native</title>
      <dc:creator>James Allardice</dc:creator>
      <pubDate>Wed, 17 Jul 2019 09:26:08 +0000</pubDate>
      <link>https://dev.to/orangejellyfish/custom-icon-fonts-with-react-native-2api</link>
      <guid>https://dev.to/orangejellyfish/custom-icon-fonts-with-react-native-2api</guid>
      <description>&lt;p&gt;When working with icons in &lt;a href="https://facebook.github.io/react-native/" rel="noopener noreferrer"&gt;React Native&lt;/a&gt; apps we're spoilt for choice with&lt;br&gt;
a wide range of free and open-source icon sets such as &lt;a href="https://fontawesome.com/" rel="noopener noreferrer"&gt;FontAwesome&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://www.google.com/design/icons/" rel="noopener noreferrer"&gt;Material&lt;/a&gt; and &lt;a href="https://ionicons.com/" rel="noopener noreferrer"&gt;Ionicons&lt;/a&gt;. To make things even easier, the&lt;br&gt;
wonderful &lt;a href="https://github.com/oblador/react-native-vector-icons" rel="noopener noreferrer"&gt;react-native-vector-icons&lt;/a&gt; project bundles all of those icon&lt;br&gt;
sets plus more into one single package. But sometimes free and open-source icon&lt;br&gt;
sets just don't cut it and you're left wondering how to achieve something that&lt;br&gt;
has the same developer experience for a custom icon set. Fortunately,&lt;br&gt;
react-native-vector-icons and a bunch of other projects have us covered here&lt;br&gt;
too.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up react-native-vector-icons
&lt;/h2&gt;

&lt;p&gt;If you're using &lt;a href="https://expo.io/" rel="noopener noreferrer"&gt;Expo&lt;/a&gt; and have not ejected to ExpoKit then there's&lt;br&gt;
nothing to do here. Expo bundles a wrapper around react-native-vector-icons in&lt;br&gt;
the &lt;a href="https://docs.expo.io/versions/latest/guides/icons/" rel="noopener noreferrer"&gt;&lt;code&gt;@expo/icons&lt;/code&gt; package&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Otherwise, the installation of the react-native-vector-icons package is as you&lt;br&gt;
would expect for a React Native app. It's published to npm so you can add it to&lt;br&gt;
your project with the CLI or equivalent (we tend to use &lt;a href="https://yarnpkg.com/en/" rel="noopener noreferrer"&gt;Yarn&lt;/a&gt; when&lt;br&gt;
working with React Native because it plays better with Expo):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;yarn add react-native-vector-icons
&lt;span class="nv"&gt;$ &lt;/span&gt;react-native &lt;span class="nb"&gt;link &lt;/span&gt;react-native-vector-icons
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Generating an icon font
&lt;/h2&gt;

&lt;p&gt;With react-native-vector-icons set up in your project you are ready to work on&lt;br&gt;
the icons themselves. In our experience &lt;a href="https://icomoon.io/" rel="noopener noreferrer"&gt;IcoMoon&lt;/a&gt; is the most effective&lt;br&gt;
tool here. IcoMoon is a web application that allows you to import SVG files and&lt;br&gt;
produce font files in various formats from collections of those SVGs, as shown&lt;br&gt;
in the following screenshot:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcyx35jc9fzeg6sf60yxu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcyx35jc9fzeg6sf60yxu.png" alt="Creating an icon set in IcoMoon"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;An example of creating an icon set in IcoMoon&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once all of your icons are imported to the IcoMoon app you can select them and&lt;br&gt;
"Generate" the font file (note that in the screenshot below it shows the number&lt;br&gt;
of selected icons to the left of the highlighted "Generate Font" button):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F70dyk98eo23hdpqssebw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F70dyk98eo23hdpqssebw.png" alt="Generating an icon font in IcoMoon"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;An example of generating an icon font from an icon set in IcoMoon&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are a few options to configure the resulting font but most of the time the&lt;br&gt;
defaults will suffice. When you're happy download the bundle and unzip it to&lt;br&gt;
find a selection of font files, some examples and a &lt;code&gt;selection.json&lt;/code&gt; file. It's&lt;br&gt;
that file plus the &lt;code&gt;*.ttf&lt;/code&gt; font file that we need. Copy those files to a&lt;br&gt;
sensible directory within your React Native codebase. We usually go for a top-&lt;br&gt;
level &lt;code&gt;assets&lt;/code&gt; directory which contains all of the static assets used by the app&lt;br&gt;
including fonts and images.&lt;/p&gt;
&lt;h2&gt;
  
  
  Using the custom icon font
&lt;/h2&gt;

&lt;p&gt;It's recommended that you pre-load any fonts that your app is going to use and&lt;br&gt;
your new custom icon font is no exception. In your main app entry point you can&lt;br&gt;
use the &lt;code&gt;Font.loadAsync&lt;/code&gt; method. If you have used the Expo CLI to initialise&lt;br&gt;
your project then you probably have something that looks like this already:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;registerRootComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AppLoading&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;expo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Font&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;expo-font&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;isLoadingComplete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;loadResourcesAsync&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nx"&gt;Font&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadAsync&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;custom-icons&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../assets/fonts/custom-icons.ttf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="nx"&gt;handleLoadingError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// In this case, you might want to report the error to your error&lt;/span&gt;
    &lt;span class="c1"&gt;// reporting service, for example Sentry&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;handleFinishLoading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;isLoadingComplete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isLoadingComplete&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isLoadingComplete&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AppLoading&lt;/span&gt;
          &lt;span class="nx"&gt;startAsync&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadResourcesAsync&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;onError&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleLoadingError&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;onFinish&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleFinishLoading&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;registerRootComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Export the App component for unit testing purposes. Expo handles rendering&lt;/span&gt;
&lt;span class="c1"&gt;// via the "registerRootComponent" call above and does not require an export.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this configuration your custom icon font file will be loaded at app start-&lt;br&gt;
up rather than at first usage which would otherwise result in flashes of&lt;br&gt;
unstyled (or missing) content.&lt;/p&gt;

&lt;p&gt;Next up you need a normal React component to render icons from your new font.&lt;br&gt;
The react-native-vector-icons package provides some utility methods to make this&lt;br&gt;
process simpler. The following few lines are all that are needed. We usually&lt;br&gt;
place this in a &lt;code&gt;src/components/icon/index.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createIconSetFromIcoMoon&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-vector-icons&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;icoMoonConfig&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../../assets/fonts/selection.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// We use the IcoMoon app (https://icomoon.io) to generate a custom font made up&lt;/span&gt;
&lt;span class="c1"&gt;// of SVG icons. The actual font file is loaded up-front in src/index.js.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;createIconSetFromIcoMoon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;icoMoonConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;custom-icons&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key points to note here are the import of the &lt;code&gt;selection.json&lt;/code&gt; file from the&lt;br&gt;
bundle downloaded from IcoMoon and the name of the font, &lt;code&gt;custom-icons&lt;/code&gt;, as&lt;br&gt;
defined in the &lt;code&gt;Font.loadAsync&lt;/code&gt; call in the main app entry point.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;createIconSetFromIcoMoon&lt;/code&gt; function could be thought of as a factory that&lt;br&gt;
returns a React component. You can now import that component from your other&lt;br&gt;
components to render icons. The following example imagines a simple "button"&lt;br&gt;
component in &lt;code&gt;src/components/button/index.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TouchableOpacity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Icon&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../icons&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TouchableOpacity&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Icon&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;settings&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Settings&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Text&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/TouchableOpacity&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new &lt;code&gt;Icon&lt;/code&gt; component supports all of the props that the open-source icon&lt;br&gt;
sets bundled with react-native-vector-icons support. This means you can apply&lt;br&gt;
custom styles, such as sizes and colours, from React Native stylesheets.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>javascript</category>
      <category>expo</category>
      <category>react</category>
    </item>
    <item>
      <title>Serverless and the principle of least privilege</title>
      <dc:creator>James Allardice</dc:creator>
      <pubDate>Wed, 02 Jan 2019 13:37:49 +0000</pubDate>
      <link>https://dev.to/orangejellyfish/serverless-and-the-principle-of-least-privilege-2on9</link>
      <guid>https://dev.to/orangejellyfish/serverless-and-the-principle-of-least-privilege-2on9</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Every program and every privileged user of the system should operate using the least amount of privilege necessary to complete the job.&lt;/p&gt;


  &lt;p&gt;— Jerome Saltzer, &lt;cite&gt;Communications of the ACM&lt;/cite&gt;&lt;/p&gt;

&lt;/blockquote&gt;

&lt;p&gt;That quote, by American computer scientist &lt;a href="https://en.wikipedia.org/wiki/Jerry_Saltzer" rel="noopener noreferrer"&gt;Jerome Saltzer&lt;/a&gt;, underpins the concept that became known as the "Principle of Least Privilege". The idea is that by ensuring each part of a system has the ability to access the data it needs to do its job and nothing beyond that. It applies to pretty much any software system, be it a web application or a program running on an embedded chip.&lt;/p&gt;

&lt;p&gt;The rest of this article is going to focus on the principle of least privilege as it applies to the &lt;a href="https://serverless.com/" rel="noopener noreferrer"&gt;Serverless framework&lt;/a&gt;, and, in particular, Serverless applications deployed to &lt;a href="https://aws.amazon.com/" rel="noopener noreferrer"&gt;AWS&lt;/a&gt;. Before we dig into Serverless it will help if you have an understanding of the Identity and Access Management, or &lt;a href="https://aws.amazon.com/iam/" rel="noopener noreferrer"&gt;IAM&lt;/a&gt;, feature of AWS.&lt;/p&gt;

&lt;h2&gt;
  
  
  IAM
&lt;/h2&gt;

&lt;p&gt;AWS IAM is a comprehensive identity and access management tool. It provides functionality to manage users and control their access to other AWS services and resources. It provides the concept of roles that can be assumed by other entities to grant access to resources. It even provides the ability for web or mobile applications to directly access AWS resources.&lt;/p&gt;

&lt;p&gt;IAM provides the concept of "identities" which are created to "provide authentication for people and processes in your AWS account". Identities can be, amongst others, "users", such as the personal account you might use to log in to the AWS Console, or "roles". For now we're primarily interested in IAM roles.&lt;/p&gt;

&lt;p&gt;Imagine an AWS Lambda function that when invoked needs to read from a DynamoDB table, manipulate some data, write the modified document back to the table and then publish a message to an SNS topic to notify other interested parties that it has done its job. By default, that Lambda will not have permission to access any of those resources. To ensure the function has the ability to access the resources it depends on it can &lt;em&gt;assume&lt;/em&gt; an IAM role when it executes. The Lambda documentation refers to this as the "execution role", and every Lambda function has one that is specified at the time it is created. Likewise, other AWS resources, such as API Gateway, may need a role that allows them to invoke Lambda functions. The Lambda web console has a helpful diagram that shows both sides of this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhrewljyv51jpf3a77ste.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhrewljyv51jpf3a77ste.png" alt="Permissions in the Lambda console" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see that the API Gateway has permission to invoke the Lambda, and the Lambda execution role gives it permission to access CloudWatch, DynamoDB and SNS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Serverless
&lt;/h2&gt;

&lt;p&gt;When developing a Serverless application for AWS you have the ability to either configure an IAM role that will be assumed by all the Lambda functions in your service (the default approach), or to define a different role for each function.&lt;/p&gt;

&lt;p&gt;If you stick with the default you'll end up with something like this in your &lt;code&gt;serverless.yml&lt;/code&gt; file. This example will allow all Lambda functions in the service to perform the "publish" action on a specific SNS topic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws&lt;/span&gt;
  &lt;span class="na"&gt;iamRoleStatements&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Effect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Allow&lt;/span&gt;
      &lt;span class="na"&gt;Action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sns:publish&lt;/span&gt;
      &lt;span class="na"&gt;Resource&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MySNSTopic&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's a couple of things to think about here. We've gone a long way towards ensuring our functions "operate using the least amount of privilege necessary to complete the job". They are able to perform only a single type of action against a specific resource. If your function code was to attempt to publish a message to a different SNS topic it would not be able to do so. However, we can do better. As we add functions to our service it's likely that they have different access requirements. By following the default configuration you will soon end up with a wide-ranging IAM role that gives all of your Lambda functions access to everything that any one of them might need. To better adhere to the principle of least privilege we need to define an IAM role per Lambda function.&lt;/p&gt;

&lt;p&gt;Unfortunately, achieving this with the Serverless framework is fairly involved. When not using the provider-level role configuration you don't benefit from any of the permissions that you usually get for free from Serverless, meaning you need to manually configure access to things like CloudWatch for logging. If this is the approach you want to take you can find plenty more information in the &lt;a href="https://serverless.com/framework/docs/providers/aws/guide/iam/" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;. But thanks to the wonderful open-source community there is a much easier route.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/functionalone/serverless-iam-roles-per-function" rel="noopener noreferrer"&gt;serverless-iam-roles-per-function plugin&lt;/a&gt; takes care of all that other stuff you'd usually get out of the box and lets you focus just on the resources that are specific to your individual Lambda function. Activate the plugin in &lt;code&gt;serverless.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;serverless-iam-roles-per-function&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then you can define &lt;code&gt;iamRoleStatements&lt;/code&gt; at the function level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;myLambdaFunction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;src/functions/hello/index.default&lt;/span&gt;
  &lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;get&lt;/span&gt;

  &lt;span class="na"&gt;iamRoleStatements&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Effect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Allow&lt;/span&gt;
      &lt;span class="na"&gt;Action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sns:publish&lt;/span&gt;
      &lt;span class="na"&gt;Resource&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MySNSTopic&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this configuration any additional Lambda functions in our service will not be able to use the &lt;code&gt;sns:publish&lt;/code&gt; action on the &lt;code&gt;MySNSTopic&lt;/code&gt; resource. And this function itself will not be able to use any other SNS actions even on that resource, fulfilling our original goal of giving each Lambda function to least amount of privilege necessary to complete the job.&lt;/p&gt;

&lt;p&gt;The orangejellyfish &lt;a href="https://github.com/orangejellyfish/serverless-starter" rel="noopener noreferrer"&gt;Serverless starter kit&lt;/a&gt; includes the aforementioned plugin by default and contains an example Lambda function along with a range of other best-practice configuration defaults and helpers.&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>aws</category>
    </item>
    <item>
      <title>Get good with git: bisect</title>
      <dc:creator>James Allardice</dc:creator>
      <pubDate>Wed, 21 Nov 2018 13:12:34 +0000</pubDate>
      <link>https://dev.to/orangejellyfish/get-good-with-git-bisect-20l1</link>
      <guid>https://dev.to/orangejellyfish/get-good-with-git-bisect-20l1</guid>
      <description>&lt;p&gt;Have you ever been in a situation where you needed to find out which commit in the history of a git repository was responsible for causing some change in behaviour? It's a fairly common debugging technique, especially in larger, older codebases. If you know where to find the code that might have introduced the change you may be able to use commands like &lt;code&gt;git blame&lt;/code&gt; or &lt;code&gt;git log&lt;/code&gt; to search through history for the offending commit, but often that is not the case, and even when it is, there is often an easier approach. Enter &lt;code&gt;git bisect&lt;/code&gt;, a useful git command that performs a binary search of history to identify the commit that introduced a change.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Do you learn better with a more hands-on approach?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If a face-to-face approach to learning works better for you or your team, orangejellyfish run a popular &lt;a href="https://www.orangejellyfish.com/workshops/get-good-with-git/" rel="noopener noreferrer"&gt;git workshop&lt;/a&gt; which can take place remotely or on-site with you, giving you an opportunity to go deeper into some more advanced git concepts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Binary search
&lt;/h2&gt;

&lt;p&gt;If that description alone is enough to put you off reading further, don't despair and follow this section to get a better understanding of what "binary search" is. If you've already got that concept down, feel free to jump ahead.&lt;/p&gt;

&lt;p&gt;"Binary search" is an algorithm designed to find a target value in a sorted list of values. It works by comparing the target value to the middle element of the list. If they do not match, half of the list has been eliminated (because the list was already sorted) and the process repeats by comparing the target value to the new middle element, and so on, until the target value is found.&lt;/p&gt;

&lt;p&gt;A visual representation might make it easier to follow. Here's our sorted list, or array, of numbers. Since this array contains numbers we can see that it in a sorted state because each element holds a value greater than the previous. Let's say that our target value is &lt;strong&gt;42&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We start by comparing our target value to the middle element. We can see that the middle element is &lt;strong&gt;greater&lt;/strong&gt; than our target:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feo3j7mx1k10qc6w51pn9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feo3j7mx1k10qc6w51pn9.png" alt="Comparing to the target value" width="800" height="122"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because the middle element is greater than the target we can discard the second half of the array and perform the test again. This time we can see that the middle element is &lt;strong&gt;smaller&lt;/strong&gt; than our target:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F119rrpkuk0mdb6f9cr6v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F119rrpkuk0mdb6f9cr6v.png" alt="Discarding half of the array" width="800" height="122"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because the middle element is smaller than the target we can discard the first half of the array (bear in mind that we are now working with a new array, having already discarded half of the original) and perform the test one more time. Note that this time, since we have an even number of elements in the array, it is up to the algorithm whether we round up or down to determine the mid-point. In this example we have rounded up for the sake of brevity. This time we can see that the middle element &lt;strong&gt;matches&lt;/strong&gt; the target:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flf1vel08nomcbzporvz9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flf1vel08nomcbzporvz9.png" alt="Discarding another half of the array" width="800" height="122"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because the middle element matches the target the binary search is complete and the position of the target in the array is the result. In our case the target is at position &lt;strong&gt;4&lt;/strong&gt;. But how does any of this apply to git?&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;git bisect&lt;/code&gt; basics
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;git bisect&lt;/code&gt; command allows us to perform a binary search on a range of commits in a repository. Try to think of a range of commits as an array where each element is an individual commit. This array is sorted in chronological (time of commit) order, rather than numerical order as in the example above, but since it is sorted we are able to perform a binary search on it. The target of the search is the commit that introduced a given change.&lt;/p&gt;

&lt;p&gt;In order to determine the relevant range of commits we need to know of a start point at which the change we are trying to find had not yet been made and an end point at which it had been. The end point will often be the &lt;code&gt;HEAD&lt;/code&gt; of the current branch. The start point can be more difficult to determine but a good strategy might be to check out an old but likely stable tag and go from there.&lt;/p&gt;

&lt;p&gt;Let's assume that we know a bug has been introduced to our codebase sometime between the &lt;code&gt;v1.2.0&lt;/code&gt; tag and now (the &lt;code&gt;HEAD&lt;/code&gt; of the master branch). Armed with that information we can start the bisect and tell it which range we're working with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git bisect start          &lt;span class="c"&gt;# Start the binary search process&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git bisect bad            &lt;span class="c"&gt;# Identify the end of the range&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git bisect good v1.2.0    &lt;span class="c"&gt;# Identify the start of the range&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Git now identifies the middle point of the range of commits, checks it out and pauses to give you the opportunity to work out whether or not the change you are trying to locate had been introduced at that point in time. You might do so by running an automated test suite, examining a file, or running your app and manually testing the relevant feature. Git tells you what has happened by printing something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Bisecting: 64 revisions left to test after this (roughly 6 steps)
[bf96dbd8768d94e935e0bb874b319ae9b65a9aaf] The mid-point commit message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Having determined whether or not the mid-point contains the change you are searching for you can tell &lt;code&gt;git bisect&lt;/code&gt; and it will continue the process by discarding one half of the range, checking out the new mid-point and pausing again. Let's assume that the change we wanted to find is already present at this point in time, meaning the current mid-point is "bad":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git bisect bad    &lt;span class="c"&gt;# Mark the current mid-point as bad, discard later commits&lt;/span&gt;
Bisecting: 32 revisions left to &lt;span class="nb"&gt;test &lt;/span&gt;after this &lt;span class="o"&gt;(&lt;/span&gt;roughly 5 steps&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;e68d1eed5051744ad21bf7391b582939b5c996fc] New mid-point commit message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Git has paused again at the new mid-point so we get the opportunity to repeat our test. Let's assume this time that the change has &lt;strong&gt;not&lt;/strong&gt; been introduced at this point in time, meaning this mid-point is "good":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git bisect good    &lt;span class="c"&gt;# Mark the current mid-point as good, discard earlier commits&lt;/span&gt;
Bisecting: 12 revisions left to &lt;span class="nb"&gt;test &lt;/span&gt;after this &lt;span class="o"&gt;(&lt;/span&gt;roughly 4 steps&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;1ee2cc616963f57900d3bc2b635d9efbd1cd168d] New mid-point commit message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Continue this process, running your test at each step and marking the mid-point as either "good" or "bad" until git is able to definitively determine the commit that introduced the change. At that point it will helpfully tell you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ebd6cd99667703a856b20c87c2307427006fcd2f is the first bad commit
commit ebd6cd99667703a856b20c87c2307427006fcd2f
Author: First Last &amp;lt;first.last@example.com&amp;gt;
Date:   Thu Aug 23 13:58:20 2018 +0000

    This is the commit that introduced the issue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All that remains now is to get back to the normal state by telling git that you are done:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git bisect reset
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Automating &lt;code&gt;git bisect&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;What we've covered so far is a powerful addition to your git debugging toolbox in its own right, but we can take it a step further to cut down some of the manual work.&lt;/p&gt;

&lt;p&gt;The part of the previous example that would slow us down in reality is the test to determine whether each mid-point commit exhibits the behaviour we are trying to locate or not. If it's possible to script that test then git is more than happy to take that burden off us. What we need is a script that exits with code &lt;code&gt;0&lt;/code&gt; if the current commit is "good" and with &lt;code&gt;1&lt;/code&gt; (the Unix catch-all error code) if it's "bad". Most automated test runners will already do this so in many cases you'll be able to use an existing script rather than writing a new one.&lt;/p&gt;

&lt;p&gt;Let's assume you're trying to track down a bug in a codebase that uses &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt; as a unit test runner. The Jest CLI tool exits with helpful codes so we're able to use it to automate a git bisect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git bisect start          &lt;span class="c"&gt;# Start the binary search process&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git bisect bad            &lt;span class="c"&gt;# Identify the end of the range&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git bisect good v1.2.0    &lt;span class="c"&gt;# Identify the start of the range&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git bisect run jest       &lt;span class="c"&gt;# Run unit tests against each mid-point&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are some additional tricks you can use in your test script. For example, exiting the script with exit code &lt;code&gt;125&lt;/code&gt; will tell &lt;code&gt;git bisect&lt;/code&gt; that the commit cannot be tested and should be skipped. In that situation the command will choose another commit for you and continue automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  What next?
&lt;/h2&gt;

&lt;p&gt;At this point you should have gained a solid understanding of &lt;code&gt;git bisect&lt;/code&gt; and be in a position to use it either manually or automatically to discover problems that were introduced by an unknown commit. If you'd like to take it further a good place to start is the &lt;a href="https://git-scm.com/docs/git-bisect" rel="noopener noreferrer"&gt;official git documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If a more hands-on approach works better for you or your team, &lt;a href="https://www.orangejellyfish.com/" rel="noopener noreferrer"&gt;orangejellyfish&lt;/a&gt; run a popular &lt;a href="https://www.orangejellyfish.com/workshops/get-good-with-git/" rel="noopener noreferrer"&gt;git workshop&lt;/a&gt; which can take place remotely or on-site with you, giving you an opportunity to go deeper into some more advanced git concepts.&lt;/p&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>A bleeding edge Serverless Framework boilerplate</title>
      <dc:creator>James Allardice</dc:creator>
      <pubDate>Wed, 15 Aug 2018 14:35:53 +0000</pubDate>
      <link>https://dev.to/orangejellyfish/a-bleeding-edge-serverless-framework-boilerplate-2g1f</link>
      <guid>https://dev.to/orangejellyfish/a-bleeding-edge-serverless-framework-boilerplate-2g1f</guid>
      <description>&lt;p&gt;At &lt;a href="https://www.orangejellyfish.com/"&gt;orangejellyfish&lt;/a&gt; we are big fans of the &lt;a href="https://serverless.com/framework/"&gt;Serverless&lt;/a&gt; framework and use it in a number of projects. Over time we have realised the need for a boilerplate Serverless app to save time when getting started, and that's what we have built.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/orangejellyfish"&gt;
        orangejellyfish
      &lt;/a&gt; / &lt;a href="https://github.com/orangejellyfish/serverless-starter"&gt;
        serverless-starter
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Serverless framework starter kit for AWS Lambda
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
serverless-starter&lt;/h1&gt;
&lt;p&gt;An opinionated starter kit by &lt;a href="https://www.orangejellyfish.com/" rel="nofollow"&gt;orangejellyfish&lt;/a&gt; for
&lt;a href="https://serverless.com/framework/" rel="nofollow"&gt;Serverless framework&lt;/a&gt; apps running in &lt;a href="https://aws.amazon.com/" rel="nofollow"&gt;AWS&lt;/a&gt;. Built to be future-proof
Inspired by and adapted from the excellent &lt;a href="https://github.com/postlight/serverless-babel-starter"&gt;serverless-babel-starter&lt;/a&gt;
project by &lt;a href="https://github.com/postlight"&gt;Postlight&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Lambdas run Node 14 by default making your functions faster and giving you the
ability to use more recent ECMAScript features including async/await, optional
chaining and nullish coalescing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Lambda code is bundled with Webpack 5 via the &lt;a href="https://github.com/serverless-heaven/serverless-webpack"&gt;serverless-webpack&lt;/a&gt; plugin
reducing the amount of code deployed to AWS.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Lambda code is compiled with &lt;a href="https://babeljs.io/docs/en/next/index.html" rel="nofollow"&gt;Babel 7&lt;/a&gt; and &lt;a href="https://babeljs.io/docs/en/next/babel-preset-env.html" rel="nofollow"&gt;babel-preset-env&lt;/a&gt;
meaning you can use even more cutting-edge ECMAScript features if you need to
without unnecessarily compiling code that would be supported by Node 14.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Lambda config is located alongside the function code and referenced from the
top-level Serverless configuration file, offering greater separation of
concerns and keeping the configuration file readable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;IAM roles are configured per-Lambda via the
&lt;a href="https://github.com/functionalone/serverless-iam-roles-per-function"&gt;serverless-iam-roles-per-function&lt;/a&gt; plugin, meaning…&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/orangejellyfish/serverless-starter"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The starter kit is an opinionated boilerplate for a Serverless app running in AWS. It's been designed to offer as much future-proofing as possible, a tricky challenge in the fast-moving JavaScript ecosystem! Our starting point was the fantastic "&lt;a href="https://github.com/postlight/serverless-babel-starter"&gt;Modern Serverless Starter Kit&lt;/a&gt;" by &lt;a href="https://github.com/postlight"&gt;Postlight&lt;/a&gt;. While that project has "modern" in the name we felt that we could safely go a bit closer to the cutting edge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;p&gt;When designing the Serverless starter kit we had a few key requirements in mind&lt;br&gt;
which directly translate into features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Node 8 support&lt;/strong&gt;. This was a key one for us. AWS has &lt;a href="https://aws.amazon.com/blogs/compute/node-js-8-10-runtime-now-available-in-aws-lambda/"&gt;supported Node 8&lt;/a&gt; as a Lambda runtime environment since April 2018, bringing native support for a whole host of recent ECMAScript features (including async/await), performance improvements and reduced memory consumption thanks to the more recent version of V8.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Webpack 4 support&lt;/strong&gt;. It was important that we could bundle our Lambda function code with Webpack to reduce the size of the package uploaded to AWS. &lt;a href="https://medium.com/webpack/webpack-4-released-today-6cdb994702d4"&gt;Webpack 4&lt;/a&gt; is the latest and greatest version, offering major speed improvements and much simpler configuration compared to previous iterations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Babel 7 support&lt;/strong&gt;. This one is more a straightforward case of future-proofing. There's currently little technical reason to favour Babel 7 over the arguably more stable version 6 but it's fun to push the boundaries sometimes!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Local development support&lt;/strong&gt;. If you have to deploy functions to AWS every time you make a change the developer experience is somewhat poor. Fortunately this problem has been solved by the &lt;a href="https://github.com/dherault/serverless-offline"&gt;serverless-offline&lt;/a&gt; plugin which emulates AWS Lambda and API Gateway locally.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Jest support&lt;/strong&gt;. Unit testing is important. &lt;a href="https://jestjs.io/"&gt;Jest&lt;/a&gt; is, in our opinion, the best tool for the job. The starter kit includes Jest configuration to automatically collect code coverage information.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ESLint configuration&lt;/strong&gt;. We're firm believers in &lt;a href="https://dev.to/blog/code-consistency-with-eslint-and-husky/"&gt;the need for consistent code&lt;/a&gt; and therefore the starter kit ships with a pre-configured ESLint set up, along with Husky and lint-staged to efficiently lint and auto-fix code at commit time.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;The Serverless CLI allows you to scaffold a new Serverless application from a template on GitHub. Run the following command to use our starter kit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;serverless create &lt;span class="nt"&gt;--template-url&lt;/span&gt; https://github.com/orangejellyfish/serverless-starter &lt;span class="nt"&gt;--path&lt;/span&gt; your/local/path
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;We think that the feature set provided by this starter kit give you a really solid start for any Serverless application but it's only the basics. Watch this space for more advanced kits, built upon this one, in the future, adding pre-configured support for things like DynamoDB.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>javascript</category>
      <category>serverless</category>
    </item>
  </channel>
</rss>
