<?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: Ryan Levick</title>
    <description>The latest articles on DEV Community by Ryan Levick (@ryan_levick).</description>
    <link>https://dev.to/ryan_levick</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%2Fuser%2Fprofile_image%2F155221%2F857fa956-256e-4da3-b818-7e7463712d9b.jpg</url>
      <title>DEV Community: Ryan Levick</title>
      <link>https://dev.to/ryan_levick</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ryan_levick"/>
    <language>en</language>
    <item>
      <title>64 Cores on Fire: Supercharging My Development Experience</title>
      <dc:creator>Ryan Levick</dc:creator>
      <pubDate>Wed, 08 May 2019 14:57:46 +0000</pubDate>
      <link>https://dev.to/azure/64-cores-on-fire-supercharging-my-development-experience-2ec3</link>
      <guid>https://dev.to/azure/64-cores-on-fire-supercharging-my-development-experience-2ec3</guid>
      <description>&lt;p&gt;I recently started contributing to the &lt;a href="https://github.com/rust-lang/rust"&gt;Rust&lt;/a&gt; standard library to start fleshing out networking support for the WebAssembly system interface (WASI). The issue is that building rustc and its component parts like LLVM takes two and a half hours on my 2015 MacBook Pro. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XhON3irD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/77s8wl6im1ubgco6eh97.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XhON3irD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/77s8wl6im1ubgco6eh97.png" alt="My poor machine"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If I was to be able to be productive, I needed a different solution!&lt;/p&gt;

&lt;h2&gt;
  
  
  Moar Cores!
&lt;/h2&gt;

&lt;p&gt;The easiest answer when your machine isn't running something fast enough is to try throw more cores at it and see if it helps. Luckily a large part of building rustc is building llvm which massively speeds up when it has access to more cores.&lt;/p&gt;

&lt;p&gt;So my co-worker, &lt;a href="//twitter.com/duncan"&gt;Duncan&lt;/a&gt; and I spun up a F64s_v2 virtual machine on Azure which has 64 total cores. The Fsv2 series of VMs on Azure are compute optimized making them the right VMs for the job.&lt;/p&gt;

&lt;p&gt;With this machine, the build times went down dramatically to a total of around  17 minutes! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XTS9wFhZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/rxuoxwfe215mempe4pwm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XTS9wFhZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/rxuoxwfe215mempe4pwm.png" alt="All the cores!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wondering what would happen with less cores, we ran the same setup on a F32s_v2 with 32 cores and a F16s_v2 with 16 cores. These builds ran in 21 and 30 minutes respectively - not too bad!&lt;/p&gt;

&lt;h2&gt;
  
  
  Estimated Cost
&lt;/h2&gt;

&lt;p&gt;Azure VMs are usually a bit cheaper in the U.S. so we hosted them there. I'm located in Europe, but in my experience latency isn't really an issue as the dev tools I use (ssh and VS Code remote extension) handle the latency fine. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://azure.microsoft.com/en-us/pricing/details/virtual-machines/ubuntu-advantage-standard?WT.mc_id=devto-blog-rylevick"&gt;The cost&lt;/a&gt; for the 64 core machine at the time of this writing $2.73 per hour, while the 32 core machine is $1.38 per hour and the 16 core machine is $0.71 per hour. &lt;/p&gt;

&lt;p&gt;Given that the smaller machines are much cheaper, I opted for doing an initial build on a 32 core machine and then for incremental builds transferring the disk to a B8MS virtual machine. B8MS is an 8 core machine that is optimized for "burst" workloads (i.e. high CPU usage that happens every once in a while - like compiling). It only costs $0.36 per hour. Of course, you should still remember to shut down the machine when you're not using it.&lt;/p&gt;

&lt;p&gt;You'll also have to &lt;a href="https://azure.microsoft.com/en-us/pricing/details/managed-disks?WT.mc_id=devto-blog-rylevick"&gt;pay for storage&lt;/a&gt;. Using a standard SSD with 64GB of RAM, only costs $5 per month.&lt;/p&gt;

&lt;p&gt;If we put all this together, I estimate it costs around $2.00 for typical dev session of around 4 or 5 hours. Not too bad if it means I spend almost all that time coding instead of waiting for the thing to compile.   &lt;/p&gt;

&lt;h2&gt;
  
  
  Dev Experience
&lt;/h2&gt;

&lt;p&gt;Obviously getting a machine setup takes a bit of time, but with simple shell scripts using the &lt;a href="https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest&amp;amp;WT.mc_id=devto-blog-rylevick"&gt;Azure CLI&lt;/a&gt;, I now can easily reproduce the setup of both machines and the swapping the disk between them.&lt;/p&gt;

&lt;p&gt;As for, writing actual code, I've been really enjoying &lt;a href="https://code.visualstudio.com?WT.mc_id=devto-blog-rylevick"&gt;VS Code&lt;/a&gt;'s &lt;a href="https://code.visualstudio.com/docs/remote/remote-overview?WT.mc_id=devto-blog-rylevick"&gt;Remote Development Extensions&lt;/a&gt;. Most of the time I don't notice, I'm not working on my machine. I've had similar experiences as a vim user in the past, but this is next level, even making file transfer to the remote machine, super simple.&lt;/p&gt;

&lt;p&gt;Hope this was an interesting look into remote dev on a big project like Rust. Let me know what you think by commenting below or reaching out on &lt;a href="//twitter.com/ryan_levick"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>vscode</category>
      <category>azure</category>
    </item>
    <item>
      <title>Giving TodoMVC the API It Deserves: Part 1 - Todo Creation</title>
      <dc:creator>Ryan Levick</dc:creator>
      <pubDate>Tue, 30 Apr 2019 15:35:50 +0000</pubDate>
      <link>https://dev.to/azure/giving-todo-mvc-the-api-it-deserves-part-1-todo-creation-19h4</link>
      <guid>https://dev.to/azure/giving-todo-mvc-the-api-it-deserves-part-1-todo-creation-19h4</guid>
      <description>&lt;p&gt;&lt;a href="http://todomvc.com"&gt;Todo MVC&lt;/a&gt; is a great way to compare different JavaScript frameworks and get a feel for how to build an app that's slightly more complex than what can easily fit in a README. &lt;/p&gt;

&lt;p&gt;In this series, we'll start where Todo MVC left off, and build a backend for the app that allows syncing your todos across devices. We'll take a look at the different possibilities inside one particular cloud provider, &lt;a href="https://azure.microsoft.com/en-us?WT.mc_id=devto-blog-rylevick"&gt;Azure&lt;/a&gt;, but the hope is that eventually others can add similar tutorials for other cloud providers. &lt;/p&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Frontend
&lt;/h2&gt;

&lt;p&gt;We'll start with a completed front end TodoMVC application. If you have a favorite framework already feel free to use the TodoMVC apps found on &lt;a href="http://todomvc.com"&gt;todomvc.com&lt;/a&gt;. We'll use a slightly trimmed down version of the Vue.js version for our example. You can find the code &lt;a href="https://github.com/rylev/todo-cloud/tree/c977967ae50350edb90da6e1a2b0857bc9963be9/client"&gt;here&lt;/a&gt;. Feel free to clone the repo down and run the app locally following the instructions in the README.&lt;/p&gt;

&lt;p&gt;If you're unfamiliar with Vue.js, you can learn more about it from the awesome resources on &lt;a href="https://vuejs.org"&gt;the official website&lt;/a&gt;. We won't need to modify the app too much to make it work with our API so don't worry if you've not used Vue before.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating an API
&lt;/h2&gt;

&lt;p&gt;The very first thing we'll do is create an extremely simple API for creating todos. To keep things simple, we'll use the same language used in Todo MVC, JavaScript, for the backend. We have several options for how to build our API, all of which have their pros and cons. We could, for instance, use some framework like &lt;a href="https://expressjs.com"&gt;Express&lt;/a&gt;, run the app on a virtual machine (VM) that we have to manage ourselves. Or we could let Azure do a bit more work for us and run the API on &lt;a href="https://azure.microsoft.com/en-us/services/app-service?WT.mc_id=devto-blog-rylevick"&gt;Azure App Service&lt;/a&gt; which handles provisioning and even scaling our APP out when it sees lots of traffic.&lt;/p&gt;

&lt;p&gt;But as we're just starting out, we want to keep things simple - the less work we have to do the better. For this reason we'll use Azure's Functions as a Service (FaaS) offering called Azure Functions. With Functions we can write code for handling an HTTP request and deploy it to the cloud without worrying about how many servers we want to run, if they have the right dependencies installed, etc. We just write the code and the service will make sure it runs properly.&lt;/p&gt;

&lt;p&gt;FaaS is also commonly known as serverless, but this name is a bit misleading. There are still servers, we just don't have to worry about managing them; we just write code and the rest is taken care of for is. &lt;/p&gt;

&lt;p&gt;We'll start by creating a function for creating todos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Functions App
&lt;/h2&gt;

&lt;p&gt;The first thing we'll need to do is to create a "Functions App". Various functions are always grouped together under an "app". At first, we'll have one function (one for creating a todo), but eventually we'll have many more. This allows for us group this functions into a logical group. &lt;/p&gt;

&lt;p&gt;There's lots of ways to create an Azure Function app and to populate this app with various functions including from the Azure Portal, VS Code and the command line. I've &lt;a href="https://dev.to/azure/the-most-minimal-serverless-function-3cm1"&gt;written about this before&lt;/a&gt;, if you want to learn more. &lt;/p&gt;

&lt;p&gt;My preferred way for creating an Azure Function is by using the &lt;a href="https://github.com/Azure/azure-functions-core-tools?WT.mc_id=devto-blog-rylevick"&gt;Azure Functions command line tool&lt;/a&gt; (which we can easily install on macOS with brew &lt;code&gt;brew tap azure/functions; brew install azure-functions-core-tools&lt;/code&gt; and on Windows with npm &lt;code&gt;npm i -g azure-functions-core-tools --unsafe-perm true&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;To create a new Azure Functions app run the following and choose &lt;code&gt;node&lt;/code&gt; as the runtime and &lt;code&gt;JavaScript&lt;/code&gt; as the language:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;func init 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And then create an Azure Function by running the following and choosing &lt;code&gt;HTTP trigger&lt;/code&gt; and naming the function &lt;code&gt;CreateTodo&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;func new 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We now have our function living in a &lt;code&gt;CreateTodo&lt;/code&gt; directory. We can run it locally by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# make sure you have an LTS version of node like node 10.15.3&lt;/span&gt;
func start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you visit the &lt;code&gt;http://localhost:7071/api/CreateTodo?name=World&lt;/code&gt; in your browser, you should see "Hello World".&lt;/p&gt;

&lt;h2&gt;
  
  
  Storage
&lt;/h2&gt;

&lt;p&gt;Before we can start writing our function, we'll need to make a decision about where we want to store our data. Again, we want to choose something simple that allows us to efficiently read or write data without much fuss. While we could use a SQL database or some other more robust option, the best option for now would be a simple key/value store that allows us write data to it without having to define the structure beforehand. &lt;/p&gt;

&lt;p&gt;For this, we'll be choosing &lt;a href="https://docs.microsoft.com/en-us/azure/cosmos-db/table-storage-overview?WT.mc_id=devto-blog-rylevick"&gt;Azure Table Storage&lt;/a&gt; which like other key/value stores (e.g., Redis) provides us with a simple way to write data that will be partitioned on some key allowing for efficient lookup. In the case of a todo app where each user has one list of todos, the most straightforward answer is to use an identifier for the user as the key. In our case, since we don't yet care about authentication, we'll just require the user to provide us an email address which we'll use as the key to partition the data. That way when we want to fetch all the user's todos, we just need to provide Table Storage with their email address and it will be able to fetch the todos extremely quickly.&lt;/p&gt;

&lt;p&gt;Alright, enough talking, let's actually get this working. &lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Table Storage Access to the Function
&lt;/h2&gt;

&lt;p&gt;We first need to configure our function to be able to talk to Table Storage. This requires extending the Azure Functions runtime since it only supports HTTP request handling by default. &lt;/p&gt;

&lt;p&gt;We can do this with the Azure Functions CLI tool. To set up the boiler plate around the extensions system run the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;func extensions &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Among other things, this creates an &lt;code&gt;extensions.csproj&lt;/code&gt; file. If you've never done dotnet development before, a &lt;code&gt;csproj&lt;/code&gt; file is just a project definition file for a dotnet project written in xml. The functions runtime is written in dotnet, so it makes sense that in order to extend it we'll need to edit a &lt;code&gt;csproj&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;extensions.csproj&lt;/code&gt; file we need to add the following line to the &lt;code&gt;ItemGroup&lt;/code&gt; list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;PackageReference&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"Microsoft.Azure.WebJobs.Extensions.Storage"&lt;/span&gt; &lt;span class="na"&gt;Version=&lt;/span&gt;&lt;span class="s"&gt;"3.0.4"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This indicates we want to use the storage extension which allows us to use Table Storage among other types of storage services like blobs and files. &lt;/p&gt;

&lt;p&gt;We need to run &lt;code&gt;func extensions install&lt;/code&gt; again to install any dependencies for this particular extension.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Our Function to Use Table Storage
&lt;/h2&gt;

&lt;p&gt;Ok, now that we can use the storage extension in our functions app, we need to configure our &lt;code&gt;CreateTodo&lt;/code&gt; function to actually use table storage.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;CreateTodo&lt;/code&gt; directory, there is the &lt;code&gt;function.json&lt;/code&gt; file which is a configuration for this particular function. It should contain the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bindings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"authLevel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"function"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"httpTrigger"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"direction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"in"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"req"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"methods"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"post"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"direction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"out"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"res"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;bindings&lt;/code&gt; value lets our function know how its bound to the outside world. In this case, we're letting the function know it will be triggered by an http POST request we'll call &lt;code&gt;req&lt;/code&gt; and it will return an http response we'll call &lt;code&gt;res&lt;/code&gt;. Our function can be triggered by other things like timers and events, but this one is configured for http.&lt;/p&gt;

&lt;p&gt;We need to add an additional binding for Table Storage. Add the following to the &lt;code&gt;"bindings"&lt;/code&gt; array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"table"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tableName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Todos"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"direction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"out"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"todosTable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"connection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"STORAGE_CONNECTION"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;type&lt;/code&gt; field indicates we're creating a binding for a table, &lt;code&gt;tableName&lt;/code&gt; indicates we're interacting with a table named &lt;code&gt;Todos&lt;/code&gt; (which we'll create soon), &lt;code&gt;direction&lt;/code&gt; indicates we're writing &lt;code&gt;out&lt;/code&gt; to the table and not reading &lt;code&gt;in&lt;/code&gt; from it, &lt;code&gt;name&lt;/code&gt; is the name we'll use to refer to our table in the function's code, and &lt;code&gt;connection&lt;/code&gt; is the environment variable where we'll store our info on how to connect to our storage account like the account name and account key.&lt;/p&gt;

&lt;h2&gt;
  
  
  Talking to Table Storage
&lt;/h2&gt;

&lt;p&gt;Now that we've configured our function to use table storage we need to actually use it. In the &lt;code&gt;CreateTodo&lt;/code&gt; directory, there is an &lt;code&gt;index.js&lt;/code&gt; file which contains the code for our Function. Replace its contents with the follow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// check for an email inside of the Authorization header&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;authorization&lt;/span&gt;&lt;span class="dl"&gt;"&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;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// there was no body or no Authorization header&lt;/span&gt;
    &lt;span class="c1"&gt;// setting context.res will make our function return the specified response&lt;/span&gt;
    &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;missing body or authorization header&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;generateId&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&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;validTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;invalid todo&lt;/span&gt;&lt;span class="dl"&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="c1"&gt;// the todo is valid&lt;/span&gt;
  &lt;span class="c1"&gt;// write to the todosTable&lt;/span&gt;
  &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bindings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todosTable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
    &lt;span class="na"&gt;PartitionKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;RowKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;
  &lt;span class="p"&gt;}]&lt;/span&gt;

  &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// the response is a 200 by default&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;validTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todo&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="nx"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;generateId&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;xy&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x3&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mh"&gt;0x8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Functions require that we export an async function that takes two arguments: a &lt;code&gt;context&lt;/code&gt; object that represents the context of our function and a &lt;code&gt;req&lt;/code&gt; object that represents the current http request.&lt;/p&gt;

&lt;p&gt;Our function simply checks that we have an &lt;code&gt;Authorization&lt;/code&gt; header (which we access using all lowercase letters and that we assume is an email address) and a request body. If not, we return a http &lt;code&gt;400&lt;/code&gt; response.&lt;/p&gt;

&lt;p&gt;We then create a &lt;code&gt;todo&lt;/code&gt; object with a generated id and a title passed to us in the request body. We then check to make sure that the todo is valid (by checking that title is truthy).&lt;/p&gt;

&lt;p&gt;Once we know we have a valid &lt;code&gt;todo&lt;/code&gt; we can set &lt;code&gt;context.bindings.todosTable&lt;/code&gt; to an array of objects that will be stored in our table. Remember that we set &lt;code&gt;todosTable&lt;/code&gt; to be the name of our table binding in the &lt;code&gt;functions.json&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;The object we put in the array assigned to &lt;code&gt;todosTable&lt;/code&gt; has three keys:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;code&gt;PartitionKey&lt;/code&gt; is how our table will be partitioned. Table Storage can do very fast lookups on partitions, so it makes sense for us to partition by email so that when we want to look up the todo by email, Table Storage can quickly return us all todos associated with that email.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RowKey&lt;/code&gt; is a unique identifier within a partition. We'll use the id we've generated. These ids are globally unique, which is even more unique than &lt;code&gt;RowKey&lt;/code&gt;s need to be.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;title&lt;/code&gt; is just the title of our todo. Table Storage requires us to provide &lt;code&gt;PartitionKey&lt;/code&gt; and &lt;code&gt;RowKey&lt;/code&gt; and we can add as many additional fields as we want. For now, we're just storing the &lt;code&gt;title&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Creating our Table Storage
&lt;/h2&gt;

&lt;p&gt;In order for us to successfully run this Function, we need to actually create an Azure Storage account so we can use Table Storage. To do this, we'll use the &lt;a href="https://github.com/Azure/azure-cli"&gt;Azure CLI&lt;/a&gt; which you can install with the directions &lt;a href="https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest&amp;amp;WT.mc_id=devto-blog-rylevick"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First you'll need to make sure you're logged in to Azure which you can do by running &lt;code&gt;az login&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then we'll create a resource group where all of our Todo Cloud resources will live. Resource groups are just a way of grouping resources so you can handle them all together. Run the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;az group create &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--name&lt;/span&gt; TodoCloud &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--location&lt;/span&gt; eastus
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Feel free to choose a &lt;a href="https://azure.microsoft.com/en-us/global-infrastructure/locations?WT.mc_id=devto-blog-rylevick"&gt;location&lt;/a&gt; that's closer to you. You can also see all locations by running &lt;code&gt;az account list-locations --query "[].name"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next we'll &lt;a href="https://docs.microsoft.com/en-us/cli/azure/storage/account?view=azure-cli-latest&amp;amp;WT.mc_id=devto-blog-rylevick"&gt;create the account&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;az storage account create &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--name&lt;/span&gt; todocloud &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--resource-group&lt;/span&gt; TodoCloud &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--location&lt;/span&gt; eastus &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--sku&lt;/span&gt; Standard_LRS &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--encryption&lt;/span&gt; blob
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can change &lt;code&gt;--location&lt;/code&gt; to a location near to you. The rest is fine to leave the same.&lt;/p&gt;

&lt;p&gt;We're getting so close! We now have a storage account, and we can create our &lt;code&gt;Todos&lt;/code&gt; table using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;az storage table create &lt;span class="nt"&gt;--account-name&lt;/span&gt; todocloud &lt;span class="nt"&gt;--name&lt;/span&gt; Todos
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We now have everything in place for our function to work. The last thing we need is to make sure the &lt;code&gt;STORAGE_CONNECTION&lt;/code&gt; environment variable we're using in our &lt;code&gt;functions.json&lt;/code&gt; config file is properly populated. We can do this by setting it in the &lt;code&gt;Values&lt;/code&gt; key found in the &lt;code&gt;local.settings.json&lt;/code&gt; file of our Functions app. These values get automatically set as environment variables our Functions App can use.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;Values&lt;/code&gt; array of your &lt;code&gt;local.settings.json&lt;/code&gt; file add the following key and value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"STORAGE_CONNECTION"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DefaultEndpointsProtocol=https;AccountName=todocloud;AccountKey=$SOME_LONG_KEY"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Make sure that you replace &lt;code&gt;$SOME_LONG_KEY&lt;/code&gt; with a proper account key. You can find a storage account key with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;az storage account keys list &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--account-name&lt;/span&gt; todocloud &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--resource-group&lt;/span&gt; TodoCloud
    &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"[0].value"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With this all in place we should now be able to run our Function App locally again with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;func start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To create a todo we can just use cURL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-XPOST&lt;/span&gt; http://localhost:7071/api/CreateTodo &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"title": "Buy milk"}'&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: ryan.levick@example.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you get a 200 back you can be sure that your todo has been stored in table storage.&lt;/p&gt;

&lt;p&gt;You can use the &lt;a href="https://azure.microsoft.com/en-us/features/storage-explorer?WT.mc_id=devto-blog-rylevick"&gt;Azure Storage Explorer app&lt;/a&gt; to view the data inside your table.&lt;/p&gt;

&lt;h2&gt;
  
  
  Change our TodoMVC app
&lt;/h2&gt;

&lt;p&gt;In our client's code in &lt;code&gt;app.js&lt;/code&gt;, we'll want to replace the &lt;code&gt;addTodo&lt;/code&gt; method (which is what gets called when the user hits the enter key after typing a todo to create it).&lt;br&gt;
Replace the existing body of &lt;code&gt;addTodo&lt;/code&gt; with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&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;newTodo&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;newTodo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trim&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;value&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="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;API&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/CreateTodo&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="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Accept&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ryan.levick@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&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;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&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;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;completed&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;newTodo&lt;/span&gt; &lt;span class="o"&gt;=&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This code is pretty naive and not the best user experience, but it does the trick. Just as before, we get the todo from &lt;code&gt;this.newTodo&lt;/code&gt; and clean it up a bit. But not we make an http POST request to our the API we have running locally. If the response's status is less than 500, we do what we did before and save the todo to our local state and reset the &lt;code&gt;newTodo&lt;/code&gt; input field.&lt;/p&gt;

&lt;p&gt;If we open up the &lt;code&gt;index.html&lt;/code&gt; file at the route of our client, and add a todo, we'll get a CORS error. To enable CORS calls for our app, we'll have to make one last change. We need to add the a &lt;code&gt;Host&lt;/code&gt; key to the JSON object in the &lt;code&gt;local.settings.json&lt;/code&gt; file with the value &lt;code&gt;{"CORS": "*"}&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;If we restart our locally running function, and try to create a todo, it should work.&lt;/p&gt;

&lt;p&gt;Hooray! 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We've done a lot in this post, we created an Azure Function and hooked it up with a newly created Table living in a Storage Account on Azure. &lt;/p&gt;

&lt;p&gt;In the next post we'll create a "GetTodos" endpoint for fetching our todos, and we'll deploy our function to Azure so we don't need to run it locally. &lt;/p&gt;

&lt;p&gt;I'd love to see others takes on how to create a backend for TodoMVC both on Azure and on other cloud providers. Feel free to contribute a PR to &lt;a href="https://github.com/rylev/todo-cloud"&gt;the repo&lt;/a&gt;, write a blog post about your experience or reach out to me on &lt;a href="https://twitter.com/ryan_levick"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>cloud</category>
      <category>serverless</category>
      <category>azure</category>
    </item>
    <item>
      <title>The Most Minimal Serverless Function</title>
      <dc:creator>Ryan Levick</dc:creator>
      <pubDate>Thu, 18 Apr 2019 08:59:23 +0000</pubDate>
      <link>https://dev.to/azure/the-most-minimal-serverless-function-3cm1</link>
      <guid>https://dev.to/azure/the-most-minimal-serverless-function-3cm1</guid>
      <description>&lt;p&gt;I've been having fun creating some APIs using &lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions?WT.mc_id=devto-blog-rylevick"&gt;Azure Functions&lt;/a&gt;. Functions as a Service (FaaS) is a category of 'serverless' products that allow me to write code and easily deploy it without having to worry about anything beyond whether the code itself works - provisioning servers, installing dependencies, and paying for idle servers are all a thing of the past. &lt;/p&gt;

&lt;p&gt;Unfortunately, first getting started with Azure Functions wasn't as smooth as I would have hoped because I didn't fully grasp all the parts that make up the Azure Functions development flow. &lt;/p&gt;

&lt;p&gt;In this post, we'll get a better understanding of how Azure Functions works by creating the simplest function we can by hand. We'll then discuss the various tools available to us that create this boilerplate for us so we don't have to. By the end, you should have a good idea of what's actually happening when you use these tools to help create Azure Functions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Project
&lt;/h3&gt;

&lt;p&gt;First thing we'll want to do is to create an Azure Function project on our local dev machine that contains all the functions for whatever project we're working on. This will have all the code for functions that we can check into source control and some configuration we can use for local testing of our functions. &lt;/p&gt;

&lt;p&gt;At a minimum, a project simply has a &lt;code&gt;host.json&lt;/code&gt; file which specifies which version of the runtime we want to use. This looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With this one file we have a working Azure Functions project! Of course, we have no functions, so it doesn't do too much. Let's create a function.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Function
&lt;/h3&gt;

&lt;p&gt;Our function will be a node function. In the case of node, at a bare minimum we need to create a directory with whatever name we want for our function (e.g., "MyHttpFunction") that has a JavaScript file named &lt;code&gt;index.js&lt;/code&gt; that has one exported function we'll look at below and a &lt;code&gt;function.json&lt;/code&gt; file that describes the function. &lt;/p&gt;

&lt;p&gt;To inform the functions runtime that we're expecting an incoming request and we want to provide an outgoing response we need to create a &lt;code&gt;function.json&lt;/code&gt; describing these bindings (&lt;code&gt;MyHttpFunction/function.json&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bindings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"httpTrigger"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"direction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"in"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"authLevel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"anonymous"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"methods"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"get"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"req"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"direction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"out"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"res"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The first object in our &lt;code&gt;bindings&lt;/code&gt; array says we want this function to be triggered by an http request (specified by "type" being set to "httpTrigger"), it will require anonymous authorization (a.k.a no authorization), and it will only be triggered on http GET requests. We also have to provide a "name" although we could call it whatever we want since it we access it as a parameter to our function. By specifying the "direction" as "in" we're saying that this is an incoming http request that's triggering our function.&lt;/p&gt;

&lt;p&gt;The second object says we want to create a binding of type "http" that we'll set in our function on a key named "res" on our context object. By specifying the "direction" as "out", we're saying our function will return or output an http response.&lt;/p&gt;

&lt;p&gt;Next, let's create the JavaScript file &lt;code&gt;MyHttpFunction/index.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// req is the request that triggered this function&lt;/span&gt;
  &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&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 specified res as our response object in our bindings&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This function will simply ignore the incoming request and set the body of the response to "Hello".&lt;/p&gt;

&lt;p&gt;While we're using node in this case, Functions work with many other languages as well. For some other languages like C#, just the code file is enough since these languages use attributes in the code to specify the information - no directory or &lt;code&gt;function.json&lt;/code&gt; file is needed. If we were to create a minimal C# function it would probably look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.IO&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.AspNetCore.Mvc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Azure.WebJobs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Azure.WebJobs.Extensions.Http&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.AspNetCore.Http&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Extensions.Logging&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;MyFunctions&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HttpTrigger&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;FunctionName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MyHttpFunction"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IActionResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;HttpTrigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AuthorizationLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Anonymous&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"get"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Route&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="n"&gt;HttpRequest&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;ILogger&lt;/span&gt; &lt;span class="n"&gt;log&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="n"&gt;ActionResult&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;OkObjectResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can test our functions locally by installing the &lt;a href="https://github.com/Azure/azure-functions-core-tools?WT.mc_id=devto-blog-rylevick"&gt;Azure Functions CLI tool&lt;/a&gt; (which we can easily install on macOs with brew &lt;code&gt;brew tap azure/functions; brew install azure-functions-core-tools&lt;/code&gt; and on Windows with npm &lt;code&gt;npm i -g azure-functions-core-tools --unsafe-perm true&lt;/code&gt;) and running the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;func host start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Function Apps
&lt;/h2&gt;

&lt;p&gt;So now we have a project and a function inside of it. We can run this function locally, but obviously we'd like to deploy this to the cloud.&lt;/p&gt;

&lt;p&gt;All functions in Azure are contained within Function Apps. Function Apps are a way to group different functions to together into logical groups. If you're creating an API for instance, you'll probably have one function per endpoint and group all of those functions into one Function App. &lt;/p&gt;

&lt;p&gt;Function apps require you to make decisions about a few things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Where will your functions live?&lt;/strong&gt; The obvious choice here is to pick a place nearest to your users. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Which OS the function is running on?&lt;/strong&gt; Because code you're writing for functions is generally cross platform and you're not having to manage the infrastructure yourself, it shouldn't matter too much which platform you choose. You can edit Windows functions but not Linux ones from the portal (which we'll discuss later), but this isn't a huge advantage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Which hosting plan should we use?&lt;/strong&gt;: consumption plan means you'll only pay for whatever you use. If you have a large spike in demand though, your app may temporarily slow down as the Azure automatically provisions more capacity for your function.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Which runtime stack will we run on?&lt;/strong&gt;: This needs to match whatever language runtime you've developed your function against. In our case, we'll want to select node. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Creating a Function App
&lt;/h3&gt;

&lt;p&gt;There are several ways to create an Azure Function App, but perhaps the simplest way for now to create one is to use the &lt;a href="https://portal.azure.com/#create/Microsoft.FunctionApp?WT.mc_id=devto-blog-rylevick"&gt;Azure Portal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We can create an Azure Function App by clicking on the "Create a resource" button in the top right of the portal, searching for "Azure Function" and following the wizard. &lt;/p&gt;

&lt;h3&gt;
  
  
  Publishing our Functions
&lt;/h3&gt;

&lt;p&gt;Once our Function App is created, it's waiting for us to publish functions to it. We can do this using the &lt;a href="https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest&amp;amp;WT.mc_id=devto-blog-rylevick"&gt;Azure CLI tool&lt;/a&gt; and the Azure Functions CLI tool we used to test our functions locally. You can do this by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;az login &lt;span class="c"&gt;# logs you into Azure&lt;/span&gt;
func azure functionapp publish &lt;span class="nv"&gt;$NAME_OF_THE_FUNCTION_APP_YOU_CREATED&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It's important to realize that this tool replaces the contents of the Azure Functions App with the content of your local Functions project. If you've already deployed functions to that Functions App, those will be overwritten. But the first time we run this, it will simply replace the empty contents of the Functions App with the contents of our local project.&lt;/p&gt;

&lt;p&gt;Once this is done, you will have a running Azure Function!&lt;/p&gt;

&lt;h2&gt;
  
  
  Reducing the Boiler Plate
&lt;/h2&gt;

&lt;p&gt;While we were easily able to create very simple functions manually, there are tools that will help us with all these steps so that we don't have to write out all the boilerplate ourselves.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating an Azure Function Project
&lt;/h3&gt;

&lt;p&gt;Using the Azure Functions CLI tool, we can run &lt;code&gt;func init&lt;/code&gt; to initialize a project. This will take you through some questions about which language runtime (e.g. node, dotnet, etc.) you want to use, and eventually it will create the necessary files for a project like the &lt;code&gt;host.json&lt;/code&gt; file we've already seen and some other files that help you customize the functions environment. &lt;/p&gt;

&lt;p&gt;If you prefer Visual Studio Code, you can use the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurefunctions&amp;amp;WT.mc_id=devto-blog-rylevick"&gt;Azure Functions extension&lt;/a&gt;. With that installed, you can open the command palette (cmd/ctrl+shift+p) and search for "Azure Functions: Create New Project" to create a new project. This will also take you through a wizard experience for creating a function similar to what you will find with &lt;code&gt;func init&lt;/code&gt;. This command also allows you to create the first function (but if you want you can choose &lt;code&gt;Skip for now...&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating an Azure Function
&lt;/h3&gt;

&lt;p&gt;Using the Azure Functions CLI tool, you can run &lt;code&gt;func new&lt;/code&gt; to take you through a wizard process for creating a function. You just need to think about what kind of trigger for your function you want.&lt;/p&gt;

&lt;p&gt;For Visual Studio Code users who have the Azure Functions extension, you can use the command palette (cmd/ctrl+shift+p), search for "Azure Functions: Create Function". This will take you through a wizard experience similar to the one from the &lt;code&gt;func&lt;/code&gt; CLI tool.&lt;/p&gt;

&lt;p&gt;Additionally, you can create a function from the Azure Portal from the Functions App screen (there's a big plus button next to the list of functions). An issue with this is that you won't have any local copy of your function that you can save in version control. You'll want to eventually download the functions app your function is a part of to your local machine so you can add it to your version control system. This typically requires merging functions that exist locally with the one that was just created on Azure which can be a real headache...&lt;/p&gt;

&lt;p&gt;You can also make edits to running functions, but you'll need to repeat those changes in your local project if you want it to be reflected in version control. My recommendation is to try to avoid creating or editing functions from the portal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Function App in Azure
&lt;/h3&gt;

&lt;p&gt;If you have the Azure CLI tool installed, you can run &lt;code&gt;az functionapp create&lt;/code&gt; along with the required options. Pro tip: you can use the Azure CLI tool from the portal by using the &lt;a href="https://docs.microsoft.com/en-us/azure/cloud-shell/overview?WT.mc_id=devto-blog-rylevick"&gt;Cloud Shell&lt;/a&gt; feature which gives you a bash or powershell command line with the tool already installed. &lt;/p&gt;

&lt;p&gt;From Visual Studio Code, using the command palette (cmd/ctrl+shift+p), you can search for "Azure Functions: Create Function App in Azure". This will take you through a Wizard experience similar to the Azure CLI experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Overall, it's important to remember that functions don't require very much setup to run. You'll need to make sure you've created an Functions App and the minimal pieces for a local project. Each function requires at most 2 small files to run.&lt;/p&gt;

&lt;p&gt;By now you should have an understanding of at a minimum what is required to run an Azure Function and the many ways that you can create those pieces. If you want to keep going, I recommend checking out the &lt;a href="https://docs.microsoft.com/en-us/learn/paths/create-serverless-applications?WT.mc_id=devto-blog-rylevick"&gt;MS Learn learning path on Functions&lt;/a&gt;! If you want to learn more, please feel free to reach out to me on &lt;a href="https://twitter.com/ryan_levick"&gt;Twitter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>azure</category>
      <category>serverless</category>
      <category>functions</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The Promise of WebAssembly</title>
      <dc:creator>Ryan Levick</dc:creator>
      <pubDate>Thu, 11 Apr 2019 08:25:06 +0000</pubDate>
      <link>https://dev.to/ryan_levick/the-promise-of-webassembly-2obi</link>
      <guid>https://dev.to/ryan_levick/the-promise-of-webassembly-2obi</guid>
      <description>&lt;p&gt;&lt;a href="https://webassembly.org"&gt;WebAssembly&lt;/a&gt; (wasm) is a assembly binary format made for the web. Originally meant as a way to run native code in web browsers, wasm has recently expanded to be able to run outside of the browser. &lt;/p&gt;

&lt;p&gt;In this post we'll take a closer look at what WebAssembly is and the related technologies around it, and we'll explore what this might mean for one particular use case - functions as a service (FaaS) a.k.a serverless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining Terms
&lt;/h2&gt;

&lt;p&gt;WebAssembly is assembly for a virtual machine. I mean 'virtual machine' here in the original sense - a conceptual machine - a machine that only theoretically exists. You can write code for that conceptual machine and a compiler can then compile it to assembly that runs on a real host machine. &lt;/p&gt;

&lt;p&gt;The &lt;a href="https://wasi.dev"&gt;WebAssembly System Interface&lt;/a&gt; (WASI) is a specification that allows WebAssembly binaries to talk to the host machine's OS through a well-defined and cross platform interface. This allows WebAssembly binaries to do useful things like write files and open TCP sockets. &lt;/p&gt;

&lt;p&gt;Fastly's &lt;a href="https://github.com/fastly/lucet"&gt;Lucet&lt;/a&gt;, Mozilla's &lt;a href="https://github.com/CraneStation/wasmtime"&gt;Wasmtime&lt;/a&gt;, and &lt;a href="https://github.com/wasmerio/wasmer"&gt;wasmer&lt;/a&gt; are all compilers that perform ahead-of-time (AOT) compilation through a library called &lt;a href="https://github.com/CraneStation/cranelift"&gt;Cranelift&lt;/a&gt; to turn the WebAssembly code into native assembly. Lucet and Wasmtime are also runtimes that implement the WASI specification allowing these binaries to talk to the host machine in a uniform, cross-platform way. &lt;/p&gt;

&lt;h2&gt;
  
  
  Advantages Over Existing Technologies
&lt;/h2&gt;

&lt;p&gt;So what makes this different from existing technologies?&lt;/p&gt;

&lt;h3&gt;
  
  
  Sanboxing with Fine-grained Permissions
&lt;/h3&gt;

&lt;p&gt;WebAssembly binaries are completely sandboxed, meaning that they only have access to the host machine's resources through WASI. &lt;/p&gt;

&lt;p&gt;There are other systems that are also sandboxed at the application level - for instance, node through v8. The difference here is the level of control you have. On one side of the spectrum, v8 is completely sandboxed and does not offer a way to talk to host systems. Node is a way to open up v8 to allow it to take to the host system. Unfortunately, node completely opens up the host system to the application in an uncontrolled and unmanaged way.&lt;/p&gt;

&lt;p&gt;WASI and the various runtimes allow for more fine-grained permission. For example, instead of allowing access to the host system's entire file system, a user can grant permissions to only a certain directory. Similar controls exist for networking and other system resources. &lt;/p&gt;

&lt;p&gt;This provides a way to run programs where you can control exactly what resources the program is allowed to access.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lightweight
&lt;/h3&gt;

&lt;p&gt;In addition to this fine-grained sandboxing, the WebAssembly/WASI runtime is very lightweight in terms of overhead. Unlike Docker which also provides fine grained sandboxing, WebAssembly operates at the application level not the OS userland level. This means WebAssembly programs can be started much more quickly and will consume much less resources both on the host system and also when being transported over the wire. &lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means For FaaS
&lt;/h2&gt;

&lt;p&gt;A completely sandboxed and lightweight environment can allow for more tightly packing serverless applications on the same machine - allowing for serverless providers to lower costs. Additionally, startup times should be much lower (theoretically on the order of 1-2 ms).&lt;/p&gt;

&lt;p&gt;Also, WebAssembly is meant to be completely language agnostic so in the future, you should be able to run whatever languages are capable of running in a WebAssembly environment, which could be every language.&lt;/p&gt;

&lt;p&gt;This also makes local testing much easier as all the user needs to install is a WebAssembly runtime (a single binary). &lt;/p&gt;

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

&lt;p&gt;Hopefully this gives you a decent overview of what WebAssembly is about at least in the context of helping push FaaS forward. &lt;/p&gt;

&lt;p&gt;If you enjoyed this article reach out to me on &lt;a href="https://twitter.com/ryan_levick"&gt;Twitter&lt;/a&gt; and let me know if you'd like me to write more about WebAssembly.&lt;/p&gt;

</description>
      <category>webassembly</category>
      <category>faas</category>
      <category>serverless</category>
      <category>wasi</category>
    </item>
  </channel>
</rss>
