<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[John Papa]]></title><description><![CDATA[Hi, I'm John Papa. I author this blog, create courses for Pluralsight, and work in Developer Relations. I speak at events, contribute to OSS, and I train technology thought leaders]]></description><link>https://johnpapa.net/</link><image><url>https://johnpapa.net/favicon.png</url><title>John Papa</title><link>https://johnpapa.net/</link></image><generator>Ghost 2.31</generator><lastBuildDate>Fri, 04 Oct 2019 12:55:19 GMT</lastBuildDate><atom:link href="https://johnpapa.net/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Shifting Your Node Express APIs to Serverless]]></title><description><![CDATA[Leaning on your express experience you can shift your APIs to serverless with minimal effort resulting in an API that scales well and lets you focus on the code, not the servers.]]></description><link>https://johnpapa.net/shifting-your-node-express-apis-to-serverless/</link><guid isPermaLink="false">5d813c6b6d50c4003879eda6</guid><category><![CDATA[node]]></category><category><![CDATA[typescript]]></category><category><![CDATA[serverless]]></category><dc:creator><![CDATA[John Papa]]></dc:creator><pubDate>Tue, 17 Sep 2019 20:19:55 GMT</pubDate><media:content url="https://johnpapa.net/content/images/2019/09/ea09p7nqzplingmhaisg-1.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://johnpapa.net/content/images/2019/09/ea09p7nqzplingmhaisg-1.jpg" alt="Shifting Your Node Express APIs to Serverless"><p>If you have Express APIs you are not alone. But have you ever considered shifting this server based API model to a serverless one? Stick with me and this by the end of this article you'll see how to do it and have a working example to try for yourself.</p><p>I love Node and Express for creating APIs! However, these require a server and paying for that server in the cloud. Shifting to serverless alleviates the cost, the server upkeep, helps scale up and down easily, and reduces the surface area of the middleware required for a robust Express app. Is it perfect? No, of course not! But this is a solid option if these factors affect you. You'll learn how to shift your Node Express APIs to Serverless Functions in this article.</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://johnpapa.net/content/images/2019/09/image.png" class="kg-image" alt="Shifting Your Node Express APIs to Serverless"><figcaption>Shifting from express to azure functions</figcaption></figure><!--kg-card-end: image--><h2 id="what-you-ll-learn">What You'll Learn</h2><p>We'll start by exploring and running the Node and Express APIs in the sample project. Then we'll walk through creating an Azure Functions app followed by refactoring the Express routes and data calls to the Azure Functions app. Finally, we'll explore the results together. Through this you'll learn to:</p><ol><li>create an Azure Function app</li><li>refactor existing Express APIs to Azure Functions</li><li>understand the differences between the approaches</li></ol><p>While this article walks through the steps to shift your APIs from Express to Azure Functions, you can also follow along with the completed sample project on GitHub.</p><p>We'll walk through the code and the steps together, and at the end I share links to everything you need to get started and try this for yourself.</p><h2 id="planning-the-shift-to-serverless">Planning the Shift to Serverless</h2><p>Before shifting the app to serverless, let's think about why we might want to do this and what effort it might take to perform the shift.</p><p>First, the Express app requires a server which you must configure and maintain. It would be nice to alleviate some of this effort and cost.</p><p>Express apps often have a long list of middleware and logic to start the server. This sample project has a minimal amount of middleware, but you'd certainly want more in a production app with more concerns (ex: security) and features (ex: logging). While Azure Functions don't make this go away entirely, there is less logic and less code to start Azure Functions. Often there is very little code and some configuration. What does this mean in a concrete example? Well, for this sample app the <em>server.ts</em> file effectively goes away.</p><p>So why make this shift? Overall there is less to think about with serverless.</p><h2 id="about-the-sample-project">About the Sample Project</h2><p>What's in the <a href="https://github.com/johnpapa/express-to-functions">sample project on GitHub</a> that you'll learn about in this article? Great question!</p><p>The project represents a simple Node Express APIs app in TypeScript that is shifted to Azure Functions.</p><p>But what if you aren't using TypeScript? That's fine. If your Express app is using JavaScript, feel free to shift it to Azure Functions using JavaScript.</p><p>The client app is Angular, however it could just as easily be Vue or React. The heroes and villains theme is used throughout the app.</p><p>While we will use an Angular app, one of the great things about Azure Functions is that you can run it locally on you computer, debug it, and call HTTP functions using tools like a browser, Postman, Insomnia (as shown below).<br></p><!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://thepracticaldev.s3.amazonaws.com/i/1hhzrhiktn18umnpy1k2.jpg" class="kg-image" alt="Shifting Your Node Express APIs to Serverless"></figure><!--kg-card-end: image--><h2 id="getting-started">Getting Started</h2><p>Let's start by getting the code and setting up the development environment. Follow these steps to prepare the code.</p><ol><li>Clone this repository</li><li>Install the npm packages</li><li>Build the Node Express and the Angular code</li></ol><!--kg-card-begin: code--><pre><code class="language-bash">git clone https://github.com/johnpapa/express-to-functions.git
cd express-to-functions
npm install
npm run node-ng:build
</code></pre><!--kg-card-end: code--><p>Make a copy of the <em>env.example</em> file named <em>.env</em>, in the root of the project. It should contain the following code.</p><p><em>.env</em></p><!--kg-card-begin: code--><pre><code>NODE_ENV=development
PORT=7070
WWW=./
</code></pre><!--kg-card-end: code--><p>Environment Variables: Applications may have very important environment variables located in the root in <em>.env</em> file. This file is not checked into GitHub because it may contain sensitive information.</p><p>Now our code is ready for us to use it. But before we do, let's take a step back and see what we have.</p><h2 id="node-and-express-apis">Node and Express APIs</h2><p>Now let's explore the <a href="https://github.com/johnpapa/express-to-functions">sample project on GitHub</a>.</p><p>This is a conventional Node and Express application that serves the following eight endpoints.</p><!--kg-card-begin: markdown--><table>
<thead>
<tr>
<th>method</th>
<th>route endpoint</th>
</tr>
</thead>
<tbody>
<tr>
<td>GET</td>
<td>heroes</td>
</tr>
<tr>
<td>POST</td>
<td>heroes</td>
</tr>
<tr>
<td>PUT</td>
<td>heroes:id</td>
</tr>
<tr>
<td>DELETE</td>
<td>heroes/:id</td>
</tr>
<tr>
<td>GET</td>
<td>villains</td>
</tr>
<tr>
<td>POST</td>
<td>villains</td>
</tr>
<tr>
<td>PUT</td>
<td>villains:id</td>
</tr>
<tr>
<td>DELETE</td>
<td>villains/:id</td>
</tr>
</tbody>
</table>
<!--kg-card-end: markdown--><p>The structure of the Node Express app is straight-forward and contained in the <em>server</em> folder.</p><!--kg-card-begin: code--><pre><code class="language-files">server
 | - routes
 | | - hero.routes.ts  👈 The hero routes
 | | - index.ts
 | | - villain.routes.ts
 | - services
 | | - data.ts         👈 The hero data (could be database API calls)
 | | - hero.service.ts 👈 The logic to get the hero data
 | | - index.ts
 | | - villain.service.ts
 | - index.ts
 | - server.ts         👈 The Express server
 | - tsconfig.json
</code></pre><!--kg-card-end: code--><p>The entry point is the <em>server/index.ts</em> file which runs the <em>server.ts</em> code to start the Express server. Then the routes (such as /heroes) are then loaded from the <em>/routes</em> folder. These routes execute the appropriate code in the <em>/services</em> folder. The <em>data.ts</em> file is where the app defines the data store configuration.</p><p>For example, when the client app makes a HTTP GET to the <em>/heroes</em> route, the route executes the logic in the <em>/services/hero.service.ts</em> file to get the heroes.</p><p>Feel free to explore the code for the Express logic in the <em>server</em> folder on your own.</p><p>Here is a screen capture of the running application.</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://thepracticaldev.s3.amazonaws.com/i/bp83wqpwc4ne6lot6x8d.jpg" class="kg-image" alt="Shifting Your Node Express APIs to Serverless"></figure><!--kg-card-end: image--><h3 id="run-and-debug-the-express-app">Run and Debug the Express App</h3><p>When I want to become familiar with an app, I find it helpful to run and step through an app with the debugger. Let's do this together.</p><p>Let's start by opening the app in Visual Studio Code.</p><ol><li>Open <em>proxy.conf.json</em> and change the port to <strong>7070</strong> (our Express app)</li><li>Open the VS Code Command Palette <strong>F1</strong></li><li>Type <strong>View: Show Debug</strong> and press <strong>ENTER</strong></li><li>Select <strong>Debug Express and Angular</strong></li><li>Press <strong>F5</strong></li><li>Notice the browser opens to <a href="http://localhost:7070">http://localhost:7070</a></li></ol><p>You may now set breakpoints in the Express and Angular code.</p><p>Here the debugger is stopped on a breakpoint in the Angular app.</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://thepracticaldev.s3.amazonaws.com/i/ak08usxnehfpgfj8vg9a.jpg" class="kg-image" alt="Shifting Your Node Express APIs to Serverless"></figure><!--kg-card-end: image--><p>Here the debugger is stopped on a breakpoint in the Express app.</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://thepracticaldev.s3.amazonaws.com/i/z328yfch0tflkw46wk88.jpg" class="kg-image" alt="Shifting Your Node Express APIs to Serverless"></figure><!--kg-card-end: image--><p>The files <em>.vscode/launch.json</em> and <em>.vscode/tasks.json</em> are integral to the debugging experience for this project. I encourage you to explore those files and copy/refactor their contents for your own purposes.</p><h2 id="making-the-shift">Making the Shift</h2><p>Now that we've run the app and explored where we started with Express, let's plan the shift from Express to serverless. I like to solve problems by breaking them down into smaller problems. In this case, et's start by breaking down the Node Express app can be broken down into its three main areas:</p><ol><li>The Express server ( mostly in <em>server.ts</em>)</li><li>The routes (<em>routes/</em>*)</li><li>The data access logic (<em>services/</em>.service.ts*)</li></ol><p>We'll take these one at a time as we make the shift for all of these. Let's start with shifting from the Express server to Azure Functions.</p><h3 id="express-azure-functions">Express 👉 Azure Functions</h3><p>The Express server runs the API on a server. You can create an Azure Functions project to run the APIs instead. I recommend using the <a href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurefunctions&amp;WT.mc_id=johnpapanet-blog-jopapa">VS Code Extension for Azure Functions</a>. Once installed, follow these steps to create the Azure Functions on your computer.</p><ol><li>Open the command palette by pressing <strong>F1</strong></li><li>Type and select <strong>Azure Functions: Create New Project</strong></li><li>Choose <strong>Browse</strong> to find the folder to create the functions</li><li>Create a new folder in your project called <em>functions</em></li><li>Select <strong>TypeScript</strong></li><li>When prompted to create a function, select <strong>Skip for Now</strong></li></ol><p>Congratulations, you just created an Azure Function app!</p><p>The Azure Functions app is what serves our routes.</p><p>Creating the function app in a <em>functions</em> folder helps separate it from the Angular and Express apps in the same project. You certainly don't have to put them all in the same project together, but for this sample it helps to see them all in one place.</p><h3 id="shifting-routes-create-your-first-function">Shifting Routes - Create Your First Function</h3><p>You may recall that we have eight endpoints in the Express app. Follow these steps to create a function for the first of these endpoints. We'll come back and create the other seven endpoints soon.</p><ol><li>Open the command palette by pressing <strong>F1</strong></li><li>Type and select <strong>Azure Functions: Create Function</strong></li><li>Choose <strong>HTTP Trigger</strong> for the type of function</li><li>Enter <strong>heroes-get</strong> as the name of the function</li><li>Select <strong>Anonymous</strong> for the authentication level</li></ol><p>Notice that there is now a folder <em>functions/heroes-get</em> that contains a few files. The <em>function.json</em> contains the configuration for the function. Open <em>function.json</em> and notice that the methods allow both GET and POST. Change this to only allow GET.</p><p>By default the route to execute this function will be <strong>heroes-get</strong>. The route in the Express app is simply <strong>heroes</strong>. We want these to be the same, so add a <code>route: "heroes"</code> entry in the <strong>bindings</strong> section in the <em>function.json</em>. Now the function will be executed when an HTTP GET on <strong>/heroes</strong> is called.</p><p>Your <em>function.json</em> should look like the following code.</p><!--kg-card-begin: code--><figure class="kg-card kg-code-card"><pre><code class="language-json">{
  "disabled": false,
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": ["get"],
      "route": "heroes"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ],
  "scriptFile": "../dist/heroes-get/index.js"
}
</code></pre><figcaption>function.json</figcaption></figure><!--kg-card-end: code--><p>The other important file here in the <em>functions/heroes-get</em> folder is <em>index.ts</em>. This file contains the logic that runs when the route is invoked. We already have all this logic from our Express app. We'll go get that next.</p><h3 id="data-shift-the-services-to-serverless">Data - Shift the Services to Serverless</h3><p>All of the logic that executes to interact with the data store is contained in the <em>server/services</em> folder of the Express app. We can lift that code and shift it over to the Azure Functions app and make a few small adjustments. This may seem like it wouldn't work, but let's consider what is different about the Express app and the Azure Functions app. Here are some main differences in the services.</p><ol><li>The Express app uses the npm package <strong>express</strong> while the Azure Functions app uses the npm package <strong>@azure/functions</strong></li><li>Express has <code>req</code> and <code>res</code> parameters representing Request and Response. Azure Functions puts these inside of a <code>context</code> object variable.</li></ol><p>That is all we have to know. So armed with this information, it makes sense that we can copy the code for the services from the Express app to the Azure Functions app with minimal changes. Let's do this now.</p><h4 id="shift-the-code-from-express-to-functions">Shift the Code from Express to Functions</h4><p>Why write everything from scratch and throw away your hard work if you do not have to, right? Well, we can take the services code from our Express app and copy it to our Azure Functions app.</p><ol><li>Copy the <strong>server/services</strong> folder</li><li>Paste into the <strong>functions</strong> folder</li></ol><p>Now we have some minor refactoring to make the code work with Azure Functions instead of Express. The one thing that changes here is that the routing API and how request and response are passed. Let's refactor for this API difference.</p><ol><li>Open the <strong>functions/services/hero.service.ts</strong> file</li><li>Replace <code>import { Request, Response } from 'express';</code> with <code>import { Context } from '@azure/functions';</code></li><li>Replace every instance of <code>(req: Request, res: Response)</code> with <code>({ req, res }: Context)</code>.</li></ol><p>Your code will look like the following when you are done refactoring. Notice the places that changed are commented.</p><!--kg-card-begin: code--><figure class="kg-card kg-code-card"><pre><code class="language-typescript">
// 👇 This was import { Request, Response } from 'express';
import { Context } from '@azure/functions';
import * as data from './data';

// 👇 This was async function getHeroes(req: Request, res: Response) {
async function getHeroes({ req, res }: Context) {
  try {
    const heroes = data.getHeroes();
    res.status(200).json(heroes);
  } catch (error) {
    res.status(500).send(error);
  }
}

// 👇 This was async function postHero(req: Request, res: Response) {
async function postHero({ req, res }: Context) {
  const hero = {
    id: undefined,
    name: req.body.name,
    description: req.body.description
  };

  try {
    const newHero = data.addHero(hero);
    res.status(201).json(newHero);
  } catch (error) {
    res.status(500).send(error);
  }
}

// 👇 This was async function putHero(req: Request, res: Response) {
async function putHero({ req, res }: Context) {
  const hero = {
    id: req.params.id,
    name: req.body.name,
    description: req.body.description
  };

  try {
    const updatedHero = data.updateHero(hero);
    res.status(200).json(updatedHero);
  } catch (error) {
    res.status(500).send(error);
  }
}

// 👇 This was async function deleteHero(req: Request, res: Response) {
async function deleteHero({ req, res }: Context) {
  const { id } = req.params;

  try {
    data.deleteHero(id);
    res.status(200).json({});
  } catch (error) {
    res.status(500).send(error);
  }
}

export default { getHeroes, postHero, putHero, deleteHero };
</code></pre><figcaption>functions/services/hero.service.ts</figcaption></figure><!--kg-card-end: code--><p>There are four functions where request and response are parameters. One each for <code>getHeroes</code>, <code>postHero</code>, <code>putHero</code>, and <code>deleteHero</code>.</p><p>The parameters to every function in the Express app contain <code>req</code> and <code>res</code>. The Azure Functions app can still get to the request and response objects, but they are contained within a <code>context</code> object. We use destructuring to access them.</p><p>The <code>Context</code> object also contains other APIs, such as <code>log</code> (ex: <code>context.log('hello')</code>). This could be used in place of the common <code>console.log</code> you use in Node apps.</p><h4 id="refactor-the-route">Refactor the Route</h4><p>Now point your route to the service in your <strong>functions/heroes-get/index.ts</strong> file. Open that file and replace it with the following code.</p><!--kg-card-begin: code--><pre><code class="language-typescript">import { AzureFunction, Context, HttpRequest } from '@azure/functions';
import { heroService } from '../services';

const httpTrigger: AzureFunction = async function(context: Context, req: HttpRequest): Promise&lt;void&gt; {
  await heroService.getHeroes(context); // 👈 This calls the hero service
};

export default httpTrigger;
</code></pre><!--kg-card-end: code--><p>The code that you add calls the asynchronous function <code>heroService.getHeroes</code> and passes in the <code>context</code> which contain the request and response objects.</p><h3 id="create-the-remaining-functions">Create the Remaining Functions</h3><p>Remember, there are eight total endpoints in the Express app and we just created the first one. Now, follow these steps to create an Azure Function for the rest of the endpoints.</p><ol><li>Open the command palette by pressing <strong>F1</strong></li><li>Type and select <strong>Azure Functions: Create Function</strong></li><li>Choose <strong>HTTP Trigger</strong> for the type of function</li><li>Enter the name of the function for heroes and villains. I recommend <strong>heroes-get</strong>, <strong>heroes-post</strong>, <strong>heroes-put</strong>, <strong>heroes-delete</strong>, <strong>villains-get</strong>, <strong>villains-post</strong>, <strong>villains-put</strong>, <strong>villains-delete</strong>)</li><li>Select <strong>Anonymous</strong> for the authentication level</li><li>Open <em>function.json</em> and set the method to the appropriate value of get, post, put or delete.</li><li>In the bindings section, for the <strong>get</strong> and <strong>post</strong>, add a <code>route: "heroes"</code> (or villains as appropriate) entry.</li><li>In the bindings section, for the <strong>delete</strong> and <strong>put</strong>, add a <code>route: "heroes/{id}"</code> (or villains as appropriate) entry.</li><li>Add the code in each function's <em>index.ts</em> file to call the appropriate hero or villain service function.</li></ol><h3 id="looking-at-the-functions-app">Looking at the Functions App</h3><p>The Azure Functions app now has folders that map to their appropriate endpoints as shown below.</p><!--kg-card-begin: markdown--><table>
<thead>
<tr>
<th>method</th>
<th>route endpoint</th>
<th>folder</th>
</tr>
</thead>
<tbody>
<tr>
<td>GET</td>
<td>heroes</td>
<td>heroes-get</td>
</tr>
<tr>
<td>POST</td>
<td>heroes</td>
<td>heroes-post</td>
</tr>
<tr>
<td>PUT</td>
<td>heroes:id</td>
<td>heroes-put</td>
</tr>
<tr>
<td>DELETE</td>
<td>heroes/:id</td>
<td>heroes-delete</td>
</tr>
<tr>
<td>GET</td>
<td>villains</td>
<td>villains-get</td>
</tr>
<tr>
<td>POST</td>
<td>villains</td>
<td>villains-post</td>
</tr>
<tr>
<td>PUT</td>
<td>villains:id</td>
<td>villains-put</td>
</tr>
<tr>
<td>DELETE</td>
<td>villains/:id</td>
<td>villains-delete</td>
</tr>
</tbody>
</table>
<!--kg-card-end: markdown--><p>The structure of the Azure Function app contained in the <em>functions</em> folder should look like the following.</p><!--kg-card-begin: code--><pre><code class="language-text">functions
 | - heroes-delete
 | | - function.json
 | | - index.ts
 | - heroes-get
 | | - function.json  👈 The hero route's configuration
 | | - index.ts       👈 The hero routes
 | - heroes-post
 | | - function.json
 | | - index.ts
 | - heroes-put
 | | - function.json
 | | - index.ts
 | - services          👈 The same folder that the Express app has
 | | - data.ts         👈 The hero data (could be database API calls)
 | | - hero.service.ts 👈 The logic to get the hero data
 | | - index.ts
 | | - villain.service.ts
 | - villains-delete
 | | - function.json
 | | - index.ts
 | - villains-get
 | | - function.json
 | | - index.ts
 | - villains-post
 | | - function.json
 | | - index.ts
 | - villains-put
 | | - function.json
 | | - index.ts
 | - .funcignore
 | - .gitignore
 | - host.json
 | - local.settings.json
 | - package.json
 | - proxies.json
 | - tsconfig.json
</code></pre><!--kg-card-end: code--><h2 id="debug-node-express-and-angular">Debug Node Express and Angular</h2><p>Now it's time to run the app and see if it all works! We'll do this through the VS Code debugger.</p><p>Just to keep things separate, we'll make sure the Express app uses port <strong>7070</strong> and the Azure Functions app uses port <strong>7071</strong>. If we were truly removing the Express app (which we could absolutely do at this point) we could keep the same port. But for educational purposes, let's keep them both around</p><ol><li>Open <em>proxy.conf.json</em> and change the port to <strong>7071</strong> (our function app)</li><li>Open the VS Code Command Palette <strong>F1</strong></li><li>Type <strong>View: Show Debug</strong> and press <strong>ENTER</strong></li><li>Select <strong>Debug Functions and Angular</strong></li><li>Press <strong>F5</strong></li><li>Open the browser to <a href="http://localhost:7071">http://localhost:7071</a></li></ol><p>You may now set breakpoints in the Functions and Angular code.</p><!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://thepracticaldev.s3.amazonaws.com/i/2l27psjcsqyh8f2u32ls.jpg" class="kg-image" alt="Shifting Your Node Express APIs to Serverless"></figure><!--kg-card-end: image--><p>In case you missed it - the files <em>.vscode/launch.json</em> and <em>.vscode/tasks.json</em> are integral to the debugging experience for this project. I encourage you to explore those files and copy/refactor their contents for your own purposes.</p><h2 id="optional-remove-the-express-app">Optional - Remove the Express App</h2><p>At this point the Express app is no longer being used. Feel free to delete it (you can always re-clone the GitHub sample) or keep it around if you want to go back and froth between Express and Azure Functions.</p><h2 id="summary">Summary</h2><p>The end result is we have Angular and Azure Functions. Now we can think about servers less (get it, because we are using serverless?).</p><p>Node and Express have been incredibly powerful and oft used for serving API endpoints. Now with serverless you could shift your APIs and not worry about server setup or maintenance, possibly reduce cost of an always on server, and replace the Express server with Azure Functions service. And for your efforts, you get an API that scales well and lets you focus on the code, not the servers.</p><p>If you want to deploy the Azure Functions app to the cloud, you can <a href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurefunctions&amp;WT.mc_id=johnpapanet-blog-jopapa">deploy it by following this tutorial</a>. All you need is an <a href="https://azure.microsoft.com/en-us/free/?wt.mc_id=johnpapanet-blog-jopapa">Azure account</a> and then use the Azure Functions extension for Visual Studio Code to deploy it.</p><p>The complete solution for the <a href="https://github.com/johnpapa/express-to-functions">sample project is on GitHub here</a>. The instructions on how to get started are also in the README file. You can explore running the Express app or the Azure Functions app to get a sense of the differences. Then try to apply this same shift to your code.</p><h2 id="resources">Resources</h2><p>Here are a bunch of resources about the topics covered in this article.</p><ul><li><a href="https://azure.microsoft.com/en-us/free/?wt.mc_id=johnpapanet-blog-jopapa">Azure Free Trial</a></li></ul><h3 id="vs-code">VS Code</h3><ul><li><a href="https://code.visualstudio.com?wt.mc_id=johnpapanet-blog-jopapa">VS Code</a></li><li><a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-node-azure-pack&amp;WT.mc_id=johnpapanet-blog-jopapa">VS Code Extension for Node on Azure</a></li><li><a href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurefunctions&amp;WT.mc_id=johnpapanet-blog-jopapa">VS Code Extension for Azure Functions</a></li></ul><h3 id="azure-functions">Azure Functions</h3><ul><li>Azure Functions <a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local#local-settings-file?WT.mc_id=johnpapanet-blog-jopapa">local.settings.json</a> file</li><li>Tutorial to <a href="https://code.visualstudio.com/tutorials/functions-extension/getting-started?WT.mc_id=johnpapanet-blog-jopapa">Deploy to Azure Using Azure Functions</a></li><li>Article about <a href="https://azure.microsoft.com/en-us/blog/improving-the-typescript-support-in-azure-functions/?WT.mc_id=johnpapanet-blog-jopapa">Azure Functions TypeScript Support</a></li></ul><h3 id="debugging-resources">Debugging Resources</h3><ul><li><a href="https://code.visualstudio.com/docs/nodejs/angular-tutorial?wt.mc_id=johnpapanet-blog-jopapa">Debugging Angular in VS Code</a></li><li><a href="https://code.visualstudio.com/docs/nodejs/reactjs-tutorial?wt.mc_id=johnpapanet-blog-jopapa">Debugging React in VS Code</a></li><li><a href="https://code.visualstudio.com/docs/nodejs/vuejs-tutorial?wt.mc_id=johnpapanet-blog-jopapa">Debugging Vue in VS Code</a></li><li><a href="https://code.visualstudio.com/Docs/editor/tasks?wt.mc_id=johnpapanet-blog-jopapa">Tasks in VS Code</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Live Share Integration with Peacock]]></title><description><![CDATA[Peacock now has integration with the Live Share VS Code extension]]></description><link>https://johnpapa.net/live-share-integration-with-peacock/</link><guid isPermaLink="false">5cf540038be4a10037130fd4</guid><category><![CDATA[vscode]]></category><category><![CDATA[webdev]]></category><category><![CDATA[javascript]]></category><category><![CDATA[fun]]></category><dc:creator><![CDATA[John Papa]]></dc:creator><pubDate>Mon, 03 Jun 2019 15:45:13 GMT</pubDate><content:encoded><![CDATA[<p>One the of the coolest part of creating Open Source Software (OSS) is that ideas can be extended by any of us in the community to create even more valuable software! This past week I reviewed, collaborated, and merged some Pull Requests into Peacock that enable it to work with both VS Code's <a href="https://code.visualstudio.com/docs/remote/remote-overview?wt.mc_id=johnpapanet-blog-jopapa">Remote Development</a> and Live Share features!</p>
<p><img src="https://johnpapa.net/content/images/2019/06/peacock-live-share-demo.gif" alt="peacock-live-share-demo"></p>
<h2 id="liveshare">Live Share</h2>
<p><a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.vscode-peacock&amp;wt.mc_id=johnpapanet-blog-jopapa">Peacock</a> detects when the <a href="https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare&amp;wt.mc_id=johnpapanet-blog-jopapa">Live Share</a> extension is installed and automatically adds two commands that allow the user to change color of their Live Share sessions as a Host or a Guest, depending on their role.</p>
<blockquote>
<p>Live Share is a VS Code extension that adds collaboration capabilities to the editor. Using Live Share one can share their local files, terminals, local servers and debugging sessions with someone remote.</p>
</blockquote>
<p>The commands allow users to pick a color from the favorites that can be used during Live Share session.</p>
<table>
<thead>
<tr>
<th>Command</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>Peacock: Change Live Share Color (Host)</td>
<td>Prompts user to select a color for Live Share Host session from the Favorites</td>
</tr>
<tr>
<td>Peacock: Change Live Share Color (Guest)</td>
<td>Prompts user to select a color for Live Share Guest session from the Favorites</td>
</tr>
</tbody>
</table>
<p>When a <a href="https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare&amp;wt.mc_id=johnpapanet-blog-jopapa">Live Share</a> session is started, the selected workspace color will be applied. When the session is finished, the workspace color is reverted back to the previous one (if set).</p>
<ul>
<li>Learn more about <a href="https://code.visualstudio.com/blogs/2017/11/15/live-share?wt.mc_id=johnpapanet-blog-jopapa">Live Share here</a></li>
<li>Get the <a href="https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare&amp;wt.mc_id=johnpapanet-blog-jopapa">Live Share extension here</a></li>
<li>Get the <a href="https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare-pack&amp;wt.mc_id=johnpapanet-blog-jopapa">Live Share extension pack</a>, which now includes Peacock</li>
</ul>
<h2 id="remotedevelopment">Remote Development</h2>
<p>Peacock also now has support for the Remote Development feature of VS Code.</p>
<p>VS Code distinguishes two classes of extensions: UI Extensions and Workspace Extensions. Peacock is classified as a UI extension as it makes contributions to the VS Code user interface and is always run on the user's local machine. UI Extensions cannot directly access files in the workspace, or run scripts/tools installed in that workspace or on the machine. Example UI Extensions include: themes, snippets, language grammars, and keymaps.</p>
<p>In version 2.1.2 Peacock enabled integration with the Remote Development by adding <code>&quot;extensionKind&quot;: &quot;ui&quot;</code> in the extension's <code>package.json</code>.</p>
<ul>
<li>Learn more about <a href="https://code.visualstudio.com/blogs/2019/05/02/remote-development?wt.mc_id=johnpapanet-blog-jopapa">VS Code Remote Development</a></li>
<li>Get the <a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack&amp;wt.mc_id=johnpapanet-blog-jopapa">VS Code Remote Development Extensions</a></li>
</ul>
<h2 id="thanks">Thanks!</h2>
<p>Special thanks to both <a href="https://twitter.com/legomushroom">@legomushroom</a> and <a href="https://twitter.com/lostintangent">@lostintangent</a> for implementing the Live Share integration. Also to <a href="https://twitter.com/mattbierner">Matt Bierner</a> for implementing the Remote Development integration.</p>
]]></content:encoded></item><item><title><![CDATA[Predictive Preloading Strategy for Your Angular Bundles]]></title><description><![CDATA[Learn how to create your own custom Angular preload strategy to preload bundles before a user navigates to their route]]></description><link>https://johnpapa.net/predictive-preloading-of-your-angular-bundles/</link><guid isPermaLink="false">5cf0ded28f0ea500bff57283</guid><category><![CDATA[angular]]></category><category><![CDATA[webdev]]></category><category><![CDATA[typescript]]></category><category><![CDATA[javascript]]></category><dc:creator><![CDATA[John Papa]]></dc:creator><pubDate>Fri, 31 May 2019 08:01:13 GMT</pubDate><content:encoded><![CDATA[<p>Users want fast apps. Getting your JavaScript bundles to your browser as quickly as possible and before your user needs them can make a huge and positive impact on their user experience. Knowing how you can improve that experience is important.</p>
<p>One way you can improve user experience with your Angular apps is to strategically decide which bundles to preload. You control when your bundles load and which bundles load. This is why you should explore choosing a built-in or creating your own custom Angular preload strategy.</p>
<p>In this series we'll explore a few of your options for preloading Angular bundles.</p>
<p>Here are the articles in this series</p>
<ul>
<li><a href="https://dev.to/john_papa/preload-all-angular-bundles-1b6l">Preload all Angular Bundles</a></li>
<li><a href="https://dev.to/john_papa/you-pick-which-angular-bundles-to-preload-5l9">You Pick Which Angular Bundles to Preload</a></li>
<li><a href="https://dev.to/azure/preload-angular-bundles-when-good-network-connectivity-is-detected-j3a">Preload Angular Bundles When Good Network Connectivity is Detected</a></li>
<li><a href="https://dev.to/john_papa/predictive-preloading-strategy-for-your-angular-bundles-4bgl">Predictive Preloading Strategy for Your Angular Bundles</a></li>
</ul>
<h2 id="scoutingahead">Scouting Ahead</h2>
<p>The &quot;on demand&quot; strategy preloads one or more routes when a user performs a specific action. You decide which action will cause a route to preload. For example, you could set this up to preload a route while a user hovers over a button or menu item.</p>
<p>You can create the custom <code>OnDemandPreloadService</code> by creating a class that implements the <code>PreloadingStrategy</code> interface, and providing it in the root. Then you must implement the <code>preload</code> function and return the <code>load()</code> function when you want to tell Angular to preload the function.</p>
<p>Notice the <code>preload</code> function in the class <code>OnDemandPreloadService</code> examines the Observable <code>preloadOnDemand$</code>. It pipes the observable and uses the <code>mergeMap</code> RxJs operator to switch to a new Observable. This new Observable's value depends on the local <code>preloadCheck</code> function.</p>
<p>The <code>preloadCheck</code> function checks if the <code>preloadOptions</code> (which comes from the original Observable) has a <code>routePath</code> that matches a route that has the <code>data.preload</code> property set to <code>true</code>. So here we are opting some of the routes into preloading and leaving some routes to be loaded when they are requested explicitly.</p>
<pre><code class="language-typescript">@Injectable({ providedIn: 'root', deps: [OnDemandPreloadService] })
export class OnDemandPreloadStrategy implements PreloadingStrategy {
  private preloadOnDemand$: Observable&lt;OnDemandPreloadOptions&gt;;

  constructor(private preloadOnDemandService: OnDemandPreloadService) {
    this.preloadOnDemand$ = this.preloadOnDemandService.state;
  }

  preload(route: Route, load: () =&gt; Observable&lt;any&gt;): Observable&lt;any&gt; {
    return this.preloadOnDemand$.pipe(
      mergeMap(preloadOptions =&gt; {
        const shouldPreload = this.preloadCheck(route, preloadOptions);
        return shouldPreload ? load() : EMPTY;
      })
    );
  }

  private preloadCheck(route: Route, preloadOptions: OnDemandPreloadOptions) {
    return (
      route.data &amp;&amp;
      route.data['preload'] &amp;&amp;
      [route.path, '*'].includes(preloadOptions.routePath) &amp;&amp;
      preloadOptions.preload
    );
  }
}
</code></pre>
<h2 id="routedefinitions">Route Definitions</h2>
<p>This strategy requires that you indicate which routes can be preloaded. You can do this by adding the <code>data.preload</code> property and set it to <code>true</code> in your route definition, as shown below.</p>
<pre><code class="language-typescript">export const routes: Routes = [
  { path: '', pathMatch: 'full', redirectTo: 'heroes' },
  {
    path: 'dashboard',
    loadChildren: () =&gt;
      import('app/dashboard/dashboard.module').then(m =&gt; m.DashboardModule),
    data: { preload: true }
  },
  {
    path: 'heroes',
    loadChildren: () =&gt;
      import('app/heroes/heroes.module').then(m =&gt; m.HeroesModule),
    data: { preload: true }
  },
  {
    path: 'villains',
    loadChildren: () =&gt;
      import('app/villains/villains.module').then(m =&gt; m.VillainsModule)
  },
  { path: '**', pathMatch: 'full', component: PageNotFoundComponent }
];
</code></pre>
<p>Notice that the dashboard and heroes routes both have the <code>preload.data</code> property set to <code>true</code>. However, the villains route does not have this property set. In this scenario the heroes and dashboard have preloading enabled, but the villains would only load when the user navigates to this route.</p>
<h2 id="settingthecustomondemandpreloadservice">Setting the Custom OnDemandPreloadService</h2>
<p>Then when setting up your <code>RouterModule</code>, pass the router options including the <code>preloadingStrategy</code> to the <code>forRoot()</code> function.</p>
<pre><code class="language-typescript">@NgModule({
  imports: [
    RouterModule.forRoot(routes, {
      preloadingStrategy: OnDemandPreloadService
    })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {}
</code></pre>
<h2 id="decidingwhentopreload">Deciding When to Preload</h2>
<p>The missing piece here is the mechanism that you use to tell the app which route to preload and when to preload it. Notice the service <code>OnDemandPreloadService</code> in the code below. You can call this service's <code>startPreload</code> function and pass the route you wish to preload. The <code>OnDemandPreloadService</code> service then next's the subject (think of this like publishing or emitting a message). Then whoever or whatever listens to that message can act on it.</p>
<p>This is where the <code>OnDemandPreloadStrategy</code> strategy comes in, as it is listening.</p>
<pre><code class="language-typescript">export class OnDemandPreloadOptions {
  constructor(public routePath: string, public preload = true) {}
}

@Injectable({ providedIn: 'root' })
export class OnDemandPreloadService {
  private subject = new Subject&lt;OnDemandPreloadOptions&gt;();
  state = this.subject.asObservable();

  startPreload(routePath: string) {
    const message = new OnDemandPreloadOptions(routePath, true);
    this.subject.next(message);
  }
}
</code></pre>
<h2 id="bindtoamouseoverevent">Bind to a Mouseover Event</h2>
<p>Now your app is ready to preload a route when you decide to do it. You can try this by binding a DOM event such as <code>mouseover</code> and firing the <code>OnDemandPreloadService</code>'s <code>startPreload</code> function.</p>
<pre><code class="language-html">&lt;a
  [routerLink]=&quot;item.link&quot;
  class=&quot;nav-link&quot;
  (mouseover)=&quot;preloadBundle('heroes')&quot;
  &gt;heroes&lt;/a
&gt;
</code></pre>
<p>Notice the following code accepts the route path and passes it along to the <code>preloadOnDemandService.startPreload</code> function.</p>
<pre><code class="language-typescript">preloadBundle(routePath) {
  this.preloadOnDemandService.startPreload(routePath);
}
</code></pre>
<h2 id="alltogether">All Together</h2>
<p>Let's step back and follow how this all works.</p>
<ol>
<li>A user hovers over your anchor tag</li>
<li>The <code>mouseover</code> binding calls a function in your component, passing the route path ('heroes' in this case)</li>
<li>That code calls the <code>PreloadOnDemandService</code> service's <code>startPreload</code>, passing the route path to it</li>
<li>The <code>PreloadOnDemandService</code> service next's the RxJS Subject, which is exposed as an Observable</li>
<li>The <code>OnDemandPreloadStrategy</code> gets a handle on that Observable, and it knows when it &quot;nexts&quot;</li>
<li>The <code>OnDemandPreloadStrategy</code> pipes it into <code>mergeMap</code> and evaluates the route for preloading</li>
<li>If it decides to preload, the <code>OnDemandPreloadStrategy</code> returns a new Observable with the <code>load()</code> function</li>
<li>If it decides not to preload, the <code>OnDemandPreloadStrategy</code> returns an Observable with the <code>EMPTY</code> observable (which does not preload)</li>
<li>The Angular router listens to the response of the strategy's <code>preload</code> function and either preloads or not, accordingly.</li>
</ol>
<h2 id="tryit">Try It</h2>
<p>After applying this strategy, rebuild and run your app with <code>ng serve</code>. Open your browser, open your developer tools, and go to <code>http://localhost:4200</code>. When you inspect the Network tab in your browser you will likely see none of your bundles already preloaded (except whichever route your navigated to by default, if that was lazy loaded).</p>
<p>Then hover over the HTML element where it fires with the <code>mouseover</code> event you bound. Check your network tab in your browser and you will see the bundle will be preloaded.</p>
<h2 id="decidingwhatisrightforyourapp">Deciding What Is Right For Your App</h2>
<p>Now that you know how to create your own preload strategy such as <code>OnDemandPreloadService</code>, how do you evaluate if this is the right strategy for your app?</p>
<p>This is a more involved strategy for certain. Could it be beneficial to your users? Do your users often hover over search results before selecting them? Would that normally fire off a lazy loaded bundle? If so, perhaps this could give that preload a jumpstart.</p>
<p>If you can determine that your users' behavior and workflow often follows a specific path before loading a new bundle, then this strategy could be beneficial.</p>
<p>You can apply this to a number of scenarios such as hovering over an HTML element, clicking a button, or scrolling to a specific area of the screen.</p>
<p>In the end the decision is up to you. I recommend before choosing this options, or any preload strategy, that you test at various network speeds under various valid and common user workflows. This data will help you decide if this is the right strategy for you, or if another may be more beneficial for users of your app.</p>
<h2 id="resources">Resources</h2>
<ul>
<li>Get <a href="https://code.visualstudio.com/?wt.mc_id=johnpapanet-blog-jopapa">VS Code</a></li>
<li>Get the VS Code <a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.angular-essentials&amp;wt.mc_id=johnpapanet-blog-jopapa">Angular Essentials</a></li>
<li>Get the VS Code <a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.angular2&amp;wt.mc_id=johnpapanet-blog-jopapa">Angular Snippets</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Preload Angular Bundles When Good Network Connectivity is Detected]]></title><description><![CDATA[Learn how to create your own custom Angular preload strategy to preload bundles in advance when network connectivity is good]]></description><link>https://johnpapa.net/preload-angular-bundles-when-good-network-connectivity-is-detected/</link><guid isPermaLink="false">5cf0dc788f0ea500bff5727d</guid><category><![CDATA[angular]]></category><category><![CDATA[webdev]]></category><category><![CDATA[typescript]]></category><category><![CDATA[javascript]]></category><dc:creator><![CDATA[John Papa]]></dc:creator><pubDate>Fri, 31 May 2019 07:50:16 GMT</pubDate><content:encoded><![CDATA[<p>Users want fast apps. Getting your JavaScript bundles to your browser as quickly as possible and before your user needs them can make a huge and positive impact on their user experience. Knowing how you can improve that experience is important.</p>
<p>One way you can improve user experience with your Angular apps is to strategically decide which bundles to preload. You control when your bundles load and which bundles load. This is why you should explore choosing a built-in or creating your own custom Angular preload strategy.</p>
<p>In this series we'll explore a few of your options for preloading Angular bundles.</p>
<p>Here are the articles in this series</p>
<ul>
<li><a href="https://dev.to/john_papa/preload-all-angular-bundles-1b6l">Preload all Angular Bundles</a></li>
<li><a href="https://dev.to/john_papa/you-pick-which-angular-bundles-to-preload-5l9">You Pick Which Angular Bundles to Preload</a></li>
<li><a href="https://dev.to/azure/preload-angular-bundles-when-good-network-connectivity-is-detected-j3a">Preload Angular Bundles When Good Network Connectivity is Detected</a></li>
<li><a href="https://dev.to/john_papa/predictive-preloading-strategy-for-your-angular-bundles-4bgl">Predictive Preloading Strategy for Your Angular Bundles</a></li>
</ul>
<blockquote>
<p>Check out <a href="https://dev.to/lacolaco/network-aware-preloading-strategy-for-angular-lazy-loading-4hae">Suguru Inatomi's post here for a similar network-aware preloading strategy</a></p>
</blockquote>
<h2 id="checkingforagoodconnection">Checking for a Good Connection</h2>
<p>The &quot;network aware&quot; strategy uses the browser's <a href="https://developer.mozilla.org/en-US/docs/Web/API/Navigator/connection">Network Information API</a> to detect the connection and speed. If the speed qualifies as good, then it preloads the bundles. If not, it leaves them alone.</p>
<blockquote>
<p>You can check browser compatibility for the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Navigator/connection#Browser_compatibility">Network Information API here</a>.</p>
</blockquote>
<p>You can create the custom <code>NetworkAwarePreloadStrategy</code> by creating a class that implements the <code>PreloadingStrategy</code> interface, and providing it in the root. Then you must implement the <code>preload</code> function and return the <code>load()</code> function when you want to tell Angular to preload the function.</p>
<p>Notice the <code>preload</code> function in the class <code>NetworkAwarePreloadStrategy</code> checks the <code>navigator.connection</code> object's <code>saveData</code> property first. Some mobile devices have a setting for &quot;data saver&quot;. When this is enabled, this property will be <code>true</code>. Therefore, if the user has decided to save their data, they did so by choice and we should not be preloading bundles (which consumes data).</p>
<p>Next the code checks if the connection's <code>effectiveType</code> is one of the connection speeds that you feel are too slow to then preload the bundles. The code below decides that 2g and slow-2g don;t qualify for preloading, but 3g and better do. Therefore, as long as the <code>saveData</code> is true and the connection speed is 3g or better, the bundle will be preloaded.</p>
<pre><code class="language-typescript">export declare var navigator;

@Injectable({ providedIn: 'root' })
export class NetworkAwarePreloadStrategy implements PreloadingStrategy {
  preload(route: Route, load: () =&gt; Observable&lt;any&gt;): Observable&lt;any&gt; {
    return this.hasGoodConnection() ? load() : EMPTY;
  }

  hasGoodConnection(): boolean {
    const conn = navigator.connection;
    if (conn) {
      if (conn.saveData) {
        return false; // save data mode is enabled, so dont preload
      }
      const avoidTheseConnections = ['slow-2g', '2g' /* , '3g', '4g' */];
      const effectiveType = conn.effectiveType || '';
      console.log(effectiveType);
      if (avoidTheseConnections.includes(effectiveType)) {
        return false;
      }
    }
    return true;
  }
}
</code></pre>
<h2 id="settingthecustomnetworkawarepreloadstrategy">Setting the Custom NetworkAwarePreloadStrategy</h2>
<p>Then when setting up your <code>RouterModule</code>, pass the router options including the <code>preloadingStrategy</code> to the <code>forRoot()</code> function.</p>
<pre><code class="language-typescript">@NgModule({
  imports: [
    RouterModule.forRoot(routes, {
      preloadingStrategy: NetworkAwarePreloadStrategy
    })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {}
</code></pre>
<h2 id="tryit">Try It</h2>
<p>After applying this strategy, rebuild and run your app with <code>ng serve</code>. Open your browser, open your developer tools, and go to <code>http://localhost:4200</code>. When you inspect the Network tab in your browser you will likely see all of your bundles already preloaded.</p>
<p>Then toggle your throttling to 2g speeds in your browser, then refresh the page. Then the routes will no longer be preloaded.</p>
<h2 id="decidingwhatisrightforyourapp">Deciding What Is Right For Your App</h2>
<p>Now that you know how to create your own preload strategy such as <code>NetworkAwarePreloadStrategy</code>, how do you evaluate if this is the right strategy for your app?</p>
<p>If mobile and low bandwidth / low WiFi scenarios are likely for your users, this could be a beneficial preload strategy. You could talk to your business users (the stakeholders in your app) to discover this, if you are not sure.</p>
<p>You could also combine this strategy with one of the other custom strategies.</p>
<p>In the end the decision is up to you. I recommend before choosing this options, or any preload strategy, that you test at various network speeds under various valid and common user workflows. This data will help you decide if this is the right strategy for you, or if another may be more beneficial for users of your app.</p>
<h2 id="resources">Resources</h2>
<ul>
<li>Get <a href="https://code.visualstudio.com/?wt.mc_id=johnpapanet-blog-jopapa">VS Code</a></li>
<li>Get the VS Code <a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.angular-essentials&amp;wt.mc_id=johnpapanet-blog-jopapa">Angular Essentials</a></li>
<li>Get the VS Code <a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.angular2&amp;wt.mc_id=johnpapanet-blog-jopapa">Angular Snippets</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[You Pick Which Angular Bundles to Preload]]></title><description><![CDATA[Learn how to create your own custom Angular preload strategy to choose which bundles to load in advance]]></description><link>https://johnpapa.net/you-pick-which-angular-bundles-to-preload/</link><guid isPermaLink="false">5ceefe498f0ea500bff57275</guid><category><![CDATA[angular]]></category><category><![CDATA[webdev]]></category><category><![CDATA[typescript]]></category><category><![CDATA[javascript]]></category><dc:creator><![CDATA[John Papa]]></dc:creator><pubDate>Wed, 29 May 2019 21:49:45 GMT</pubDate><content:encoded><![CDATA[<p>Users want fast apps. Getting your JavaScript bundles to your browser as quickly as possible and before your user needs them can make a huge and positive impact on their user experience. Knowing how you can improve that experience is important.</p>
<p>One way you can improve user experience with your Angular apps is to strategically decide which bundles to preload. You control when your bundles load and which bundles load. This is why you should explore choosing a built-in or creating your own custom Angular preload strategy.</p>
<p>In this series we'll explore a few of your options for preloading Angular bundles.</p>
<p>Here are the other articles in this series</p>
<ul>
<li><a href="https://dev.to/john_papa/preload-all-angular-bundles-1b6l">Preload all Angular Bundles</a></li>
<li><a href="https://dev.to/john_papa/you-pick-which-angular-bundles-to-preload-5l9">You Pick Which Angular Bundles to Preload</a></li>
<li><a href="https://dev.to/azure/preload-angular-bundles-when-good-network-connectivity-is-detected-j3a">Preload Angular Bundles When Good Network Connectivity is Detected</a></li>
<li><a href="https://dev.to/john_papa/predictive-preloading-strategy-for-your-angular-bundles-4bgl">Predictive Preloading Strategy for Your Angular Bundles</a></li>
</ul>
<h2 id="optingin">Opting in</h2>
<p>The &quot;opt in&quot; strategy is like a buffet. You pick what you want to preload, and leave the rest to load as needed.</p>
<p>Creating custom preload strategies is a great way to control the manner in which the bundles preload. The custom <code>OptInPreloadStrategy</code> preload strategy let's you indicate which lazy loaded bundles should be preloaded.</p>
<p>You can do this by creating a new class that implements that <code>PreloadingStrategy</code> interface, and providing it in the root. Then you must implement the <code>preload</code> function and return the <code>load()</code> function when you want to tell Angular to preload the function.</p>
<p>Notice the <code>preload</code> function in the class <code>OptInPreloadStrategy</code> checks the route definition for a <code>data</code> property that contains a <code>preload</code> property. If that <code>data.preload</code> property exists and is a truthy value, then the <code>load()</code> function will be returned. When the <code>load()</code> function is returned, the router listens to this Observable and will make the network call to load the route's bundle.</p>
<pre><code class="language-typescript">import { Injectable } from '@angular/core';
import { PreloadingStrategy, Route } from '@angular/router';
import { Observable, EMPTY } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class OptInPreloadStrategy implements PreloadingStrategy {
  preload(route: Route, load: () =&gt; Observable&lt;any&gt;): Observable&lt;any&gt; {
    return route.data &amp;&amp; route.data['preload'] ? load() : EMPTY;
  }
}
</code></pre>
<h2 id="routedefinitions">Route Definitions</h2>
<p>This strategy requires that you indicate which routes should be preloaded. You can do this by adding the <code>data.preload</code> property and set it to <code>true</code> in your route definition, as shown below.</p>
<pre><code class="language-typescript">export const routes: Routes = [
  { path: '', pathMatch: 'full', redirectTo: 'heroes' },
  {
    path: 'dashboard',
    loadChildren: () =&gt;
      import('app/dashboard/dashboard.module').then(m =&gt; m.DashboardModule),
    data: { preload: true }
  },
  {
    path: 'heroes',
    loadChildren: () =&gt;
      import('app/heroes/heroes.module').then(m =&gt; m.HeroesModule),
    data: { preload: true }
  },
  {
    path: 'villains',
    loadChildren: () =&gt;
      import('app/villains/villains.module').then(m =&gt; m.VillainsModule)
  },
  { path: '**', pathMatch: 'full', component: PageNotFoundComponent }
];
</code></pre>
<p>Notice that the dashboard and heroes routes both have the <code>preload.data</code> property set to <code>true</code>. However, the villains route does not have this property set. In this scenario the heroes and dashboard would preload, but the villains would only load when the user navigates to this route.</p>
<h2 id="settingthecustomoptinpreloadstrategy">Setting the Custom OptInPreloadStrategy</h2>
<p>Then when setting up your <code>RouterModule</code>, pass the router options including the <code>preloadingStrategy</code> to the <code>forRoot()</code> function.</p>
<pre><code class="language-typescript">@NgModule({
  imports: [
    RouterModule.forRoot(routes, { preloadingStrategy: OptInPreloadStrategy })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {}
</code></pre>
<h2 id="tryit">Try It</h2>
<p>After applying this strategy and setting some of the route definition's routes <code>data.preload = true</code>, rebuild and run your app with <code>ng serve</code>. Open your browser, open your developer tools, and go to <code>http://localhost:4200</code>. When you inspect the Network tab in your browser you will see all of your bundles already preloaded.</p>
<p>Notice that the dashboard and heroes are already preloaded, but villains are not. If you wish to really see this make a difference, enable throttling in your developer tools to a slower connection such as 3G, then refresh the page. The preloading will be much more visible now in the Network tab.</p>
<h2 id="decidingwhatisrightforyourapp">Deciding What Is Right For Your App</h2>
<p>Now that you know how to create your own preload strategy such as <code>OptInPreloadStrategy</code>, how do you evaluate if this is the right strategy for your app?</p>
<p>It might make sense to consider which bundles would help improve your users' experience by being preloaded first. You could talk to your business users (the stakeholders in your app) and discover what they feel are the most frequented areas of your app. You could use analytics from existing apps or perform user studies to determine this, as well.</p>
<p>In the end the decision is up to you. I recommend before choosing this options, or any preload strategy, that you test at various network speeds under various valid and common user workflows. This data will help you decide if this is the right strategy for you, or if another may be more beneficial for users of your app.</p>
<h2 id="resources">Resources</h2>
<ul>
<li>Get <a href="https://code.visualstudio.com/?wt.mc_id=johnpapanet-blog-jopapa">VS Code</a></li>
<li>Get the VS Code <a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.angular-essentials&amp;wt.mc_id=johnpapanet-blog-jopapa">Angular Essentials</a></li>
<li>Get the VS Code <a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.angular2&amp;wt.mc_id=johnpapanet-blog-jopapa">Angular Snippets</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Preload All Angular Bundles]]></title><description><![CDATA[Learn how to use the built-in Angular preload strategy to preload all lazy loaded bundles in advance
]]></description><link>https://johnpapa.net/preload-all-angular-bundles/</link><guid isPermaLink="false">5ceef9da8f0ea500bff5726f</guid><category><![CDATA[angular]]></category><category><![CDATA[webdev]]></category><category><![CDATA[typescript]]></category><category><![CDATA[javascript]]></category><dc:creator><![CDATA[John Papa]]></dc:creator><pubDate>Wed, 29 May 2019 21:31:14 GMT</pubDate><content:encoded><![CDATA[<p>Users want fast apps. Getting your JavaScript bundles to your browser as quickly as possible and before your user needs them can make a huge and positive impact on their user experience. Knowing how you can improve that experience is important.</p>
<p>One way you can improve user experience with your Angular apps is to strategically decide which bundles to preload. You control when your bundles load and which bundles load. This is why you should explore choosing a built-in or creating your own custom Angular preload strategy.</p>
<p>In this series we'll explore a few of your options for preloading Angular bundles.</p>
<p>Here are the other articles in this series</p>
<ul>
<li><a href="https://dev.to/john_papa/preload-all-angular-bundles-1b6l">Preload all Angular Bundles</a></li>
<li><a href="https://dev.to/john_papa/you-pick-which-angular-bundles-to-preload-5l9">You Pick Which Angular Bundles to Preload</a></li>
<li><a href="https://dev.to/azure/preload-angular-bundles-when-good-network-connectivity-is-detected-j3a">Preload Angular Bundles When Good Network Connectivity is Detected</a></li>
<li><a href="https://dev.to/john_papa/predictive-preloading-strategy-for-your-angular-bundles-4bgl">Predictive Preloading Strategy for Your Angular Bundles</a></li>
</ul>
<h2 id="preloadall">Preload All</h2>
<p>Out of the box Angular's default preload strategy is to not preload. So if you want to preload you must change that behavior.</p>
<p>You can tell Angular to preload all of the lazy loaded modules in advance by using the built-in preload strategy <code>PreloadAllModules</code>. Simply import this from <code>@angular/router</code> as shown below.</p>
<pre><code class="language-typescript">import { RouterModule, Routes, PreloadAllModules } from '@angular/router';
</code></pre>
<p>Then when setting up your <code>RouterModule</code>, pass the router options including the <code>preloadingStrategy</code> to the <code>forRoot()</code> function.</p>
<pre><code class="language-typescript">@NgModule({
  imports: [
    RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {}
</code></pre>
<h2 id="tryit">Try It</h2>
<p>Now rebuild and run your app with <code>ng serve</code>. Open your browser, open your developer tools, and go to <code>http://localhost:4200</code>. When you inspect the Network tab in your browser you will see all of your bundles already preloaded.</p>
<p>Now when you navigate to your lazy loaded bundles you will see that they are already loaded, so the experience is fast. If you wish to really see this make a difference, enable throttling in your developer tools to a slower connection such as 3G, then refresh the page. The preloading will be much more visible now in the Network tab.</p>
<h2 id="decidingwhatisrightforyourapp">Deciding What Is Right For Your App</h2>
<p>Now that you know how to use the built-in <code>PreloadAllModules</code> strategy, how do you evaluate if this is the right strategy for your app? Well, this depends on your situation.</p>
<p>If your app has several bundles from lazy loading and all are large, these will all start transferring to your browse as your app loads. You don't control which ones load first, so if a user clicks on a route chances are that it won't be the first one preloaded.</p>
<p>What if your users rarely ever go to some of these routes? Does it make sense to preload them all up front?</p>
<p>If you feel the users could benefit from the routes all loading up front, this may be a good choice.</p>
<p>In the end the decision is up to you. I recommend before choosing this options, or any preload strategy, that you test at various network speeds under various valid and common user workflows. This data will help you decide if this is the right strategy for you, or if another may be more beneficial for users of your app.</p>
<h2 id="resources">Resources</h2>
<ul>
<li>Get <a href="https://code.visualstudio.com/?wt.mc_id=johnpapanet-blog-jopapa">VS Code</a></li>
<li>Get the VS Code <a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.angular-essentials&amp;wt.mc_id=johnpapanet-blog-jopapa">Angular Essentials</a></li>
<li>Get the VS Code <a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.angular2&amp;wt.mc_id=johnpapanet-blog-jopapa">Angular Snippets</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[When npm tells you you're hosed]]></title><description><![CDATA[One way to try to recover from npm errors]]></description><link>https://johnpapa.net/npmwipe/</link><guid isPermaLink="false">5cbe12fb8f0ea500bff57256</guid><category><![CDATA[npm]]></category><category><![CDATA[node]]></category><category><![CDATA[javascript]]></category><category><![CDATA[webdev]]></category><dc:creator><![CDATA[John Papa]]></dc:creator><pubDate>Mon, 22 Apr 2019 19:17:06 GMT</pubDate><content:encoded><![CDATA[<p>There may be a problem with a package you are using, not npm itself. Sigh. Deep breath. Grunt. Okay - time to wipe the <code>node_modules</code> and start again.</p>
<p><img src="https://johnpapa.net/content/images/2019/04/npm-node-errors-1.jpg" alt="npm-node-errors-1"></p>
<p>Reasons aside, for now, there are a few commands I seem to run almost daily to try to recover from errors. <a href="https://twitter.com/kvlly">Kelly Vaughn</a> got me thinking this morning about this from <a href="https://twitter.com/kvlly/status/1120320939303014402">her post on Twitter</a></p>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">if at first you don&#39;t succeed, try `rm -rf node_modules &amp;&amp; npm install`</p>&mdash; Kelly Vaughn 🐞 (@kvlly) <a href="https://twitter.com/kvlly/status/1120320939303014402?ref_src=twsrc%5Etfw">April 22, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>There are a few contributing factors to me running into issues with npm packages.</p>
<ol>
<li>I manage a lot of code, including some just infrequent enough where the packages get stale.</li>
<li>I work in coffee shops and poor WiFi areas quite often</li>
<li>Murphy's Law surrounds me</li>
</ol>
<p>So what do I do when I see one of the issues with my npm packages? Especially the ones that claim there may be something wrong with one of the packages and not npm itself? I clear the <code>node_modules</code> folder and try again.</p>
<pre><code class="language-bash">rm -rf node_modules package-lock.json
npm install
</code></pre>
<p>And to do it with flair, I created a bash alias to run these commands.</p>
<pre><code class="language-bash">npm-wipe
npm i
</code></pre>
<p>Why run it in two commands? Mostly because I like to see that the first one completed then go run <code>npm install</code> manually. I have no good reason. You may prefer to run it all at once.</p>
<h2 id="bashalias">Bash Alias</h2>
<p>Here is how I set up my bash alias on my macOS.</p>
<pre><code class="language-bash">alias npm-wipe=&quot;rm -rf node_modules package-lock.json&quot;
</code></pre>
<p>Hope this helps you out of a bind once in a while, too!</p>
]]></content:encoded></item><item><title><![CDATA[The Pitch of Your Voice: Some tips to consider to make your story more engaging]]></title><description><![CDATA[Learn how to own the pitch your voice in your presentation to maintain audience engagement]]></description><link>https://johnpapa.net/voice-pitch/</link><guid isPermaLink="false">5cb77c718f0ea500bff5724e</guid><category><![CDATA[devrel]]></category><category><![CDATA[career]]></category><category><![CDATA[discuss]]></category><dc:creator><![CDATA[John Papa]]></dc:creator><pubDate>Wed, 17 Apr 2019 19:23:02 GMT</pubDate><content:encoded><![CDATA[<blockquote>
<p>Are you a storyteller on stage? Do you want to engage and inspire your audience comfortably and naturally? The great news is that you have one of the essential tools to accomplish this already! Let's explore how you can adjust your voice to tell your stories in a more impactful way.</p>
</blockquote>
<h2 id="pitch">Pitch</h2>
<p>Have you ever watched a presentation where the speaker seemed to grab your attention with the tone the used to pronounce specific phrases? Let me jog your memory in case you can't recall. Do you remember any of these lines from famous movies?</p>
<blockquote>
<p>&quot;You shall not pass!&quot; - Fellowship of the Ring, 2000</p>
</blockquote>
<blockquote>
<p>“I'll get you, my pretty, and your little dog, too!” The Wizard of Oz, 1939</p>
</blockquote>
<blockquote>
<p>“You can't handle the truth!” A Few Good Men, 1992</p>
</blockquote>
<blockquote>
<p>“Here's Johnny!” The Shining, 1980</p>
</blockquote>
<blockquote>
<p>“My precious.” The Lord of the Rings: Two Towers, 2002</p>
</blockquote>
<p>These are all from some great movies! Each of these stands out for various reasons. But one of the keys we should focus on is the pitch of the actor/actress's voice. I bet as you read them you could hear the actor/actress's voice in your head. Now trying saying these yourself without using any of their vocal changes.</p>
<p>Did you notice that each of these quotes were said with varying degrees of a high and low vocal pitch? Some were softer, some louder. Some were faster, some slower. Some were deeper and some higher pitched. The changes in pitch (we'll focus there for now) can help grab attention mainly when used sparingly at critical moments in the delivery of your story.</p>
<h3 id="whatispitch">What is Pitch?</h3>
<p>Pitch is the highness or lowness of your voice. It can be a handy tool for you when presenting.</p>
<h3 id="pitchnotvolume">Pitch, Not Volume</h3>
<p>We'll talk more about volume in a future post. These two topics can overlap a little, but the best way to think about these is that the pitch is the deep or high voice you use. And you can still adjust the volume independently of the pitch.</p>
<h2 id="trythisexercise">Try this Exercise</h2>
<p>Let's start with an exercise you can try right now. Let's take the phrase &quot;Winter is Coming&quot; (yes, I am a Game of Thrones fan). Try saying this phrase first with a high pitch, then a typical pitch of your voice, then with a deeper pitch. Notice how they sound different.</p>
<p>The odds are that some of these may sound natural and compelling while others may sound awkward. That's understandable. Pitch isn't a tool that should be wielded lightly. When it works, it works great. But it should be used with purpose and sparingly to capture attention.</p>
<p>Now say this phrase in a high pitched voice. It just doesn't work for the story. Does it grab attention? Very likely it would. But it may catch the wrong kind of attention by causing confusion for the audience as they think &quot;why is the actor saying it like that?&quot;</p>
<p>Proper use of pitch adds to the story. Using a low and deep pitch throughout, and slowly (note the speed can play into this too), gives some sense of aw to the phrase.</p>
<h2 id="anotherpitchexercise">Another Pitch Exercise</h2>
<p>What is your baseline for your pitch? Let's find out. We'll pick a simple word like &quot;yes&quot; and repeat it till you find your comfortable, typical, baseline pitch.</p>
<p>Now say &quot;yes&quot; at your baseline pitch and then raise it a step higher. Continue going step by step higher to get a feel for your comfort range. Then take a few steps down in your pitch to find your deeper pitch for &quot;yes&quot;.</p>
<p>The key here is to use varying pitches that are comfortable and natural for you. If you don't like the way they sound, odds are others will not either. So find the pitches that work for you and are not forced.</p>
<h3 id="whereisthisuseful">Where is this useful?</h3>
<p>Changing your pitch can make the difference in your story being followed and remembered, vs. quickly forgotten.</p>
<p>Let's start with some boundaries and guidelines for pitch. Pitch isn't something I recommend changing too often in your presentation. Otherwise, you risk sounding a bit off, and you lose the value of the infrequent pitch change to grab attention.</p>
<p>Changing pitch can help grab attention most especially when used within a part of your story where the pitch is one way, and then you adjust the pitch suddenly. Here are some examples of changing pitch:</p>
<h3 id="questions">Questions</h3>
<p>During your story you pause, move forward and bend a little and speak into the mic &quot;Has this ever happened to you?&quot;</p>
<p>If you were talking in a high pitch before this, try using a deeper tone of your voice for the question. Or, use a higher pitch for the question if you were speaking more deeply prior to it. This gives a chance to your audience to re-focus on you and your voice.</p>
<p>Note that using a higher pitch at the end of sentences is similar to the tone used when asking a question.</p>
<h3 id="exclamations">Exclamations</h3>
<p>Your story may have &quot;aha&quot; moments. In these, a high pitch can emphasize the moment. For example, imagine you are telling a story that suddenly changes the narrative to show the audience that a great secret is revealed. You could stop and exclaim in a higher pitch &quot;Woah? What just happened here?&quot;. Or you could use a deeper pitch for the same phrase. Depending on the context of your story and what pitch pattern you had been speaking in, going deeper or higher can help grab the audience.</p>
<h3 id="avoidthesleepers">Avoid the Sleepers</h3>
<p>When we speak in the same pitch and tone and pace and volume, it is natural for humans to tune out from your presentation. You don't want heads to nod off - and yes, I had this happen to me when I presented. Some people can't stay awake. Changing any one of these can help and changing more than one can help even more!</p>
<p>We hear the term &quot;monotone&quot; often when referring to the same pitch of a voice for a period of time. By changing the pitch at a critical moment in your talk, you can avoid this and be sure to grab (or re-grab) attention</p>
<h2 id="partingtipsonpitch">Parting Tips on Pitch</h2>
<p>Here are quick tips for using the pitch of your voice.</p>
<ul>
<li>Discover your typical and most often used pitch. Then find small variances you can comfortably use.</li>
<li>Try using a high pitch for asking questions to your audience.</li>
<li>Use a deeper pitch when you want to convey more authority at a point in your story.</li>
</ul>
<p>Finally, observe the audience when you vary your pitch. Make mental notes of their reactions and make adjustments for the next time you present.</p>
<h2 id="whatsinthisseries">What's in This Series?</h2>
<p>Here are the other topics in this series, in no particular order. I'll update these links as I publish them.</p>
<p>1 - <a href="https://dev.to/azure/use-your-voice-effectively-for-impactful-presentations-4128">Using Your Voice</a><br>
2 - <a href="https://dev.to/john_papa/speed-of-voice-the-pace-of-your-presentation-can-make-heavily-impact-how-well-it-lands">Pace of your voice</a><br>
3 - Pitch of your voice<br>
4 - Volume of your voice<br>
5 - Emphasis of words in your speech<br>
6 - Clarity of your speech</p>
<p>Good luck with your next presentation!</p>
]]></content:encoded></item><item><title><![CDATA[Show the Time to Read Your Markdown in VS Code]]></title><description><![CDATA[Check how long your written content will take for someone to read it]]></description><link>https://johnpapa.net/show-the-time-to-read-your-markdown-in-vs-code/</link><guid isPermaLink="false">5cabb8538f0ea500bff57242</guid><category><![CDATA[devrel]]></category><category><![CDATA[vscode]]></category><category><![CDATA[markdown]]></category><dc:creator><![CDATA[John Papa]]></dc:creator><pubDate>Mon, 08 Apr 2019 21:14:37 GMT</pubDate><content:encoded><![CDATA[<h2 id="readtime">Read Time</h2>
<p>Recently I posted <a href="https://dev.to/azure/how-i-write-online-articles-1lfb">How I Write Online Articles</a>. Since then I have been working on a few ideas for making this easier. Today I'm announcing a preview version of a new VS Code extension called <a href="https://marketplace.visualstudio.com/itemdetails?itemName=johnpapa.read-time&amp;wt.mc_id=johnpapanet-blog-jopapa">Read Time</a></p>
<blockquote>
<p>You can get <a href="https://marketplace.visualstudio.com/itemdetails?itemName=johnpapa.read-time&amp;wt.mc_id=johnpapanet-blog-jopapa">Read Time here from the VS Code Marketplace</a></p>
</blockquote>
<p>Read Time is a Visual Studio Code extension that is ideal for writers who want an estimate how for long it may take to read your markdown.</p>
<p>When writing markdown you will see a book icon and a number in your VS Code status bar. The number will update as you add or remove text in your markdown file. When you are not in a markdown file, it will disappear. It's that simple.</p>
<p><img src="https://johnpapa.net/content/images/2019/04/read-time-ex.jpg" alt="read-time-ex"></p>
<h2 id="futureideas">Future Ideas</h2>
<p>This extension is new, and I have some ideas on how to make it even more useful. If you have ideas, by all means, please share your feedback here or in GitHub.</p>
<p>One new feature I would like to add is the ability to adjust the assumed words-per-minute that a person reads. By default in many calculations, this is 200 words/minute. The API is open for this, and I have made a PR into the library to adjust for it. It is only a matter of time before I add this feature.</p>
<p>Another is to allow adjusting the types of files that it will read. Currently, it only reads markdown files. But this could be opened for extending to other files, too. Making this a user configured feature could be nice.</p>
<h2 id="whyisnttheiconisappearinginthestatusbar">Why Isn't the Icon is Appearing in the Status Bar?</h2>
<p>There is only so much room in the status bar and the Read Time status bar icon may become a casualty and have disappeared from your status bar. You can test this by zooming out of your vs code a few times. Zooming out will also zoom out the status bar. If the status bar icon were a casualty, then it would reappear when you zoom out.</p>
<p>The Read Time icon is very slim (just an icon and a number). However, if it is not appearing, you can try to change your settings for other items in the status bar to make them disappear. In other words, clean up your status bar by hiding things you do not want to see. Here is one example where I hid a few things that were in my status bar.</p>
<pre><code class="language-json">  &quot;workbench.statusBar.feedback.visible&quot;: false,
  &quot;debug.showInStatusBar&quot;: &quot;never&quot;,
  &quot;azure.showSignedInEmail&quot;: false,
  &quot;liveshare.showInStatusBar&quot;: &quot;whileCollaborating&quot;,
  &quot;spellright.statusBarIndicator&quot;: false
</code></pre>
<h2 id="vscodeextensionsforwriting">VS Code Extensions for Writing</h2>
<p>In case you are curious, here are the VS Code extensions I use:</p>
<ul>
<li><a href="https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint&amp;wt.mc_id=johnpapanet-blog-jopapa">Markdown Lint</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=ban.spellright&amp;wt.mc_id=johnpapanet-blog-jopapa">Spell Right</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.vscode-peacock&amp;wt.mc_id=johnpapanet-blog-jopapa">Peacock</a> - I color code my vs code editor for writing articles</li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.read-time&amp;wt.mc_id=johnpapanet-blog-jopapa">Read Time</a></li>
</ul>
<h2 id="whatdoyouthink">What Do You Think?</h2>
<p>I'd love to hear your feedback. What do you like about it? What else would be useful to you in writing?</p>
]]></content:encoded></item><item><title><![CDATA[11 Awesome Resources for Building Your Applications in CI Using Azure DevOps Pipelines]]></title><description><![CDATA[If you want to build an Azure DevOps pipeline using YAML, this article is for you]]></description><link>https://johnpapa.net/11devopslinks/</link><guid isPermaLink="false">5ca4c64f8f0ea500bff57237</guid><category><![CDATA[webdev]]></category><category><![CDATA[devops]]></category><category><![CDATA[azure]]></category><dc:creator><![CDATA[John Papa]]></dc:creator><pubDate>Wed, 03 Apr 2019 14:45:00 GMT</pubDate><content:encoded><![CDATA[<p>This isn't your average article. It may be more accurate to classify this article as a brain dump that I hope you'll find some value. It's a condensed list of links that I found to be very useful for creating a CI build pipeline.</p>
<p><img src="https://johnpapa.net/content/images/2019/04/conveyor.png" alt="conveyor"></p>
<p>This is what I would have loved when I was learning how to create a CI pipeline with Azure DevOps. I wanted to create the pipeline using a YAML file, and while the quick-start is helpful, my scenario was more nuanced. I bet your situations have special cases too.</p>
<p>As I was working on putting my app into an Azure DevOps pipeline I wrote down all of the links that I found to be super helpful. Thus, I decided to make a list of them and share them with you, in case they may be of help to you, as well.</p>
<blockquote>
<p>In case you are curious, <a href="https://johnpapa.visualstudio.com/vscode-peacock/_build/results?buildId=186">this is the Pipeline that I built</a> when I was creating <a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.vscode-peacock&amp;wt.mc_id=devto-blog-jopapa">Peacock</a>.</p>
</blockquote>
<h2 id="freefoross">Free for OSS?</h2>
<p>What does it cost for OSS? This is a great question, and the best answer comes directly from the <a href="https://azure.microsoft.com/en-us/blog/announcing-azure-pipelines-with-unlimited-ci-cd-minutes-for-open-source/?wt.mc_id=devto-blog-jopapa">source here</a>.</p>
<blockquote>
<p>With the introduction of Azure DevOps today, we’re offering developers a new CI/CD service called Azure Pipelines that enables you to continuously build, test, and deploy to any platform or cloud.</p>
</blockquote>
<p>Here are some more details on the <a href="https://azure.microsoft.com/en-us/pricing/details/devops/azure-devops-services/?WT.mc_id=devto-blog-jopapa">pricing and what you can get for free and what qualifies</a>.</p>
<h2 id="gimmethelinks">Gimme the Links</h2>
<p>I tried, below, to explain why each might be helpful, so you can decide which might suit your use cases.</p>
<p>I hope this helps!</p>
<h3 id="1startingpageforallthingsdevops">- 1 - Starting page for all things DevOps</h3>
<p>Start here. Seriously, it's a great starting place that can help ground you in the Azure DevOps tool and what you can do.</p>
<ul>
<li>Start here to learn <a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/?view=azure-devops&amp;wt.mc_id=devto-blog-jopapa">Azure Pipelines</a></li>
</ul>
<h3 id="2multiplejobs">- 2 - Multiple Jobs</h3>
<p>If you want to run your builds in different ways, this is a great resource. For example, imagine you want to run your build on Windows and Linux and macOS. If so, this is the place to start.</p>
<ul>
<li>Learn how to <a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/process/multiple-phases?view=azure-devops&amp;tabs=yaml&amp;wt.mc_id=devto-blog-jopapa">create multiple jobs</a></li>
</ul>
<h3 id="3triggerabuild">- 3 - Trigger a Build</h3>
<p>If you want to trigger builds from your GitHub repo to Azure DevOps, this is a great resource. It shows how to set up the YAML for Triggers for branches and Pull Requests.</p>
<ul>
<li>Learn how to set up the <a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/build/triggers?view=azure-devops&amp;tabs=yaml&amp;wt.mc_id=devto-blog-jopapa">YAML for Triggers for branches and Pull Requests</a></li>
</ul>
<h3 id="4yamlexample">- 4 - YAML Example</h3>
<p>If you want an example of what a YAML file in DevOps looks like, look no further.</p>
<ul>
<li>Check out this <a href="https://github.com/MicrosoftDocs/pipelines-javascript/blob/master/azure-pipelines.yml?wt.mc_id=devto-blog-jopapa">example of a pipeline YAML file</a></li>
</ul>
<h3 id="5buildmultiplebranches">- 5 - Build Multiple Branches</h3>
<p>If you want to build more than one branch or exclude some branches from builds, then this is a great resource.</p>
<ul>
<li>Learn to <a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/build/ci-build-git?view=azure-devops&amp;tabs=yaml&amp;wt.mc_id=devto-blog-jopapa">build multiple branches</a></li>
</ul>
<h3 id="6buildusingmultiplenodeversions">- 6 - Build Using Multiple Node Versions</h3>
<p>If you like to test against more than one version of Node.js, this is a great resource.</p>
<ul>
<li>Learn how to <a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/languages/javascript?view=azure-devops&amp;wt.mc_id=devto-blog-jopapa&amp;tabs=yaml#use-multiple-node-versions">create a build strategy for multiple Node versions</a></li>
</ul>
<h3 id="7hostedagentsandyaml">- 7 - Hosted Agents and YAML</h3>
<p>If you want to learn more about how to create the hosted agent (the thing that does all the work for you), this is a great resource.</p>
<ul>
<li>Learn the <a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops&amp;wt.mc_id=devto-blog-jopapa&amp;tabs=yaml#use-a-microsoft-hosted-agent">Host agent syntax for the YAML</a></li>
</ul>
<h3 id="8examplepipelineofavscodeextension">- 8 - Example Pipeline of a VS Code Extension</h3>
<p>I was building a VS Code extension, so this example was helpful for me. If you are building a Node.js app, it may help you too.</p>
<ul>
<li>See an <a href="https://code.visualstudio.com/api/working-with-extensions/continuous-integration#azure-pipelines?&amp;wt.mc_id=devto-blog-jopapa">example of a pipeline for VS Code Extensions</a></li>
</ul>
<h3 id="9multiplebuildjobs">- 9 - Multiple Build Jobs</h3>
<p>If you want to run your build in different ways, this is a great resource. A great example is running multiple jobs for multiple OS's.</p>
<ul>
<li>Learn how to run <a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/process/multiple-phases?view=azure-devops&amp;tabs=yaml&amp;wt.mc_id=devto-blog-jopapa">multiple jobs</a></li>
</ul>
<h3 id="10extensionforvscode">- 10 - Extension for VS Code</h3>
<p>If you want some extra help for Azure DevOps Pipelines and YAML in VS Code, try this resource.</p>
<ul>
<li>
<p>Learn about the <a href="https://azure.microsoft.com/en-us/blog/new-azure-pipelines-announcements-vs-code-extension-github-releases-and-more/?wt.mc_id=devto-blog-jopapa">Azure Pipelines</a> extension for VS Code</p>
</li>
<li>
<p>Get the <a href="https://marketplace.visualstudio.com/items?itemName=ms-azure-devops.azure-pipelines&amp;wt.mc_id=devto-blog-jopapa">Azure DevOps Pipelines extension</a></p>
</li>
</ul>
<h3 id="11allthingsyaml">- 11 - All Things YAML</h3>
<p>If you get stuck in the YAML (I know I did), then this is an excellent resource for figuring out what goes where.</p>
<ul>
<li>Lean on the <a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&amp;tabs=schema&amp;viewFallbackFrom=vsts&amp;wt.mc_id=devto-blog-jopapa">YAML scheme reference</a></li>
</ul>
<p>I hope these help you as much as they helped me!</p>
<p><em>this article is <a href="https://johnpapa.net/11devopslinks/">cross posted to from johnpapa.net</a></em></p>
]]></content:encoded></item><item><title><![CDATA[How I Write Online Articles]]></title><description><![CDATA[<p>I like to write, and when I do, I prefer writing in markdown. Lately, people have been asking my writing process involves, so I decided to write it down in this short post. This is my process and in no way should you feel obligated to use it. Hopefully, this</p>]]></description><link>https://johnpapa.net/how-i-write-online-articles/</link><guid isPermaLink="false">5ca232818f0ea500bff5722d</guid><category><![CDATA[devrel]]></category><category><![CDATA[vscode]]></category><category><![CDATA[discuss]]></category><category><![CDATA[markdown]]></category><category><![CDATA[career]]></category><dc:creator><![CDATA[John Papa]]></dc:creator><pubDate>Mon, 01 Apr 2019 15:55:08 GMT</pubDate><content:encoded><![CDATA[<p>I like to write, and when I do, I prefer writing in markdown. Lately, people have been asking my writing process involves, so I decided to write it down in this short post. This is my process and in no way should you feel obligated to use it. Hopefully, this helps you.</p>
<h2 id="mywritingprocess">My Writing Process</h2>
<p>All of this assumes I have an idea and I know what I am writing. That in itself is a whole different topic and not covered here. If you want to know how I write, this is the right place to be.</p>
<p><img src="https://johnpapa.net/content/images/2019/04/writing-articles-1.png" alt="sketchnote"></p>
<h3 id="mygoals">My Goals</h3>
<p>I have some primary goals with writing:</p>
<ol>
<li>Stable Tools: What I write in must be stable (I don't want to have to rewrite it!)</li>
<li>Saving: I want to save my articles, so I can iterate, refer back, and always have it.</li>
<li>Proofing: I want to spell check and grammar check my articles.</li>
<li>Markdown: I prefer writing in markdown</li>
<li>Offline: It must work offline</li>
</ol>
<h2 id="myworkflow">My Workflow</h2>
<p>My workflow is short and hits my main goals. So let's get right to the workflow.</p>
<h3 id="1vscode">- 1 - VS Code</h3>
<p>I use <a href="https://code.visualstudio.com?wt.mc_id=johnpapanet-blog-jopapa">VS Code</a> to write my articles. It has excellent markdown support and is super stable which satisfies two of my goals. Plus, I work in this for my coding all day, so I don't have to switch to another tool.</p>
<p>Here are the VS Code extensions I use:</p>
<ul>
<li><a href="https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint&amp;wt.mc_id=johnpapanet-blog-jopapa">Markdown Lint</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=bierner.markdown-preview-github-styles&amp;wt.mc_id=johnpapanet-blog-jopapa">Markdown Preview</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=ban.spellright&amp;wt.mc_id=johnpapanet-blog-jopapa">Spell Right</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.vscode-peacock&amp;wt.mc_id=johnpapanet-blog-jopapa">Peacock</a> - I color code my vs code editor for writing articles</li>
</ul>
<h3 id="2proofing">- 2 - Proofing</h3>
<p>I currently use Spell Right (see the link above) for spell checking in my markdown. I then copy and paste the content to a local doc in Grammarly for grammar checking. You can use any grammar checking tools including Microsoft Word.</p>
<p>I find this to be a good step because spell check only catches part of the story. Grammar checking helps to avoid confusing sentences.</p>
<h3 id="3pushtoaprivategithubrepo">- 3 - Push to a Private GitHub Repo</h3>
<p>Saving my content and making sure I do not lose it (2 of my goals) are reinforced by creating a GitHub repository for my content. I prefer this to be private as it contains a lot of my writing. I also organize my repository in a way that makes sense to me. I can find my articles quickly, modify them, iterate on them, and move along.</p>
<p>VS Code integrates with GitHub well, and I use this every day for source control. I find comfort staying in my familiar tools to write articles, commit, push, and move along.</p>
<p>Here is an example of my meta in dev.to:</p>
<pre><code class="language-text">---
title: How I Write Online Articles
published: true
description: How you can write online articles
tags: devrel, vscode, markdown, discuss
cover_image: https://thepracticaldev.s3.amazonaws.com/i/n0ecqvxjrzh9qy6ekfgy.png
canonical_url: https://johnpapa.net/how-i-write-online-articles/
---
</code></pre>
<h3 id="4copyandpastetotargetsite">- 4 - Copy and Paste to Target Site</h3>
<p>The target for my articles could be Ghost (where I host my blog), Medium, dev.to, or any number of platforms. Unfortunately, because they are all different, some support various features, and few have an API, I currently copy and paste. Copy and paste only takes a few moments, so it's not a big deal.</p>
<p>Once I paste into the target platform, I generally find something that looks a little awkward. I make my adjustments in the target platform, test it out in preview (not publishing it), and repeat till it is good.</p>
<p>Then I copy the changes back to my local VS Code editor, commit, and push.</p>
<h3 id="5publishonmyblogandthendevto">- 5 - Publish on my Blog and then dev.to</h3>
<p>I publish my content to my blog first, since it is my blog and I like having a home for all of my content. Then I copy the canonical URL for my blog post and that to the dev.to target in the headers by setting <code>canonical_url</code>. Then I'll publish the same article on dev.to.</p>
<h2 id="coverimageorsketchnotes">Cover Image or SketchNotes</h2>
<p>I like to add something visual to my articles. I find visuals in articles to help connect the concepts in my mind. Also, it's fun! There are a lot of ways to get royalty free images. <a href="https://www.pexels.com">Pexels</a> is one of these.</p>
<p>Often I want a very specific image and it is much easier to draw one. This is where I use my sketchnotes. The sketchnote at the top of this article is what I use to plan out my article.</p>
<blockquote>
<p>I'll share more on how and why I use sketchnotes in a future article.</p>
</blockquote>
<h2 id="ideasforthefuture">Ideas for the Future</h2>
<p>I'd love to have an open API for all writing platforms, especially dev.to. Imagine writing locally in your favorite tools like VS Code, and then pressing a command which publishes the article on dev.to! I'm currently discussing some ideas for how I could write such an extension to publish to dev.to. An extension would require an API from a target platform and a bunch of cool features which I could code in the extension (gist previews using liquid embeds, for example). But ... hey ... it would be a lot of fun and very useful.</p>
<p>The great team at dev.to are considering an API. I imagine it one feature in a long list of great ideas they are prioritizing.</p>
<h2 id="whatdoyoudo">What Do You Do?</h2>
<p>I shared my writing process. I'd love to hear about yours! Is yours different? What do you like about it? What do you wish you could change?</p>
]]></content:encoded></item><item><title><![CDATA[Speed of Voice - The Pace of Your Presentation Can Heavily Impact How Well it Lands]]></title><description><![CDATA[Learn how to control the pace of your voice in your presentation to land your message]]></description><link>https://johnpapa.net/speed-of-voice/</link><guid isPermaLink="false">5c9ea2248f0ea500bff57225</guid><category><![CDATA[devrel]]></category><category><![CDATA[career]]></category><category><![CDATA[discuss]]></category><dc:creator><![CDATA[John Papa]]></dc:creator><pubDate>Fri, 29 Mar 2019 22:57:08 GMT</pubDate><content:encoded><![CDATA[<blockquote>
<p>Are you a storyteller on stage? Do you want to engage and inspire your audience comfortably and naturally? The great news is that you have one of the essential tools to accomplish this already! Let's explore how you can adjust your voice to tell your stories in a more impactful way.</p>
</blockquote>
<h2 id="pace">Pace</h2>
<p>Have you ever been told you talk too fast or too slow during a presentation?</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/o6pdkv0zy3ekm1rkxj7j.jpg" alt="Pace on Stage"></p>
<p>Let's dissect that for a moment. What pace is too fast vs. too slow? Why is either a problem? Is it because the person is trying to keep up and your quick pace is hard to process? Is slower better, or is it not enough to keep their interest? How do you solve this problem (is it even a problem)? You might have to be a wizard and figure out the exact pace that makes everyone happy. But you know, my father always tells me that if I try to make everyone happy I'll be very disappointed. The same thing here is true.</p>
<p>So let's step back a bit and talk about the right pace. My feeling is that there is no single right pace. Often I find that a presentation where the velocity varies is much more interesting than one where the same rhythm and cadence exists.</p>
<h2 id="patterns">Patterns</h2>
<p>Our brains are attuned for detecting patterns. When we find them, things start to blend in. Remember that catchy song you were recently listening to while working? I bet you remember the pattern and can work while it's playing. You can focus on other things because you have trained yourself to expect the pattern that is playing. We can tune out on patterns and put them in the back of our minds.</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/2pbl3mp7fc5o2fhfsvo3.jpg" alt="Patterns"></p>
<h2 id="changethepatterns">Change the Patterns</h2>
<p>Now imagine you are attending or watching a presentation. You will detect patterns in the presentation, perhaps in the back of your mind. But they are there. Your mind is trained to recognize them and expect them. If the pace is constant throughout the presentation, that is indeed a pattern.</p>
<p>If the presenter varies his/her pace at critical moments, it recaptures your attention.</p>
<blockquote>
<p>Patterns are another tool we can use. Both maintaining patterns and breaking patterns are good tools. I'll share more on this in a future article, outside of this series on &quot;voice&quot;.</p>
</blockquote>
<h2 id="ludicrousspeed">Ludicrous Speed</h2>
<p>Sometimes we may speak quickly and pretty much non-stop without pausing. Sometimes people are just fast-talkers. This is OK - in fact talking fast can be very effective at times. The key part being &quot;at times&quot;. When we talk fast we can generate excitement. Maybe you're so excited about this topic that this section of the presentation makes you giddy! I know there are times I want to jump up and down because I'm excited about what I am sharing. This is OK. No, it's better than OK. If you can help make your audience feel what you feel, you've connected with them.</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/mnefx4nw6njz7ndxng4x.png" alt="Speed"></p>
<p>You should use a fast pace at key moments in your presentation to generate a feeling in your audience. Do this when it feels right.</p>
<p>I recommend thinking about what your normal pace is, and then find a comfortable faster and slower pace that you can use when you want to shake things up. Use these changes of pace purposefully to grab the audience, connect with them, and help them share the feeling you have right then and there.</p>
<p>One caveat to remember is that a fast pace does not mean you have to lose clarity. Be sure your voice is still clear and understandable. Especially if you are speaking to audiences that may not be native speaking to the language you are talking.</p>
<h2 id="pausingatkeymoments">Pausing at Key Moments</h2>
<p>We're often told that slowing down too much can be bad in a presentation. That dead silence is a bad thing. Well, it can be, but it can also be an incredibly effective way to grab attention and make an essential point.</p>
<p>Have you ever listened to a presentation, a news report, or just a conversation with your friends where there was suddenly a pause in the action? What did you do? This pause can grab your attention cleverly and subtly.</p>
<p>When you place a pause at a strategic moment in a presentation, they can positively impact its effectiveness. Here are some use cases for using a pause to improve a presentation:</p>
<ol>
<li>when you want the listener to have time to absorb an important point and think about it</li>
<li>when you ask a question you want them to consider and answer in their heads.</li>
<li>when you want to give the audience a chance to predict what you will say/do next</li>
<li>when you want to change the direction of a presentation</li>
<li>when you need to collect your thoughts or breathing</li>
</ol>
<p>You know those &quot;ums&quot; and &quot;so's&quot; that pop up a lot? They are filler words, and sometimes we use those to fill in gaps between our thoughts. Ask yourself this: Do you follow a presentation when the speaker is talking fast and non-stop? Maybe. But what if those filler moments were actual pauses? This might give the audience time to think about what you are saying. You can also vary the length of your breaks, depending on the reaction you want from your audience.</p>
<p>A short pause is good for the audience to catch up and process what you say. A longer break gives them time to think through it, answer a question, and wonder where you are going next. Remember, you control the narrative.</p>
<p>This doesn't mean you should pause every other word. You likely won't be effective talking consistently like dramatic Captain Kirk on Star Trek for a 30-minute presentation. But if you find the key strategic moments in your presentation where you need to grab their attention. A pause might do the trick.</p>
<h2 id="partingtipsonpace">Parting Tips on Pace</h2>
<p>Here are quick tips for using the pace of your voice.</p>
<ul>
<li>Vary your pace. People learn to live and look for patterns and rhythms.</li>
<li>Use a fast pace at a key moment to generate excitement.</li>
<li>Use pauses. If you like a number, choose two key moments in your next presentation.</li>
<li>If you think you may speak too slowly, vary your rate to speak quickly at times.</li>
<li>If you think you may talk too quickly, change your rate to speak slower at times.</li>
</ul>
<p>Finally, observe the audience when you vary your pace. What reactions do they have? Experiment with this and as it will help you adjust your speed and improve your engagement with your audience.</p>
<blockquote>
<p>A bonus tip is to use your body language during a pause to gather the audience. Ask a question or make a profound point, then smile and node your head with them.</p>
</blockquote>
<h2 id="whatsinthisseries">What's in This Series?</h2>
<p>Here are the other topics in this series, in no particular order. I'll update these links as I publish them.</p>
<p>0 -<a href="https://johnpapa.net/use-your-voice-effectively-for-impactful-presentations/">Using Your Voice</a><br>
1 - <a href="https://johnpapa.net/speed-of-voice">Pace of your voice</a><br>
2 - Pitch of your voice<br>
3 - Volume of your voice<br>
4 - Emphasis of words in your speech<br>
5 - Clarity of your speech</p>
<p>Good luck with your next presentation!</p>
<p><em>cross posted to <a href="https://dev.to/azure/speed-of-voice-the-pace-of-your-presentation-can-heavily-impact-how-well-it-lands-9b6">dev.to here</a></em></p>
]]></content:encoded></item><item><title><![CDATA[Recommended VS Code Extensions for Angular Developers]]></title><description><![CDATA[Recommended VS Code Extensions for Angular Developers]]></description><link>https://johnpapa.net/rec-ng-extensions/</link><guid isPermaLink="false">5c9cc1f98f0ea500bff5721d</guid><category><![CDATA[webdev]]></category><category><![CDATA[vscode]]></category><category><![CDATA[javascript]]></category><category><![CDATA[angular]]></category><dc:creator><![CDATA[John Papa]]></dc:creator><pubDate>Thu, 28 Mar 2019 12:47:04 GMT</pubDate><media:content url="https://johnpapa.net/content/images/2019/03/axe-close-up-drill-909256.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://johnpapa.net/content/images/2019/03/axe-close-up-drill-909256.jpg" alt="Recommended VS Code Extensions for Angular Developers"><p>I am often asked, &quot;What are you favorite VS Code extensions for Angular?&quot;. This post covers my most often used VS Code extensions for Angular development.</p>
<blockquote>
<p>The right tool for the right job.</p>
</blockquote>
<p>We hear this a lot. When we use good tools, our development lives become so much more efficient. I created an extension pack that makes it easy to get them all by installing this one extension.</p>
<p>While there are other notable and excellent extensions, this list is what I maintain (and it is fluid) in an extension pack. The coolness of an extension pack is that you can install a set related of extensions all at once.</p>
<h2 id="angularessentials">Angular Essentials</h2>
<p>You can get them all most easily by installing my <a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.angular-essentials&amp;wt.mc_id=devto-blog-jopapa">Angular Essentials extension pack for VS Code</a>.</p>
<ul>
<li>Click <a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.angular-essentials&amp;wt.mc_id=devto-blog-jopapa">here to install them all</a> from the extension pack</li>
</ul>
<p>... or ... You can also install each of these one by one, if you don't want all of them.</p>
<h3 id="includedextensions">Included Extensions</h3>
<p>Here is the list of extensions the pack includes, in alphabetical order:</p>
<ul>
<li>
<p><a href="https://marketplace.visualstudio.com/items?itemName=natewallace.angular2-inline&amp;wt.mc_id=devto-blog-jopapa">Angular Inline</a> - This extension extends the javascript and typescript languages to add Angular2 specific features for inline templates and stylesheets. When you define an inline template or inline style sheet using the back-tick character(`) the content will be processed by this extension.</p>
</li>
<li>
<p><a href="https://marketplace.visualstudio.com/items?itemName=Angular.ng-template&amp;wt.mc_id=devto-blog-jopapa">Angular Language Service</a> - This extension provides a rich editing experience for Angular templates, both inline and external templates. This extension is brought to you by members of the Angular team. It is fantastic at helping write solid code in the html templates.</p>
</li>
<li>
<p><a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.Angular2&amp;wt.mc_id=devto-blog-jopapa">Angular Snippets</a> - Angular snippets that follow the official style guide, for TypeScript, templates, and RxJS.</p>
</li>
<li>
<p><a href="https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-chrome&amp;wt.mc_id=devto-blog-jopapa">Chrome Debugger</a> - VS Code debugger for Chrome.</p>
</li>
<li>
<p><a href="https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig&amp;wt.mc_id=devto-blog-jopapa">Editor Config</a> - EditorConfig for VS Code. Great for maintaining consistent editor settings.</p>
</li>
<li>
<p><a href="https://marketplace.visualstudio.com/items?itemName=pkief.material-icon-theme&amp;wt.mc_id=devto-blog-jopapa">Material Icon Theme</a> Show material icons in the explorer</p>
</li>
<li>
<p><a href="https://marketplace.visualstudio.com/items?itemName=eg2.vscode-npm-script&amp;wt.mc_id=devto-blog-jopapa">npm</a> This extension supports running npm scripts defined in the package.json file and validating the installed modules against the dependencies defined in the package.json.</p>
</li>
<li>
<p><a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.vscode-peacock&amp;wt.mc_id=devto-blog-jopapa">Peacock</a> This extension subtly changes the workspace color of your workspace. Ideal when you have multiple VS Code instances and you want to quickly identify which is which.</p>
</li>
<li>
<p><a href="https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode&amp;wt.mc_id=devto-blog-jopapa">Prettier</a> VS Code plugin for prettier/prettier, which formats code consistently</p>
</li>
<li>
<p><a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-typescript-tslint-plugin&amp;wt.mc_id=devto-blog-jopapa">tslint</a> - Adds tslint to VS Code using the TypeScript TSLint language service plugin.</p>
</li>
<li>
<p><a href="https://marketplace.visualstudio.com/items?itemName=johnpapa.winteriscoming&amp;wt.mc_id=devto-blog-jopapa">Winter is Coming</a> I like using the dark blue theme</p>
</li>
</ul>
<h2 id="debuggingangularinvscode">Debugging Angular in VS Code</h2>
<p>The Chrome Debugger extension is excellent, and it enables you to debug front-end javascript in VS Code. You should set this up by <a href="https://code.visualstudio.com/docs/nodejs/angular-tutorial#_configure-the-chrome-debugger?wt.mc_id=devto-blog-jopapa">following this guide in the docs</a>.</p>
<p>tldr;</p>
<p>Add the configuration for <code>chrome</code>, as shown below, to your <code>launch.json</code>:</p>
<pre><code class="language-json">{
  &quot;version&quot;: &quot;0.2.0&quot;,
  &quot;configurations&quot;: [
    {
      &quot;type&quot;: &quot;chrome&quot;,
      &quot;request&quot;: &quot;launch&quot;,
      &quot;name&quot;: &quot;Launch Chrome against localhost&quot;,
      &quot;url&quot;: &quot;http://localhost:4200&quot;,
      &quot;webRoot&quot;: &quot;${workspaceFolder}&quot;
    }
  ]
}
</code></pre>
<p>Then, run your angular app with <code>ng serve -o</code>, set some breakpoints in VS Code, and press <code>F5</code>.</p>
<h2 id="whatelse">What Else</h2>
<p>If you have ideas for what other extensions may be a good fit for Angular Essentials, please discuss them to the comments here or as an issue in GitHub.</p>
<p>I have some in mind that I'm currently evaluating ... including <a href="https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console&amp;wt.mc_id=devto-blog-jopapa">Angular Console</a>, which is extremely promising!</p>
<p><em>This article is <a href="https://dev.to/azure/use-your-voice-effectively-for-impactful-presentations-4128">cross posted to dev.to</a></em></p>
]]></content:encoded></item><item><title><![CDATA[Use Your Voice Effectively for Impactful Presentations]]></title><description><![CDATA[Learn how to use your voice to be an effective storyteller in presentations.]]></description><link>https://johnpapa.net/use-your-voice-effectively-for-impactful-presentations/</link><guid isPermaLink="false">5c9415528f0ea500bff57213</guid><category><![CDATA[devrel]]></category><category><![CDATA[career]]></category><category><![CDATA[discuss]]></category><dc:creator><![CDATA[John Papa]]></dc:creator><pubDate>Thu, 21 Mar 2019 22:53:01 GMT</pubDate><media:content url="https://johnpapa.net/content/images/2019/03/voice.JPG" medium="image"/><content:encoded><![CDATA[<h1 id="usingyourvoiceasastoryteller">Using Your Voice as a Storyteller</h1>
<img src="https://johnpapa.net/content/images/2019/03/voice.JPG" alt="Use Your Voice Effectively for Impactful Presentations"><p>Are you a storyteller on stage? Do you want to engage and inspire your audience in a comfortable and natural way? The great news is that you have one of the essential tools to accomplish this already!</p>
<p><strong>Your voice</strong>.</p>
<p>But how? Ah, there are a variety of ways you can use your voice to tell your stories in an appealing and impactful way. Let's explore these in this series.</p>
<h2 id="whenyourpresentationlandswell">When Your Presentation Lands Well</h2>
<p>When you're &quot;on&quot;, your presentation is a story that flows along a melody. The audience is responding and receiving your main message. You feel great because you connected with them. They feel great because they connected with you.</p>
<p>There are a lot of ways to help improve a presentation, but like learning anything, I like to reduce the concept count to focus on one area at a time. Reducing the concept to one thing, such as voice, allows me to improve in that area for each upcoming presentation with being distracted with 100 things to ponder.</p>
<p>Let's focus on your voice. This series of posts that I'm sharing will explain some of the ways I have learned from various coaches and training that have helped me improve how well my presentations land.</p>
<h2 id="whatscominginthisseries">What's Coming in This Series?</h2>
<p>Are you dramatically pausing like Captain Kirk or are you speaking as fast as a legal disclaimer in a radio commercial? How high or low do you talk when presenting Do you have a whispering or a booming voice? Do you accentuate critical words and phrases?</p>
<p>If any of these intrigue you, I hope you'll enjoy the upcoming posts (in no particular order):</p>
<p>1 - Pace of your voice<br>
2 - Pitch of your voice<br>
3 - Volume of your voice<br>
4 - Emphasis of words in your speech<br>
5 - Clarity of your speech</p>
<p>I'll update these links as I publish them.</p>
<p>I hope you find value in these!</p>
<p><em><a href="https://dev.to/azure/use-your-voice-effectively-for-impactful-presentations-4128">Cross posted to dev.to</a></em></p>
]]></content:encoded></item><item><title><![CDATA[How do You Structure Your Code When Moving Your API from Express to Serverless Functions?]]></title><description><![CDATA[Learn one good way to structure your serverless functions on Azure.]]></description><link>https://johnpapa.net/how-do-you-structure-your-code-when-moving-your-api-from-express-to-serverless-functions/</link><guid isPermaLink="false">5c9407828f0ea500bff5720b</guid><category><![CDATA[node]]></category><category><![CDATA[javascript]]></category><category><![CDATA[webdev]]></category><category><![CDATA[serverless]]></category><dc:creator><![CDATA[John Papa]]></dc:creator><pubDate>Thu, 21 Mar 2019 21:55:21 GMT</pubDate><media:content url="https://johnpapa.net/content/images/2019/03/func.JPG" medium="image"/><content:encoded><![CDATA[<img src="https://johnpapa.net/content/images/2019/03/func.JPG" alt="How do You Structure Your Code When Moving Your API from Express to Serverless Functions?"><p>There are a lot of articles showing how to use serverless functions for a variety of purposes. A lot of them cover how to get started, and they are very useful. But what do you do when you want to organize them a bit more as you do for your Node.js Express APIs?</p>
<p>There's a lot to talk about on this topic, but in this post, I want to focus specifically on one way you can organize your code. Add a comment to let me know what other areas you are interested in, and I'll consider covering those in the future.</p>
<p>Here are some <em>getting started</em> resources that I recommend:</p>
<ul>
<li><a href="https://code.visualstudio.com/tutorials/functions-extension/getting-started?wt.mc_id=johnpapanet-blog-jopapa">Your first Azure Function with the VS Code Functions Extension</a></li>
<li><a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-overview?wt.mc_id=johnpapanet-blog-jopapa">Azure Functions Overview</a></li>
<li><a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference?wt.mc_id=johnpapanet-blog-jopapa">Developer Guide</a></li>
<li><a href="https://github.com/johnpapa/heroes-serverless?wt.mc_id=johnpapanet-blog-jopapa">Sample Code in a GitHub Repo</a></li>
<li><a href="https://docs.microsoft.com/en-us/azure/cosmos-db/sql-api-nodejs-get-started?wt.mc_id=johnpapanet-blog-jopapa">JavaScript SDK for Cosmos DB</a></li>
</ul>
<h2 id="whyshouldyoustructureyourcode">Why Should You Structure Your Code?</h2>
<p>You can put all of your function logic in a single file. But do you want to do that? What about shared logic? Testing? Debugging? Readability? This is where having a pattern or structure can help. There are many ways to do this. Beyond those I mentioned above, consistency is the primary additional aspect I target.</p>
<p>Here is a pretty standard representation of a function app:</p>
<pre><code class="language-text">FunctionApp
 | - host.json
 | - myfirstfunction
 | | - function.json
 | | - index.js
 | | - ...
 | - mysecondfunction
 | | - function.json
 | | - index.js
 | | - ...
 | - sharedCode
</code></pre>
<p>Here is what my structure is looking like, just for the heroes API.</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/07y8kaeg3k6g0gnw2kgo.png" alt="How do You Structure Your Code When Moving Your API from Express to Serverless Functions?"></p>
<h2 id="yourentrypoint">Your Entry Point</h2>
<p>The entry point to your function is in a file called <code>index.js</code> in a folder with the same name as your function.</p>
<p>The function itself is pretty self-explanatory. When this function is called the context is passed to it. The context has access to the request and response objects, which is super convenient. Then I call the asynchronous operation to get my data and set the response.</p>
<pre><code class="language-javascript">// heroes-get/index.js
const { getHeroes } = require('../shared/hero.service');

module.exports = async function(context) {
  context.log(
    'getHeroes: JavaScript HTTP trigger function processed a request.'
  );
  await getHeroes(context);
};
</code></pre>
<blockquote>
<p>An alternative is to pass <code>context.res</code> and/or <code>context.req</code>  into the service. How you choose is up to you. I prefer to pass <code>req</code> and <code>res</code> in as it's more familiar to me. But passing <code>context</code> also allows access to other features, such as <code>context.log</code>. There is no right or wrong here, choose your adventure and be consistent.</p>
</blockquote>
<h2 id="dataaccessservice">Data Access Service</h2>
<p>When you create your first Azure function, the &quot;hello world&quot; function usually returns a static string message. In most APIs, you're going to want to talk to another database or web service to get/manipulate data before returning a response.</p>
<p>In my case, I am getting a list of heroes. So I defer most of my data access service to a Node.js module I named <code>hero.service.js</code>. Why do this? Simply put, organizing my code (in this case the data access service) so it is DRY (do not repeat yourself) and isolates the responsibility and makes it easier to scale, extend, debug, and test.</p>
<p>The <code>hero.service.js</code> module begins by getting a reference to the container (the storage unit that contains my data for my database). Why abstract that? Good question ... I abstract it to a shared module so I can reuse that logic. I'll be needing to get containers of all types, and getting the container requires accessing the database with some database specific connectivity APIs. We'll look closer at that in a moment.</p>
<p>The <code>getHeroes</code> service accepts the context and uses destructuring to get the response object out into a variable <code>res</code>. Then it tries to get the heroes, and when successful it adds them to the response. When it fails, it responds with an error.</p>
<pre><code class="language-javascript">// shared/hero.service.js
const { heroes: container } = require('./index').containers;

async function getHeroes(context) {
  let { req, res } = context;
  try {
    const { result: heroes } = await container.items.readAll().toArray();
    res.status(200).json(heroes);
  } catch (error) {
    res.status(500).send(error);
  }
}
</code></pre>
<h2 id="shareddatabasemodule">Shared Database Module</h2>
<p>The data access service module <code>hero.service.js</code> imports from a shared database module. This module is where the magic happens for connecting to our database. In this case, I am using <a href="https://docs.microsoft.com/en-us/azure/cosmos-db/sql-api-nodejs-get-started?wt.mc_id=johnpapanet-blog-jopapa">Azure's CosmosDB via its Node.js SDK in npm</a>.</p>
<p>Notice that the code reads in the secrets via the Node.js environment variables. Then it merely exports the containers from the appropriate database. I can use different environment variables without requiring the code to change.</p>
<pre><code class="language-javascript">// shared/index.js
const cosmos = require('@azure/cosmos');

const endpoint = process.env.CORE_API_URL;
const masterKey = process.env.CORE_API_KEY;
const databaseDefName = 'vikings-db';
const heroContainerName = 'heroes';
const villainContainerName = 'villains';
const { CosmosClient } = cosmos;

const client = new CosmosClient({ endpoint, auth: { masterKey } });

const containers = {
  heroes: client.database(databaseDefName).container(heroContainerName),
  villains: client.database(databaseDefName).container(villainContainerName)
};

module.exports = { containers };
</code></pre>
<h2 id="whatsyourroute">What's Your Route?</h2>
<p>I didn't want my API to be <code>/api/heroes-get</code> but rather I prefer <code>/api/heroes</code> when executing the <code>GET</code> action, so I changed that. My function is in the path <code>/heroes-get/index.js</code> and inside that same folder, there is a <code>function.json</code> file. This file is where you configure the function's behavior. The key one I wanted to change was the route alias. Notice I changed this by setting <code>route: heroes</code> in the code block below.</p>
<p>Now my endpoint is <code>api/heroes</code>.</p>
<pre><code class="language-json">// function.json
{
  &quot;disabled&quot;: false,
  &quot;bindings&quot;: [
    {
      &quot;authLevel&quot;: &quot;anonymous&quot;,
      &quot;type&quot;: &quot;httpTrigger&quot;,
      &quot;direction&quot;: &quot;in&quot;,
      &quot;name&quot;: &quot;req&quot;,
      &quot;methods&quot;: [&quot;get&quot;],
      &quot;route&quot;: &quot;heroes&quot;
    },
    {
      &quot;type&quot;: &quot;http&quot;,
      &quot;direction&quot;: &quot;out&quot;,
      &quot;name&quot;: &quot;res&quot;
    }
  ]
}
</code></pre>
<h2 id="whatsthepoint">What's the Point?</h2>
<p>Organizing your code and isolating logic only makes your life easier if it had some tangible positive effect, so let's explore that. When writing your next function for updating heroes, the function could look like the following code.</p>
<pre><code class="language-javascript">const { putHero } = require('../shared/hero.service');

module.exports = async function(context) {
  context.log('putHero: JavaScript HTTP trigger function processed a request.');
  await putHero(context);
};
</code></pre>
<p>Do you notice that it looks very similar to the function for getting heroes? There is a pattern forming, and that's a good thing. The big difference here is that the code is calling <code>putHero</code> in the <code>hero.service.js</code> module. Let's take a closer look at that.</p>
<p>The logic for updating the heroes is isolated. Isolation is one of the main jobs of the <code>hero.service.js</code>, along with the logic for getting the heroes.</p>
<p>Thinking forward, the logic for delete, insert, and any other operations also could go in this module and be exported for use in other functions. This makes it relatively simple to extend this structure to other actions and models.</p>
<pre><code class="language-javascript">// shared/hero.service.js
const { heroes: container } = require('./index').containers;

async function getHeroes(context) {
  // ...
}

async function putHero(context) {
  const { req, res } = context;
  const hero = {
    id: req.params.id,
    name: req.body.name,
    description: req.body.description
  };

  try {
    const { body } = await container.items.upsert(hero);
    res.status(200).json(body);
    context.log('Hero updated successfully!');
  } catch (error) {
    res.status(500).send(error);
  }
}
</code></pre>
<h2 id="moreserverless">More Serverless</h2>
<p>Share your interests, and as I write more posts on Serverless I'll keep them in mind! In the meantime here are those resources again, in case you want some <em>getting started</em> materials:</p>
<ul>
<li><a href="https://code.visualstudio.com/tutorials/functions-extension/getting-started?wt.mc_id=johnpapanet-blog-jopapa">Your first Azure Function with the VS Code Functions Extension</a></li>
<li><a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-overview?wt.mc_id=johnpapanet-blog-jopapa">Azure Functions Overview</a></li>
<li><a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference?wt.mc_id=johnpapanet-blog-jopapa">Developer Guide</a></li>
<li><a href="https://github.com/johnpapa/heroes-serverless?wt.mc_id=johnpapanet-blog-jopapa">Sample Code in a GitHub Repo</a></li>
<li><a href="https://docs.microsoft.com/en-us/azure/cosmos-db/sql-api-nodejs-get-started?wt.mc_id=johnpapanet-blog-jopapa">JavaScript SDK for Cosmos DB</a></li>
</ul>
<h2 id="creditandthanks">Credit and Thanks</h2>
<p>Thanks to <a href="https://twitter.com/_mhoeger">Marie Hoeger</a> for reviewing the content of this post and taking my feedback. You should definitely <a href="https://twitter.com/_mhoeger">follow Marie on Twitter</a>!</p>
]]></content:encoded></item></channel></rss>