<?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:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Christian Gonzalez on Medium]]></title>
        <description><![CDATA[Stories by Christian Gonzalez on Medium]]></description>
        <link>https://medium.com/@christiango?source=rss-f4ad0c0455ef------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*yUwOdZZy55nsS_3PflhPPQ.jpeg</url>
            <title>Stories by Christian Gonzalez on Medium</title>
            <link>https://medium.com/@christiango?source=rss-f4ad0c0455ef------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 30 May 2026 19:19:20 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@christiango/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Getting the most out of TypeScript’s type system]]></title>
            <link>https://medium.com/@christiango/getting-the-most-out-of-typescripts-type-system-e6e9fc643216?source=rss-f4ad0c0455ef------2</link>
            <guid isPermaLink="false">https://medium.com/p/e6e9fc643216</guid>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Christian Gonzalez]]></dc:creator>
            <pubDate>Wed, 15 Apr 2020 20:01:35 GMT</pubDate>
            <atom:updated>2020-04-15T20:09:57.784Z</atom:updated>
            <content:encoded><![CDATA[<p>TypeScript provides static analysis to help developers write large applications with many contributors. One of the best ways to get the most out of TypeScript is to enable the --strict <a href="https://www.typescriptlang.org/docs/handbook/compiler-options.html">compiler option</a>, which enables a bunch of optional checks to catch common bugs. In this article, we’ll dive deeper into how your team can get the most out of --strict mode by diving deeper into the TypeScript type system.</p><h4>Why does any of this matter?</h4><p>Having worked on a few large scale applications over my career, one of the most common runtime errors I have seen is something along the lines of Uncaught TypeError: Cannot read property &#39;foo&#39; of undefined. One of the nice features enabled by TypeScript --strict mode is that it also enables all the checks that come with the --strictNullCheck option, which will result in compiler errors anytime you try to access a property on an object that may be null or undefined. Here’s an example:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/413e6150dd77924673c734624724e169/href">https://medium.com/media/413e6150dd77924673c734624724e169/href</a></iframe><ul><li>The getStringLengthError function would result in a compiler error when --strictNullChecks are enabled, but no error when the checks are off, which could lead to runtime errors.</li><li>The second function, getStringLengthNoError, demonstrates that checking maybeUndefined is not undefined before trying to access the length property, doesn’t result in an error. Once we make that undefined check, TypeScript knows the type of maybeUndefined is no longer string | undefined, but instead a string in the context of the if block.</li><li>The process by which we introduce a type check here to reduce the possible types of a variable in TypeScript is commonly referred to as “narrowing”.</li></ul><p>While --strict mode does make it harder for us to write code that results in runtime type errors, it does not completely eliminate them.</p><h4>TypeScript is not C#</h4><p>One of the things that often confuses experienced developers when they first start using TypeScript is how it’s type system differs from that of other languages. TypeScript’s type system is very powerful (more on that later), but it has one key difference from other languages: <strong>the types do not exist at runtime</strong>. One of TypeScript’s key features is that TypeScript programs can be translated into JavaScript code that can be run in a browser. The <a href="https://www.typescriptlang.org/play/">TypeScript playground</a> is a great place where you can see what JavaScript is generated for a given TypeScript program. In the example below, all evidence of our AwesomeInterface is gone in the generated JavaScript code.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ff057c25f86daca8122c465dbca2b435/href">https://medium.com/media/ff057c25f86daca8122c465dbca2b435/href</a></iframe><p>The fact that types do not exist at runtime is very important to know. One particular source of confusion is the existence of the as keyword in both TypeScript and C#. In C#, the <a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/type-testing-and-cast#as-operator">as operator</a> tries to do a type conversion and returns null when the conversion is not possible. This causes many developers coming from a C# to expect the code snippet below to only enter the if block if arg is an implementation of AwesomeInterface. If you take a look at the generated code below, you can see the as keyword simply gets compiled away, causing us to go into the if block for any value of arg that is not falsy!</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d7b22d1d6fea74adae963447aff01e56/href">https://medium.com/media/d7b22d1d6fea74adae963447aff01e56/href</a></iframe><p>Type casting via as AwesomeInterfaceor &lt;AwesomeInterface&gt; in TypeScript simply tells the compiler to treat the variable as if it were an AwesomeInterface rather than doing any work to see if the object actually has the shape defined by AwesomeInterface. Type casts can sometimes be helpful when you have more context than the TypeScript compiler in a certain situation, but in general you should avoid using type casts in favor of other techniques we will cover in this article.</p><h4>Ok, so how do I check the type of something at runtime?</h4><p>There are many scenarios where you may want to identify the type of something at runtime in a TypeScript application. One example could be you have a function that takes in an argument that could have multiple types and you want to have different behavior for each of these types. Take a look at the example below, where we define a hypothetical function that takes in an argument that can be a number, string, or number array.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1d0a2fd88c721795bae904f3491a6666/href">https://medium.com/media/1d0a2fd88c721795bae904f3491a6666/href</a></iframe><p>In this example, we used type “narrowing” to determine what the exact type of arg is before using the value.</p><ul><li>The first if statement uses the typeof operator to check if the input is a string. This enables the compiler to know that the value of arg on line 3 is a string.</li><li>The second if statement uses the Array.isArray function to determine if arg is a number array.</li><li>By the time we get to line 10, if the type of arg was string or number[], we would have already returned. This means the TypeScript compiler knows the only possible type for argis number at this point, so we don’t to do an additional check here.</li></ul><p>This technique also works for more complex types as well. Consider the example below where we have a function that takes in an argument of type Person or CityLocation.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4121639998732f0944f7b127fb56fc8c/href">https://medium.com/media/4121639998732f0944f7b127fb56fc8c/href</a></iframe><p>Here we use the in keyword to check if arg has a firstName property. If it does, we know that it must be a Person type since CityLocation has no firstName property.</p><p>There is a caveat with this kind of a check that can be demonstrated with this sample code.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c8cba94f3fbdd86fdc9ed989ab88598e/href">https://medium.com/media/c8cba94f3fbdd86fdc9ed989ab88598e/href</a></iframe><p>In this example myLocation implements the CityLocation contract, but also adds an additional firstName property. In this case, our code would see that the object passed in has a firstName property on it and goes down the path for an argument of the Person type, even though myLocation does not have the lastName property we’d expect a Person type to have. This could be addressed by also including a check for &#39;lastName&#39; in arg.</p><p>As another example, let’s change the type of CityLocation from an interface to a class. When the type of an object is a class, we have the option of using instanceof keyword in addition to the is operator.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ff0db600192dab5e367aeafdcafbb504/href">https://medium.com/media/ff0db600192dab5e367aeafdcafbb504/href</a></iframe><h4>Can I trust the inputs to my function are what they say they are?</h4><p>One thing we are taking for granted in the examples shown previously is that we trust the input values we are working with at runtime actually match the type signature declaration at compile time. That is, we are trusting that a function with the signature (param: string | number) always is called with an argument that is of type string or number. Often times, this assumption holds. For example, if your APIs are only called by other TypeScript code using — strictmode, then this is a safe assumption, since the callers would get a compiler error if they violated the type signature (assuming they didn’t use a type cast).</p><p>However, there are many situations where you cannot trust the data you are being given has a particular shape. One example would be data obtained from an API call or read from local storage.</p><p>Let’s say we have a function that we expect to provide a string argument, but it is possible the caller will give us a non-string value. We certainly don’t want our code to throw an exception when we are given an unexpected input value. The temptation here may be to define this value with the any type, but that would cause us to lose all type safety. To demonstrate why any is a bad fit, look at the example below.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3f3f9a8691a5db65ab1205f9918ee202/href">https://medium.com/media/3f3f9a8691a5db65ab1205f9918ee202/href</a></iframe><p>Despite the fact that this example is certainly going to throw an exception, the compiler does not give us an error due to the fact that x has the type of any.</p><p>For these kinds of scenarios, the TypeScript language has the unknown keyword. The TypeScript team <a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html#new-unknown-top-type">refers </a>to unknown as the type-safe counter part to any. In practice, this means that TypeScript will make sure that you have done the right type assertions before accessing any properties on a variable of unknown type. Below we have an example of a getLength function that is expected to be called with an array or string, but we can’t know for sure.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c3b33467b3e3a146c9912cfbcd89f1bd/href">https://medium.com/media/c3b33467b3e3a146c9912cfbcd89f1bd/href</a></iframe><p>The use of unknown ensures that we do not call the length property on input unless we have narrowed it down to a type that is known to have a length property on it.</p><h4>Tips and tricks for type system pros</h4><p>Now that you are motivated to and using the any and as keywords, here are some concepts you may find useful in your codebases.</p><p><a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html#using-type-predicates">Type predicates</a> enable you to avoid duplicating type checks throughout a codebase.</p><p><a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html#discriminated-unions">Discriminated unions</a> are a useful pattern for defining union types that can be differentiated easily at runtime.</p><p><a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html#exhaustiveness-checking">Exhaustive switch statements</a> are useful for ensuring that all possible values for a union type are covered by your code.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e6e9fc643216" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Being effective while working from home]]></title>
            <link>https://medium.com/@christiango/being-effective-while-working-from-home-4165df64a0d2?source=rss-f4ad0c0455ef------2</link>
            <guid isPermaLink="false">https://medium.com/p/4165df64a0d2</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[remote-working]]></category>
            <category><![CDATA[software-engineering]]></category>
            <dc:creator><![CDATA[Christian Gonzalez]]></dc:creator>
            <pubDate>Thu, 05 Mar 2020 19:03:21 GMT</pubDate>
            <atom:updated>2020-03-05T19:03:21.932Z</atom:updated>
            <content:encoded><![CDATA[<p>I work remotely out of Miami, Florida as a Software engineer for Microsoft. Given the recent health concerns in the Seattle area, I wrote up some tips for my Redmond-based coworkers as many of them are working from home these days. Sharing this more broadly in case others find these tips helpful.</p><ol><li><strong>Define a location to be your work space </strong>— This one can be tough since many people live in apartments, but try to identify an area of your home where you will be able to focus. Define this area as your “work space” and try not to use this area for other activities like eating, watching TV, or browsing social media.</li><li><strong>Set expectations for those around you </strong>— Often times when working from home, you will be surrounded by other people. Try to make it clear to other folks when you are working and set expectations for when you can be interrupted. For deep focus activities, like coding, folks who aren’t in the tech industry have a hard time understanding how disruptive an interruption could be. Try to have a conversation up front about your expectations when you are working from home. What worked well for me was to tell the folks around me to get a hold of me using asynchronous communication (text messages work really well for this), especially when I am on a call. This is more complicated if you have children in the house, so hopefully some of the parents reading this can share some tips specific to this scenario!</li><li><strong>Use your webcam </strong>— When calling into meetings while working remote use your webcam. It makes a huge difference. I also recommend having a good webcam and lighting where you will be working. I personally use the <a href="https://www.amazon.com/Logitech-C920S-Webcam-Privacy-Shutter/dp/B07K95WFWM/ref=nav_ya_signin?keywords=webcam&amp;qid=1583429562&amp;sr=8-3&amp;">Logitech C920 s</a> and a <a href="https://www.amazon.com/gp/product/B07H3NRJ7H/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&amp;psc=1">ring light</a>. Scott Hanselman has a great <a href="https://www.hanselman.com/blog/GoodBetterBestCreatingTheUltimateRemoteWorkerWebcamSetupOnABudget.aspx">writeup </a>about this that inspired my set up.</li><li><strong>The mic on your laptop is probably terrible </strong>— Some folks prefer to use headphones or a dedicated mic for better call quality. Most laptop microphones are typically highly directional so they don’t work well if you are not directly in front of the laptop. I personally use a <a href="https://www.amazon.com/Blue-Yeti-Premium-Recording-Streaming/dp/B07DTTGZ7M/ref=sr_1_2?keywords=yeti+mini&amp;qid=1583429858&amp;s=electronics&amp;sr=1-2">Blue Yeti Nano</a>.</li><li><strong>Take breaks and make sure to move around</strong> — It’s very easy to fall into the trap of doing deep work for several hours. I find it very helpful to intentionally take breaks to move around the house or neighborhood a bit. I also find disconnecting during work completely during lunch to be super helpful. I have a “no eating around my work computer” rule.</li><li><strong>Favor public asynchronous communication </strong>— This is something we typically should always be doing, but try to avoid direct IM for communication with others since it can be disruptive and doesn’t offer the transparency and inclusion we value at Microsoft. In general, I recommend using public <a href="https://products.office.com/en-us/microsoft-teams/group-chat-software?&amp;OCID=AID2000955_SEM_XTdEagAAAE3FRi0s:20200305190040:s&amp;msclkid=8ee9a8504bdf11f50a5ef631078cd60a&amp;ef_id=XTdEagAAAE3FRi0s:20200305190040:s">Teams</a> channel as your primary communication tool over email and direct IM.</li><li><strong>Avoid the temptation to do other work while on a video call </strong>— I found it super difficult to stay focused in meetings when I first started working remotely. I was often coding or checking emails. I eventually had to resort to the measure of moving my keyboard out of reach while I am on a Teams call. Turning on your webcam also has the nice side effect of keeping you honest.</li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4165df64a0d2" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The unexpected impact of dynamic imports on tree shaking]]></title>
            <link>https://medium.com/@christiango/the-unexpected-impact-of-dynamic-imports-on-tree-shaking-ddadeb135dd7?source=rss-f4ad0c0455ef------2</link>
            <guid isPermaLink="false">https://medium.com/p/ddadeb135dd7</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[web-performance]]></category>
            <category><![CDATA[webpack]]></category>
            <dc:creator><![CDATA[Christian Gonzalez]]></dc:creator>
            <pubDate>Tue, 17 Sep 2019 13:56:10 GMT</pubDate>
            <atom:updated>2020-09-17T22:01:47.444Z</atom:updated>
            <content:encoded><![CDATA[<p>We learned a lot from a recent investigation of a bundle size regression in one of the Office web applications. Here is a summary of our investigation in the hope that it will help others in their pursuit of improved application performance.</p><p>As part of a recent performance push, we decided to dive deeper into the dependency graph generated by <a href="https://github.com/webpack-contrib/webpack-bundle-analyzer">webpack-bundle-analyzer</a> to make sure that all the code in our main bundle was indeed required on the boot path. To our surprise, we discovered that a large portion of our bundle was taken up by an internal package @ms/office-web-platform. This package contains a lot of the common infrastructure shared by various Office web experiences, such as logging, authentication, and common utilities. Over time, this package has become quite large, but often times only a small percentage of the code in the package is on the critical boot path of an application. Upon closer inspection, it appeared as if tree shaking was not enabled at all for the package.</p><p>We first expected this to be a configuration issue, so we verified that @ms/office-web-platform was meeting the <a href="https://webpack.js.org/guides/tree-shaking/">tree-shaking</a> requirements. We made sure the package was exporting ECMA Script Modules, had a module entry in package.json, and properly set the sideEffects flag in package.json. We also confirmed that another application using @ms/office-web-platform was seeing the correct tree shaking behavior.</p><p>We then scanned the modules in our main bundle to find all the static imports of @ms/office-web-platform. We only found usages of the logger, with imports of the form:</p><pre>import { logger } from &#39;@ms/office-web-platform&#39;;</pre><p>This logging module is very small and does not have dependencies on many other modules. The @ms/office-web-platform package has a structure that is roughly like this:</p><pre>/lib<br>  /authentication<br>    auth.js<br>    index.js<br>  /telemetry<br>    index.js<br>    logger.js<br>  ...<br>index.js</pre><p>All index.js files simply re-export other modules. As an exercise, we tried changing the path of the imports from the root index.js file to instead be pointing at the /telemetry/index.js module. Our imports then look like this:</p><pre>import { logger } from &#39;@ms/office-web-platform/lib/telemetry&#39;;</pre><p>This change dramatically reduced the bundle size, which was great! However, this change would force us to take a dependency on the internal package structure of the @ms/office-web-platform package and there was a concern that this bundle would easily regress the next time some adds an import to something from the @ms/office-web-platform. We needed to understand what was actually going on here.</p><p>The webpack stats files weren’t providing us with any clues, so we went ahead and started removing imports and eventually got to a state where were able to get a minimal reproduction of the issue by removing all app code except for this:</p><pre>import { logger } from &#39;@ms/office-web-platform&#39;;<br>import { getAuthService } from &#39;./AuthService&#39;;</pre><pre>export function boot() {<br>  logger.loadFull();</pre><pre>return getAuthService();<br>}</pre><p>Removing either import in this case cause the bundle size to dramatically drop. We eventually went into getAuthServiceand started removing code until we saw the desired bundle output. We tracked the issue to this line of code ingetAuthService:</p><pre>// IMPORTANT: Dynamically load dependency on office-web-platform  <br>// package to ensure that it is not included inside initial app <br>// bundle. This method is not called on app boot up so delay loading <br>// makes sense.<br>const platform = await import(&#39;@ms/office-web-platform&#39;);</pre><p>This code had good intentions, it meant to delay load some code that isn’t needed on the initial render. When this line of code was first added we didn’t have any telemetry in the boot slice, so we didn’t have any code from @ms/office-web-platform in the main chunk. When we added logging to the main slice, we introduced a static import of the index.js module at the root of the @ms/office-web-platform. A static require isn&#39;t a problem since webpack tree shaking will only include the bits we care about, which we were able to confirm by removing the dynamic import. The problem comes with the dynamic import of that same index.js module.</p><pre>import(&#39;@ms/office-web-platform&#39;);</pre><p>When you dynamically import a module, it automatically makes that module ineligible for tree shaking. The result of the dynamic import is an object with all the exports of the module. Due to the dynamic nature of JavaScript, webpack can’t easily determine which exports will be used, so webpack can’t do any tree shaking. For more details on tree shaking behavior for dynamic imports, checkout this great <a href="https://github.com/webpack/webpack.js.org/issues/2684">description</a> from the webpack team.</p><p>This discovery revealed why we weren’t tree shaking the @ms/office-web-platform module, but it was still unclear why all of the code from that package was in the main slice rather than just the telemetry module we were statically importing. The spec for ECMA script modules defines that modules that can only be evaluated once, so we cannot evaluate the index.js module once in the boot slice and then once again later in the delay loaded slice. Since we have a static import @ms/office-web-platform/lib/index.js module in the boot path, we expect the evaluation of the index.js module to happen in the boot chunk. Since this exact index.js module is also required in a dynamic import, this module is no longer eligible for tree shaking, meaning we will pull in <strong>everything</strong> that is re-exported by that module in the boot slice!</p><p>The fix here was to switch all the dynamic imports of @ms/office-web-platform to be scoped to specific modules that were being required, meaning we would update our imports from import(&#39;@ms/office-web-platform&#39;) to import(&#39;@ms/office-web-platform/lib/expensiveModule&#39;)This has the downside of making the application dependent on the internal package structure of @ms/office-web-platform, meaning we would run into issues if the logger.js module was moved to different location in the package. In the end we felt this trade off worth making to improve our boot performance. Going forward, we are going to evaluate all our dynamic imports and ensure we are not pulling in too much code. We’re also considering splitting larger packages like @ms/office-web-platform into smaller modules so that we can go back to importing from the index.js file at the root of the module.</p><p><strong>Edit August 2020</strong>:</p><p>Since publishing this article, we recently moved to a different pattern for dynamic imports that does not cause dependencies on the internal package structure of an external package. Rather than having a reference import(&#39;@ms/office-web-platform/lib/expensiveModule&#39;) inside of our package, we create a module in the package consuming @ms/office-web-platform that has a static import to the expensive modules we need and dynamically import that module. For example, we would create a file officeWebPlatformLazy.js inside the package that wishes to delay load @ms/office-web-platform. The contents of officeWebPlatformLazy.js would look something like this:</p><pre>export{ expensiveModule } from &#39;@ms/office-web-platform&#39;;</pre><p>Now, we replace all the import(&#39;@ms/office-web-platform/lib/expensiveModule&#39;) statements with statements like import(&#39;../officeWebPlatformLazy&#39;). With this approach, we still get the expected bundle output, but removed the dependency on the internal structure of the external package @ms/office-web-platform.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ddadeb135dd7" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A new architecture for Word Online’s UX Platform]]></title>
            <link>https://medium.com/web-on-the-edge/a-new-architecture-for-word-onlines-ux-platform-196e04c7528a?source=rss-f4ad0c0455ef------2</link>
            <guid isPermaLink="false">https://medium.com/p/196e04c7528a</guid>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[react]]></category>
            <dc:creator><![CDATA[Christian Gonzalez]]></dc:creator>
            <pubDate>Thu, 06 Sep 2018 15:01:35 GMT</pubDate>
            <atom:updated>2018-09-06T15:01:35.789Z</atom:updated>
            <content:encoded><![CDATA[<p>As part of the effort to deliver refreshed visuals for Word Online, we decided to build a <a href="https://medium.com/web-on-the-edge/modernizing-word-onlines-ux-platform-df1050344e3a">new UX platform for Office Online</a> to improve the long-term engineering velocity of our team. This new UX platform would be influenced by industry best practices, even if it came at the cost of the platform being a bit more painful to integrate into our monolithic applications. We went into this project as if this were the beginning of an effort to rewrite Word Online from scratch. With this approach, we hoped to build a UX platform that was isolated, extensible, and reusable. While this approach would introduce short term pain as we had to refactor our existing application to introduce the right APIs for an isolated UX platform, we knew that this would pay off in the long run as we continue to modernize other parts of our applications.</p><h3>Building a standalone component</h3><p>To help us ensure that our new architecture was not influenced by the structure of the existing Office Online applications, we decided that we would build the UX platform as a standalone NPM package. This NPM package would live in a new git repository and it would have its own test application that would enable us to render parts of the UX platform in isolation. This contrasts with our existing UX platform, where things like the Ribbon can only be rendered inside an application like Word Online. The hope was that this test application would be a place where developers making UI changes could see their changes in seconds instead the minutes it takes with our current stack.</p><p>There was some initial concern here that this approach would make it more difficult for developers working on bug fixes to test their changes end to end. After all, there are some bugs in Word Online that only appear when the UX platform is integrated within the larger application. In practice, we found that this isolated test app enabled us to easily separate bugs in the UX platform from bugs in the integration of the UX platform into an Office Online application. We also invested in tooling to enable developers to be able to validate changes in the UX platform inside a larger application without deploying a new version of the NPM package. A side effect of this development approach is that we did not have Office Online specific implementation details inside the UX platform, which has enabled us to share our code with other web applications within Microsoft.</p><h3>Design considerations</h3><p>To fully understand the design decisions we made when building up a new UX platform, it is important to understand some of the functionality we need to support in our applications. While our initial UX platform rewrite was only targeting the Ribbon, we plan to eventually port all our UX surfaces to React and TypeScript. It was very important for us to have a forward looking mindset here to enable us to scale out to more developers as the project matured.</p><h4>Responsive layout</h4><p>The Single Line Ribbon has a responsive design where controls can be rendered in an overflow menu to fit in narrower browser windows. This means we need to support rendering any control type in an overflow menu. We also needed to figure out a clean way for application teams to author the contents of their Ribbons and order in which controls go into an overflow. The implementation of Ribbon scaling was actually one of the more challenging parts of this rewrite and likely merits a blog post of its own.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iuiokR5LDQuKXuEwDh3ISA.gif" /><figcaption>Ribbon Scaling</figcaption></figure><h4>Tell Me</h4><p>Another interesting aspect of our UX platform is the “Tell Me” control. This is a feature that enables users to search for a command in Word Online. The Tell Me control needs to be able to query for all controls in the Ribbon to determine what results should be presented to the user. The Tell Me control was implemented years after our legacy Script# UX platform, which resulted in some clunky mechanisms for interacting with the Ribbon to identify and invoke commands. We wanted to improve the architecture in the new UX platform to ensure we were exposing the right APIs from our UX platform to prevent tight coupling between the Ribbon and Tell Me code.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZQigMzqrPybJL5bLzZluLA.gif" /><figcaption>Tell Me Control</figcaption></figure><h4>Add Ins</h4><p>Office Online’s extensibility platform allows for third party developers to develop features and have their own buttons in the Ribbon. Like “Tell Me”, this functionality came to Word Online a long time after the initial implementation of the UX platform. The legacy Ribbon was originally built under the assumption that all controls could be statically defined at build time. We did not have APIs for adding or removing controls at run time, so this meant that we had to write new code for add ins to support this scenario rather than leveraging the same mechanism for constructing the first party controls in the Ribbon. It was a goal of the rewrite to consolidate the ways in which controls are added to the Ribbon.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ImvNAGINHIzB-mR0OQO1XQ.png" /><figcaption>Pickit Images is an example of a third party extension that adds a Ribbon control at run time</figcaption></figure><h4>Synchronizing state across multiple UI surfaces</h4><p>Controls that appear in the Ribbon might also appear in other UI surfaces, such as context menus, floaties, and Tell Me search results. Many of these controls also have some state associated with them. An example of this can be seen with “toggle buttons” like the “bold” button in Word Online. Whenever the user’s selection contains bold text, the control has a darker background color than it does when the selection does not contain bolded text.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vGFtyYbMy_L24qmpxYC01Q.gif" /><figcaption>Bold toggle state updating with changes in the user’s selection</figcaption></figure><p>This state needs to be consistent across all the UI surfaces in which the “bold” button appears. Today, each of these UI surfaces has its own “bold” button whose state needs to be kept up to date, resulting in each application having code that needs to know about all these UI surfaces. For the new UX platform, we wanted to eliminate this duplication and reduce some of this coupling between core application logic and the UX platform.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Oi84eUm7Nr8RroPODNsMxA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/482/1*DSCfa1KA3f3Goja8boc5TA.png" /><figcaption>The various commanding surfaces where the bold command is available</figcaption></figure><h3>The UX Store</h3><p>One of the key design decisions we made was to introduce the concept of a “UX Store”. Each control in our UI would have an associated JavaScript object known as a “control model” that represents all the metadata about that control. This includes things like the icon, label text, and tooltip for the control. The control models would also include any state that a control may have, such as the “toggled” state of the bold button. These models would not contain details about how a control should appear, enabling us to have a single model for a control that can be shared across UI surfaces.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/070853bc37fa010e042f43c451ef8680/href">https://medium.com/media/070853bc37fa010e042f43c451ef8680/href</a></iframe><p>The UX store would also have the definitions of the Ribbon contents for a given application. This is where we would define the controls that would appear in each Ribbon tab, as well as specifying the order in which controls would be dropped into the overflow menu as the window width decreases.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e742f889715babb1f74fef27eb07e6ef/href">https://medium.com/media/e742f889715babb1f74fef27eb07e6ef/href</a></iframe><p>The UX store was implemented using Redux. We had actually written three versions of the UX store using various open source state management libraries. We wrote one version using <a href="https://reactjs.org/docs/state-and-lifecycle.html">React’s setState API</a>, another using <a href="https://redux.js.org/">Redux</a>, and another version using <a href="https://mobx.js.org/">MobX</a>. We were actually very happy with all three versions of the store and I think we would have been successful with any of these approaches. We decided against React setState because we did not want our UX store to be React-specific and we liked how cleanly our Redux and MobX implementations separated our state from the React components. We ended up choosing Redux because we really liked the organization of the store into actions/reducers/selectors. We also liked working with immutable data structures, since we were easily able to leverage <a href="https://github.com/reduxjs/reselect">reselect</a> and <a href="https://reactjs.org/docs/react-api.html#reactpurecomponent">React Pure Components</a> to get great update performance for our UI.</p><h3>App Integration</h3><p>To ensure that we were creating a UX platform that was truly a standalone component, we built up the majority of the UX store well before we ever tried to integrate it into the existing Word Online application. The extraction of the UX platform into an external NPM package forced us to come up with a well-defined API for communication with the UX platform. This API needed to work across all Office Online applications, not just Word Online.</p><p>There is a very large set of interactions that need to happen between the UX platform and the application, but we can break it down into two large categories.</p><h4>Communication from UX platform to the application</h4><p>The first category is communication from the UX platform to the application. This includes the scenario where the user clicks on the bold button in the Ribbon and the application needs to respond to that by updating the formatting of the user’s selection.</p><p>The application is responsible for registering a function, known as the command handler, that will be invoked whenever the user executes a Ribbon command. When the user interacts with a control in the Ribbon, the command handler is invoked with an object that contains information about the command that was just invoked. This payload contains the name of the command that was invoked (e.g. “Bold”) as well as any other data associated with this control execution. For toggle buttons, this will include the current toggle state of the control. For things like the font name drop down, this will include the name of the font that the user selected. The application then uses the data in the payload to execute the requested user action within the command handler.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1008/1*9UXaMgWw8KffkqznIHFuUg.png" /><figcaption>Data flow from UX platform to Application</figcaption></figure><h4>Communication from the application to the UX Platform</h4><p>There are also scenarios when the application needs to update some state in the UX platform. An example of this is when a user invokes a keyboard shortcut to apply bold formatting to the current selection. In this scenario, the application needs to update the “toggled” state of the bold button in the Ribbon to reflect the new state of the user’s selection in the document.</p><p>The UX platform exposes an API to enable the application to update the Ribbon in response to a user action. These APIs are mostly just exposing a subset of the Redux actions available in the UX store. The platform has APIs like ‘setButtonToggleState’ which enables the application to set the toggle state of the bold button when the user’s selection changes. These APIs would make the appropriate updates in the UX store and then trigger a rerender of the Ribbon with the React props derived from the updated UX state.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1008/1*wLXcHZ8p69OIjovlZfFdQw.png" /><figcaption>Data flow from Application to UX platform</figcaption></figure><h3>Looking back</h3><p>We took a lot of inspiration from the open source community when building up our UX platform. This was most evident in our decision to create the UX platform as a standalone NPM package. This packaging strategy ended up being a forcing function for us to implement good contracts between our application and UX platform, which we expect will make our code easier to maintain going forward. The biggest difference from our previous UX platform architecture was the creation of a UX store. This design ended up solving many of the pain points of our existing UX platform.</p><ul><li>We are now able to use the same APIs for the insertion of first party controls and third party controls.</li><li>We have eliminated the state duplication for controls that appear in multiple UI surfaces, reducing the amount of work we will have to do as we convert the remainder of our UI surfaces to React.</li><li>We now have a nice set of APIs that the Tell Me control can interact with to get control metadata rather than digging into implementation details of the Ribbon.</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=196e04c7528a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/web-on-the-edge/a-new-architecture-for-word-onlines-ux-platform-196e04c7528a">A new architecture for Word Online’s UX Platform</a> was originally published in <a href="https://medium.com/web-on-the-edge">Web Dev @ Microsoft</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Modernizing Word Online’s UX platform]]></title>
            <link>https://medium.com/web-on-the-edge/modernizing-word-onlines-ux-platform-df1050344e3a?source=rss-f4ad0c0455ef------2</link>
            <guid isPermaLink="false">https://medium.com/p/df1050344e3a</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Christian Gonzalez]]></dc:creator>
            <pubDate>Wed, 29 Aug 2018 15:39:42 GMT</pubDate>
            <atom:updated>2018-09-06T15:05:27.054Z</atom:updated>
            <content:encoded><![CDATA[<h3>Introduction</h3><p>Early in 2017, our design team proposed a pretty significant visual refresh of Word Online. While many of these changes were quick CSS tweaks to change some colors and padding, there were also some significant visual updates that would require core changes to the code in our UX framework. The most prominent of these visual changes were targeted at the primary commanding surface at the top of Word Online, commonly referred to as the <a href="https://en.wikipedia.org/wiki/Ribbon_(computing)">Ribbon</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iQ_Y-cu3-mbSqEuWfPdoTw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iTje9iWAEYsLtvUBFWr7AQ.png" /><figcaption>Current visuals on the left. New visuals on the right.</figcaption></figure><p>The goal of this visual update was to allocate more visual real estate to the user’s document by moving from a “Multi Line Ribbon” to a “Single Line Ribbon”. In order to make all these commands fit into a single row, we needed to be able to render some of the less frequently used commands in an “overflow menu”. This is not a behavior that we supported in the Multi Line Ribbon, so we would have to do some work in our UX platform to ensure we could support rendering all our control types in menus.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GjVwBfl7RM1HEiOWxHV3TA.png" /><figcaption>Overflow menu gives access to less frequently used commands.</figcaption></figure><p>The Single Line Ribbon was also designed to be more responsive than the Multi Line Ribbon. As the window width decreases, commands will move from the top level into the overflow well.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iuiokR5LDQuKXuEwDh3ISA.gif" /></figure><h3>Time for a rewrite?</h3><p>The Word Online codebase is over 11 years old. At that time, the JavaScript ecosystem was also not as mature it as it is today, with a growing sentiment that raw JavaScript did not scale to large applications. This led to a rise in the use of Script# (a transpiler from C# to JavaScript) for large web applications within Microsoft. Script# was a vital tool that helped our code base scale to our growing engineering team and played a key role in getting us to the point where we are able to confidently ship new versions of Word Online multiple times per week. Over the past few years <a href="https://www.typescriptlang.org/">TypeScript </a>has emerged as Microsoft’s public facing solution to large scale JavaScript development. This has led to Script# usage declining across the company, as the developer experience offered in TypeScript is far superior to that experienced by Script# developers.</p><p>On the Office Online team, we have been trying to write some new features in TypeScript to help improve our engineering velocity. This approach proved to be very successful for isolated features, but it had the tendency of being a very frustrating experience for developers that were working on features that tightly integrated with the large Script# code base. It became clear that we would have to eventually rewrite a core piece of Word Online in TypeScript to reduce the friction for developers trying to write new features in TypeScript.</p><p>The proposed updates to the Word Online Ribbon would require extensive refactoring of the UX platform in order to enable the new responsive design, making it an ideal candidate for a rewrite on a more modern tech stack. After some initial prototyping, it became pretty clear that taking the additional time now to rewrite our UX platform would have significant long term improvements to the workflow of our development team. We decided that we would write the Single Line Ribbon from scratch in TypeScript. To make sure we were able to deliver the UX refresh in a timely fashion, we would not rewrite the entire UX platform at this time and instead just focus on rewriting the Ribbon. This meant we would still need to support the Multi Line Ribbon and other UX surfaces from our existing UX platform, such as context menus and task panes, alongside the new UX platform.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*L5iKro97GucgqmkEn-Arcw.jpeg" /><figcaption>The parts outlined in red would be in scope of the rewrite, the parts in green would not be rewritten</figcaption></figure><h3>Building a new UX platform</h3><p>Since many teams at Microsoft were already using TypeScript, we saw this as a great opportunity to connect with other web app teams to learn from their experiences. We reached out to our friends on the Outlook Web team, who at the time had just started an effort to move a significant portion of their Script# code base to TypeScript. During these conversations we learned that they, like many other popular web applications, were using <a href="https://reactjs.org/">React</a> for their user interfaces. Our initial prototype of the Single Line Ribbon was written in React, so we were very eager to use some of the components that they had built for our real implementation. After getting more details on Outlook’s UX platform, we found out Outlook wasn’t the only team at Microsoft using React and that many teams had started building their app using components from a Microsoft owned open source library called <a href="https://developer.microsoft.com/en-us/fabric#/components">Fabric React</a>.</p><p>We started to build the new Ribbon on top of Fabric React, enabling us to reduce overall development time by leveraging the components that other teams at Microsoft had already contributed to the project. We even added some new components to the project that are now being used in other products of Microsoft. Overall, we were amazed to see how the open source mindset around Fabric React enabled us to collaborate with product teams at Microsoft that were outside of the Office organization.</p><p>The move to TypeScript made it much easier for us to leverage open source software, enabling us to spend more time writing product code and lest time writing code for build tools and general infrastructure. In addition to React, we ended up leveraging popular open source libraries like <a href="https://redux.js.org/">Redux</a>, <a href="https://webpack.js.org/">Webpack</a>, and <a href="https://jestjs.io/">Jest</a> to provide a modern development experience to our engineering team.</p><p>After a year of hard work, we ended up being very happy with our decision to build up a new UX platform. This new UX platform has enabled to deliver features that leveraged modern browser functionality, such as the use of SVGs to deliver more crisp looking icons on the new UX platform.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/642/1*E5LcWeAJ9c-do0SM3n7RTg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/786/1*goleiO4y-TIqyA2ihS5pjg.png" /><figcaption>Comparison of PNG (left) vs SVG (right) icons on high DPI screens</figcaption></figure><p>The rewrite has already had the anticipated impact on developer efficiency and our ability to write more features in Typescript. We will be leveraging the efficiency of the new platform to respond to user feedback and continue to improve the experience. The move to a more modern platform also had some surprising effects, as we saw it encourage us to work more closely with other web app teams within Microsoft and in the broader open source community.</p><h3>Try it out today!</h3><p>The new visuals are enabled by default for Word documents hosted on OneDrive. Please try it out today and let us know your thoughts on the new experience by leaving <a href="https://support.office.com/en-us/article/how-do-i-give-feedback-on-microsoft-office-2b102d44-b43f-4dd2-9ff4-23cf144cfb11#platform=Office_Online">feedback in the app</a>!</p><p>This is just an introduction to the work we’ve done over the past year. We’ll be publishing some more detailed articles on our architecture and some of the work we did to improve the performance of our UX platform. Feel free to reach out on <a href="https://twitter.com/christiango">twitter</a> with suggestions on what you’d like to hear more about in future blog posts!</p><ul><li><a href="https://medium.com/@christiango/a-new-architecture-for-word-onlines-ux-platform-196e04c7528a">A new architecture for Word Online’s UX Platform</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=df1050344e3a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/web-on-the-edge/modernizing-word-onlines-ux-platform-df1050344e3a">Modernizing Word Online’s UX platform</a> was originally published in <a href="https://medium.com/web-on-the-edge">Web Dev @ Microsoft</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Thinking in TypeScript]]></title>
            <link>https://medium.com/web-on-the-edge/thinking-in-typescript-cb7f8a6434c0?source=rss-f4ad0c0455ef------2</link>
            <guid isPermaLink="false">https://medium.com/p/cb7f8a6434c0</guid>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Christian Gonzalez]]></dc:creator>
            <pubDate>Tue, 19 Sep 2017 22:52:23 GMT</pubDate>
            <atom:updated>2018-09-03T15:31:14.505Z</atom:updated>
            <content:encoded><![CDATA[<p>On the Office Online team, we regularly hire experienced engineers that have never worked on large scale web applications. As a result, we have a large number of engineers with strong backgrounds in languages like C# and Java learning how to write code in TypeScript for the first time. This transition comes naturally to most engineers, as some of the syntax may feel very familiar to C# and Java developers, but I think there is a lot to be gained from spending some time to learn how to leverage some of the unique capabilities of the language. This blog post will focus on some of the tips we’ve often found ourselves sharing in code reviews for developers that are new to TypeScript. I hope you find them helpful!</p><h4>You might not need a class</h4><p>Developers with a background in Object Oriented programming languages are used to encapsulating code within classes. An example we see regularly from new developers is the creation of utility classes that contains some static methods. Consider this example:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8d5778636ae122387e549fb51353f49a/href">https://medium.com/media/8d5778636ae122387e549fb51353f49a/href</a></iframe><p>While this is a perfectly reasonable way to organize your code, you could instead create a module that exports a set of utility functions:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/58fcbde33f325592c832409cf96b89fc/href">https://medium.com/media/58fcbde33f325592c832409cf96b89fc/href</a></iframe><p>While it is nice that the utility function is less verbose and generates less JavaScript when transpiled to ES5, this isn’t the primary reason why we prefer to use functions over classes in many situations. By favoring functions over classes, developers will naturally be writing code that adheres to the principle of <a href="https://en.wikipedia.org/wiki/Composition_over_inheritance">Composition over Inheritance</a>, which we’ve found makes it easier for us to write components that are testable and loosely coupled.</p><h4>An interface might not be what you expect it to be</h4><p>A common source of confusion for developers new to TypeScript is the concept of interfaces. Developers coming from a C# or Java background are familiar with the concept of interfaces used in a context like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/75e015d5277830d2a4d2642a92913613/href">https://medium.com/media/75e015d5277830d2a4d2642a92913613/href</a></iframe><p>While this is perfectly valid TypeScript, we rarely ever write code that looks like this inside the Office Online codebase. If you read the <a href="https://www.typescriptlang.org/docs/handbook/interfaces.html">TypeScript documentation for interfaces</a>, you’ll see them described as a way to define the types of a JavaScript object rather than something that should be implemented by a class. This means we could actually write code that looks like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b012bd77299953ddf99b840ca38e9415/href">https://medium.com/media/b012bd77299953ddf99b840ca38e9415/href</a></iframe><p>Now, this code is fundamentally different than the code in the previous example. The prior example created an instance of a class, which has a constructor and could also have methods, and assigned it to a person variable. The second example simply created a plain JavaScript object and assigned it to the person variable. When following the second approach, developers will typically use <a href="https://en.wikipedia.org/wiki/Pure_function">pure functions</a> to manipulate these plain JavaScript objects rather than having methods to manipulate the state contained within the person object. This approach allows for a clean separation of data and the code that manipulates data, which is something I’ve found makes code easier to reason about and unit test.</p><p>You may have noticed that these first two guidelines have recommended that you avoid using classes. While I personally prefer plain JavaScript objects manipulated by pure functions over classes with methods, this does not mean I think you shouldn’t use classes at all in TypeScript. In fact, I actually encourage them to be used for things like stateful <a href="https://facebook.github.io/react/docs/components-and-props.html#functional-and-class-components">React components</a>. These recommendations are mostly about demonstrating the new possibilities a developer has for structuring their code when introduced to a language that has <a href="https://en.wikipedia.org/wiki/First-class_function">first-class functions</a>.</p><h4>The types don’t exist at run time</h4><p>The types provided by TypeScript allow some bugs to be identified through the static analysis performed by the compiler. TypeScript is ultimately transpiled into JavaScript that is executed by the browser. Since JavaScript does not have a type system as strong as the one provided by TypeScript, the type information from TypeScript code will be stripped from a program as a result of the transpilation process. The end result is that you do not have access to the types of an object at run time like you do in some other languages like C#.</p><p>While the inability to access type information at run time may seem like a deal-breaking constraint, TypeScript supports <a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html">Discriminated Unions</a> as a mechanism for differentiating objects of different types at run time. To better understand how discriminated unions work, let’s consider an application that displays a number to the user and supports a set of actions that manipulates that number.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4003f2419c1e3ee425860aafff1fd101/href">https://medium.com/media/4003f2419c1e3ee425860aafff1fd101/href</a></iframe><p>In this example, we have a function getNextState that takes in an Action and the current state and returns the next state. Action is a union type of the Add and Decrement interfaces. Both of these interfaces have a type property, referred to as the <em>discriminant</em>, that allows us to determine which Action type was passed in to the getNextState function.The TypeScript compiler is able to leverage this type property within each clause of the switch statement to narrow down the set of valid properties to just those that correspond to the interface with that type value. For example, the compiler knows that the action inside the ‘Add’ case has a numberToAdd property and it knows that any reference to numberToAdd inside of the ‘Decrement’ block is a compiler error. The use of a discriminant allows us to differentiate objects of different types at runtime while also providing us with stronger type checking and an improved intellisense experience. When discriminated unions are combined with <a href="https://github.com/Microsoft/TypeScript/wiki/What&#39;s-new-in-TypeScript#new---strict-master-option">TypeScript strict mode</a>, the compiler is able to do exhaustiveness checking on the switch statement inside the getNextState function, which is helpful to ensure that developers update that function as new Action types are added.</p><h4>Use undefined instead of null</h4><p>As Douglas Crockford has said many times, one of the annoying things in JavaScript is that it has two bottom values: null and undefined. Developers coming from other programming languages are probably familiar with the null keyword and are likely to favor the usage of the null keyword over undefined. While there is nothing wrong with this approach, there are often scenarios where a variable might have a value of undefined, such as optional parameters, for a function. This would result in variables that can have a real value, null, or undefined, which means developers need to remember to check for both null and undefined. Of course you can get around this by replacing instances of</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/219e0ab223813e4e8265e443d8039bbc/href">https://medium.com/media/219e0ab223813e4e8265e443d8039bbc/href</a></iframe><p>with</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4dbd24eb39cfe6295e803ddc202dd0ed/href">https://medium.com/media/4dbd24eb39cfe6295e803ddc202dd0ed/href</a></iframe><p>Since both null and undefined are falsy values. However, this approach won’t work if the type of foo also had valid falsy values (such as 0 for a number or “” for a string) that you don’t want to handle in the same fashion as null and undefined. As a result, we found it preferable on the Office Online team to avoid using null in our codebase, instead encouraging the use of undefined (almost) everywhere.</p><h4>Conclusions</h4><p>TypeScript has emerged as a powerful tool for writing large scale web applications. The static type checking provides familiarity to experienced programmers coming from languages like C# and Java without reducing the ability for your programs to leverage the large library of open source JavaScript libraries. Experienced developers should find the syntax of TypeScript to be very familiar, but I hope these tips help these developers reach out of their comfort zones to fully leverage the capabilities of the language.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cb7f8a6434c0" width="1" height="1" alt=""><hr><p><a href="https://medium.com/web-on-the-edge/thinking-in-typescript-cb7f8a6434c0">Thinking in TypeScript</a> was originally published in <a href="https://medium.com/web-on-the-edge">Web Dev @ Microsoft</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Performance gains from switching to Closure Compiler]]></title>
            <link>https://medium.com/web-on-the-edge/performance-gains-from-switching-to-closure-compiler-8b97b7e434e5?source=rss-f4ad0c0455ef------2</link>
            <guid isPermaLink="false">https://medium.com/p/8b97b7e434e5</guid>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Christian Gonzalez]]></dc:creator>
            <pubDate>Mon, 15 May 2017 08:31:34 GMT</pubDate>
            <atom:updated>2017-05-15T08:31:34.414Z</atom:updated>
            <content:encoded><![CDATA[<p>On the Office Online team, we’re constantly looking for ways to improve the boot times of our applications. One of the factors that directly impacts the time it takes for these applications to boot is the raw size of the JavaScript files required to boot the page and provide basic editing functionality. By reducing the overall size of our critical JavaScript files, we can reduce the amount of time the browser spends downloading and parsing code.</p><p>One way we’ve achieved this is by <a href="https://en.wikipedia.org/wiki/Minification_(programming)">minifying</a> all the JavaScript we send down to the browser. At first we used <a href="https://www.nuget.org/packages/AjaxMin/">Microsoft’s Ajax Minifier</a>, which reduces the size of JavaScript files by performing optimizations such as removing whitespace and renaming local variables to have shorter names. We then implemented a tool that would leverage knowledge of the entire application to rename functions and remove unused functions from the output JavaScript. This tool worked well for many years, but it was tightly coupled to our internal build system and eventually was no longer being actively maintained. This caused us to look to the open source community for a more modern solution for JavaScript minification.</p><p>We recently replaced our internal minification tool with <a href="https://developers.google.com/closure/compiler/docs/compilation_levels">Closure Compiler</a>. Like our previous minification tool, Closure Compiler in <a href="https://developers.google.com/closure/compiler/docs/compilation_levels">Advanced Mode</a> supports global function renaming and dead code removal. It also has additional features like function inlining and dynamic moving of code between JavaScript files. When running our JavaScript code through Closure Compiler, the size of our main JavaScript file after Gzip compression was 15% smaller than it was with our old minification tool. We found that most of these file size savings came from the compiler’s ability to move code from our main JavaScript file into one of our “delay-loaded” JavaScript files that were also fed as inputs to the compiler.</p><p>The JavaScript download time isn’t the only factor that contributes to the boot time of our applications. The browser also needs to parse the JavaScript, run our app initialization code, and render content once available. To get a better understanding of how these file size reductions would translate into boot time improvements, we ran a controlled A/B test in production for Word Online users. In the control group of this experiment, users were served JavaScript files that come from our old minification pipeline. In the treatment group, users saw JavaScript files that were minified with Closure Compiler. Our experiment showed that there was an 8% improvement in boot time across all browsers. We also saw that the “gap to interactive”, which measures the time between the document being visible to the user to the time it is editable, improved by 14% across all browsers.</p><p>After analyzing the results of this experiment in Word Online, we started moving other Office Online applications to also use Closure Compiler and saw similar performance improvements. We also did some work to make our JavaScript exception logging code compatible with Closure Compiler by creating a tool that turns minified method names in a stack trace back into their human readable form. For more info on that, check out this <a href="https://medium.com/web-on-the-edge/deminifying-javascript-call-stacks-ef600d01bd4a">blog post</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8b97b7e434e5" width="1" height="1" alt=""><hr><p><a href="https://medium.com/web-on-the-edge/performance-gains-from-switching-to-closure-compiler-8b97b7e434e5">Performance gains from switching to Closure Compiler</a> was originally published in <a href="https://medium.com/web-on-the-edge">Web Dev @ Microsoft</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Deminifying JavaScript call stacks]]></title>
            <link>https://medium.com/web-on-the-edge/deminifying-javascript-call-stacks-ef600d01bd4a?source=rss-f4ad0c0455ef------2</link>
            <guid isPermaLink="false">https://medium.com/p/ef600d01bd4a</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Christian Gonzalez]]></dc:creator>
            <pubDate>Thu, 30 Mar 2017 22:12:27 GMT</pubDate>
            <atom:updated>2017-06-17T23:51:11.744Z</atom:updated>
            <content:encoded><![CDATA[<p>When deploying a new version of Office Online, we look at several pieces of telemetry to help determine the overall health of an individual application. One of these signals is the rate at which our users are experiencing unhanded JavaScript exceptions. We attempt to group these exceptions based on the value of the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Stack">stack</a> property on the error object to determine how often a particular exception is occurring.</p><p>Since our JavaScript is aggressively minified with the <a href="https://github.com/google/closure-compiler">closure compiler</a>, it can be a bit difficult to track down the code that caused the exception since the method names have all been changed in an effort to reduce the number of bytes sent over the wire.</p><p>As an example, consider this JavaScript snippet which will cause a crash when the user clicks a button on the page.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f217bfa0c84fcc68a88aef99564fb58c/href">https://medium.com/media/f217bfa0c84fcc68a88aef99564fb58c/href</a></iframe><p>After running it through a minifier, the output becomes something like the snippet below. This is pretty printed for clarity. In production you’d likely see all the line breaks and spaces stripped out.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/10267fb3c7ec0dd1535b0a1fe20135e5/href">https://medium.com/media/10267fb3c7ec0dd1535b0a1fe20135e5/href</a></iframe><p>I created a <a href="https://jsfiddle.net/5y87kdwg/1/">jsfiddle</a> hosting this script and some basic HTML to allow the user to force a crash on the page by calling the ‘causeCrash’ function. When the user clicks the “crash button”, the stack property on the error object passed to the window.onerror handler will be something like this:</p><pre>TypeError: Cannot read property &#39;length&#39; of undefined<br>    at https://fiddle.jshell.net/_display/:62:26<br>    at t (https://fiddle.jshell.net/_display/:63:10)<br>    at e (https://fiddle.jshell.net/_display/:56:17)<br>    at n (https://fiddle.jshell.net/_display/:52:17)<br>    at causeCrash (https://fiddle.jshell.net/_display/:67:8)<br>    at HTMLButtonElement.&lt;anonymous&gt; (https://fiddle.jshell.net/_display/:70:9)</pre><p>It’s not very easy to determine what happened from this stack trace alone. In an effort to improve our app’s reliability, we developed an <a href="https://github.com/Microsoft/sourcemap-toolkit">open source .NET library</a> that parses the stack string and determines the original function names for the code that appears in the stack trace. This tool works with any code generated by a JavaScript minifier that produces <a href="https://www.html5rocks.com/en/tutorials/developertools/sourcemaps/">source maps</a>, including Closure Compiler, UglifyJS2 and AjaxMin.</p><p>For each function call that appears in the minfied stack trace, the library looks up the relevant mapping entry in the source map that corresponds to the location information for that function call. In the previous example, the call to function <em>i </em>in the minified stack frame has a corresponding deminified stack frame with the following information:</p><pre>FilePath: &quot;crashcauser.js&quot;<br>    MethodName: &quot;level1&quot;<br>    SourcePosition.ZeroBasedColumnNumber: 8<br>    SourcePosition.ZeroBasedLineNumber: 5</pre><p>We bucket our exceptions by these deminified stack frame entries. This means that the same exception occurring on multiple browsers would be be in the same bucket. Bucketing by deminified stack frames also allows for us to track exceptions across multiple deployments, even though the minified method names might have changed between the two different versions of the application. This analysis has provided us with the necessary information to assign bugs to the right developers for our top unexpected JavaScript exceptions in Office Online.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ef600d01bd4a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/web-on-the-edge/deminifying-javascript-call-stacks-ef600d01bd4a">Deminifying JavaScript call stacks</a> was originally published in <a href="https://medium.com/web-on-the-edge">Web Dev @ Microsoft</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>