Optimization of Lodash styling and bundle size

Lodash is one of the most widely used libraries in modern web development. Whether your webapp is based on Angular, React, Vue or something more exotic – chances that you use Lodash are pretty high. Lodash provides tons of utility methods, making your code more fast and elegant.

However, those tons of useful methods come with a cost – Lodash “weights” more than 70 KB of minified code. This is a significant addition even for the heavy apps. Moreover, chances are you are using just a handful of methods from the whole library. Tree shaking provided by your favorite packing tool could help, but here it comes the next issue – there are several possible ways you can import Lodash in your ES6-based code, potentially making it “unshakable”:

// Method 1:
// import the whole library
import _ from 'lodash';

// Method 2:
// import only relevant methods
import { map, find, filter } from 'lodash';

// Method 3:
// import individual modules
import map from 'lodash/map';
import find from 'lodash/find';
import filter from 'lodash/filter';

Each one of those methods has own pros and cons (and they are described in depth in this excellent article from BlazeMeter), but in many cases personal choice of the developer plays more significant role than formal recommendations. In big projects dealing with the styling of Lodash imports alone may quickly become a mess, and a single “whole library” import will eliminate all your bundle size optimization efforts.

Fortunately, there is a way to handle both size and styling issues together – with the help of Lodash plugins for Eslint and Babel.

Eslint plugin for Lodash enforces consistent and recommended styling for Lodash usage. I’ve found rules coming from plugin:lodash/canonical configuration to be a perfect fit for our React application. This set enforces whole package imports with _ as the name for Lodash variable, enforces usage of Lodash methods over native counterparts when available, and much more. The only caveat I found was in the testing code, where it confused enzyme.find() with native method. Fortunately, we have separate eslint configuration for testing code, so it was pretty easy to tweak the offending rule without sacrificing the style of the application code.

Babel plugin for Lodash implicitly transforms recommended _ imports to per-module imports, reducing “tree-shaked” bundle size. For the app that I was experimenting with, applying both plugins effectively reduced the size of the app bundle by more than 42 KB – but your mileage may vary.

In addition, I spent some time looking at webpack plugin for Lodash, but ultimately decided to skip it. The plugin strips out significant parts of internal Lodash implementation, claiming that those parts are rarely used. While the plugin is configurable, maintaining this configuration will be a pain. Moreover, the code that is unit-tested may be significantly different from the code that is being packaged, especially around edge cases. In my opinion, potential gain in bundle size does not justify the risks of the implementation.

There is one more thing that is worth mentioning in this context. Don’t use Lodash chaining – neither explicit (with _.chain(arr)...) nor implicit (with _(arr)...), since this again will import the whole Lodash library. There are more details about it in this Medium post. In some cases, where chaining seems to be the most simple and elegant way of doing things, see if you can get away with flow and lodash/fp combination:

import { flow, map, compact } from 'lodash/fp';

const result = 
  flow(
    map(...),
    compact
  )(arr);

You can read more about functional programming with Lodash here.

Happy Lodashing!

Summary of Cache-Related HTTP Headers

Long ago (long before the first post in this blog!) I’ve composed a list of cache-related HTTP headers, so I would not need to go through the trial-and-error process of guessing the right combination more than once. Recently I got another question about caching and it took me a lot of time to recall where I saw this list last time. So now I’m placing it here.

Please treat the explanations below as quick and incomplete summary. For full specification of “Pragma”, “Cache-Control” and “Expires” headers refer to HTTP/1.1 specification.

Caching in HTTP 1.1

Following directive does not prevent caching despite its name. It allows caching of the page, but specifies that the cache must ask the originating web server if the page is up-to-date before serving the cached version. So the cached page can still be served up if the originating web server says so. Applies to all caches.

Cache-Control: no-cache

Following directive tells the browser that the page has expired and must be treated as stale. Should be good news as long as the caches obey.

Expires: Thu, 01 Jan 1970 00:00:00 GMT

Following directive specifies that the page contains information intended for a single user only and must not be cached by a shared cache (e.g. a proxy server).

Cache-Control: private

Following directive specifies that a cache must not store any part of the response or the request that elicited it.

Cache-Control: no-store

Following directive tells the cache that the maximum acceptable staleness of a page is 0 seconds.

Cache-Control: max-stale=0

Caching in HTTP 1.0

Following directive is the only cache control directive for HTTP 1.0, so use it in addition to any HTTP 1.1 cache control headers you include.

Pragma: no-cache

Continue reading “Summary of Cache-Related HTTP Headers”

Static Internal IP Address for Windows Azure VMs

WinAzureOn the same day I published my Azure Newbie Notes post, which mentioned, among other things, the inability to set static IP address for VMs, things changed a bit. Then-new v0.7.3 of Windows Azure PowerShell added several cmdlets that allow handling of static internal IP addresses. This came without any official announcements, but was covered in several blog posts on TechNet. No doubt this is a must-have feature – many services just won’t operate correctly without constant IP address, with DNS server is probably the most notable among them. Unfortunately, configuring static IP address via web-based Azure Management Console is not available yet.

[ Here you can find brief explanation on how to install and configure Azure PowerShell, along with the some related links. ]

Several posts and articles with useful samples related to static IP addresses:

Here and in the samples below “MyVM” is the name of the virtual machine we want to update and “MyCloudService” is the name of the cloud service this VM belongs to.

Probably the most useful sample nowadays is one that shows how to take existing VM and set it to have a static IP address. Although most of the articles say you have to use an available (that is, free) IP address, you can use the same IP address that is already assigned to the specific VM. Also, pay attention that Update-AzureVM cmdlet reboots the VM. Note that in the sample run below I’m configuring MyVM to the same IP address it already has. Of course, it makes sense to run the first part of the command alone first to make sure you are going to update the right VM.

Get-AzureVM -ServiceName MyCloudService -Name MyVM | Set-AzureStaticVNetIP -IPAddress 10.0.0.100 | Update-AzureVM

Another useful command is to check whether a VM already has a static IP address configured or not. For VMs with static IP address configured, this IP will be displayed, otherwise only the diagnostic output of the first part will be shown.

Get-AzureVM -ServiceName MyCloudService -Name MyVM | Get-AzureStaticVNetIP

Continue reading “Static Internal IP Address for Windows Azure VMs”

Windows Azure PowerShell

Windows Azure PowerShellWindows Azure PowerShell is a module that provides cmdlets to manage Azure through Windows PowerShell.

Here you can find an official documentation on how to install and configure Azure PowerShell. But in a nutshell, there are two simple steps.

Step 1:
Download and run Microsoft Web Platform installer, which will guide you through the Windows Azure PowerShell installation. The process is a bit lengthy and includes some heavy Microsoft components, such as IIS Express and SQL Server Express. Note that a system restart may (will?) be required during the installation, so prepare accordingly.

Step 2:
Open Azure PowerShell and configure it to use your Azure account, as explained in the documentation.
Two methods are available – via your Azure credentials (with session available for the next 12 hours) and certificate-based. The former did not work in my case, resulting in some strange error, so I had no choice but to go with certificates option. Surprisingly, the setup went extremely easy. First, download your settings file with Get-AzurePublishSettingsFile cmdlet. Second, import the resulting file with Import-AzurePublishSettingsFile cmdlet and delete the file from the local system.

The sources for Microsoft Azure PowerShell cmdlets are available on GitHub, as well as the changelog.

Windows Azure – Newbie Notes

WinAzureThis week I dedicated some time to check what Windows Azure is about. Here are some notes I gathered during those days. I have some background in VMware and AWS, so the notes are mostly around the differences between those and Windows Azure that I spotted.

The first thing to note is that single Management Console provides access to all Windows Azure functionality pieces. Here those pieces look like the parts of a whole. In AWS each service actually is a separate service (with some of those services being integrated), and the console clearly reflects that.

Virtual Machines and Virtual Networks
Those are two basic concepts that are much the same between Azure and AWS, besides maybe some terminology differences:

Amazon AWS Windows Azure
Instance Virtual Machine
(Instance) Type (VM) Size
Start, Stop, Terminate Start, Shut Down, Delete
AMI (= Amazon Machine Image) (VM) Images
VPC (= Virtual Private Cloud) (Virtual) Network

My feeling is that similarly named type/size on Azure is much slower than its AWS counterpart, but I cannot prove that with some test results yet.

VM Images
Just like AWS, Azure provides you large set of images to start your VM from. There is no marketplace for 3rd party images yet, but you can create your own images if you need to. Two major differences here are the need to go through all sysprep burden on your own and the fact that the original VM is deleted (sic!) after it was captured as an image. Yet, this may be not that bad to avoid some confusion, considering that original instance is mostly wiped after sysprep.

IP Addresses
Unlike AWS, where internal IP address of an instance within VPC will remain constant for the instance lifetime (that is – until the termination), here both external and internal IP of the VM will not survive the shutdown and will be changed after you turn it on. A possible workaround is to shut down the VM from inside the guest OS and not from the Management Console. This way the VM is considered running by Azure and all VM resources, including IP addresses, are preserved. Note that in this state the VM continues to eat your budget! [ Update (May 2014): Here is a great article on the topic. Also, setting static IP address is now possible via PowerShell. ]

Cloud Service
The concept of cloud service does not exist on AWS, and is not easy to create simple explanations of what it is. The explanation from Microsoft pretends to be complete, but is mostly confusing. There are some better explanations on the net, much more suitable for newbies – for example this one, which explains the concept by giving three examples of cloud services:
1) Small HTML site.
2) Complex 2-tier web application built on ASP.NET and SQL Server.
3) Virtual network with multi-server application cluster and local AD installation.
Each VM lives inside some cloud service, even if it is a cloud service with single VM inside.
Each cloud service has own permanent DNS name under “cloudapp.net” domain, short and fully resolvable on the internet, and single public IP address. The IP address will be released after all VMs in the cloud service go down, but the new IP will be associated with the same DNS name after the service will be up again. Each VM in the service will get own externally available ports (so-called “endpoints”), which are mapped to some private ports on the VM itself. Those port numbers do no change, making configuration of various connection managers (like mRemoteNG) static and easy to maintain. In addition, cloud service may be configured to act as a load-balancer for containing VMs, eliminating the need to maintain separate entity for that (like, say, ELB on AWS).

Name Resolution
There are significant differences related to name resolution between Azure and AWS. The build-in DNS service is intended to provide name resolution for virtual machines that reside in the same cloud service only. That is, even if you have two virtual machines that are located on the same virtual network, but belong to different cloud services, you will need to use your own DNS server solution in order for them to communicate directly by hostname. I guess this is one of the reasons for Azure-provided DNS server not being able to perform reverse lookups.
Pay attention that setting own DNS server in Azure is not so straightforward given that internal IP addresses may change over time. [ Update (May 2014): Things have changed. read about it here. ]

Active Directory
Windows Azure Active Directory is not a Domain Controller. You can use it to sync on-premises AD with Windows Azure AD to easily enable SSO, but you can not join computers to Windows Azure AD. In addition, it appears that you cannot delete Windows Azure Active Directory that you don’t need anymore. Well, at least they don’t charge for it. But anyway, if you do need full Active Directory (with Domain Services) in Azure – recall that it requires own DNS server…

Storage
Windows Azure Blob Storage is somehow similar to S3 in AWS – but only if you need programmatic access. There is no way to upload files there via Management Console, and I was unable to find third party utils or browser extensions that can do it for you without mandatory registration to their service (and providing them your Azure credentials). [ Update (May 2014): CloudBerry Explorer for Microsoft Azure Cloud Storage seems to do that job perfectly! ]

Security
There is no AWS-like separate “security groups” in Azure. Instead, the same functionality is provided by endpoints that are configured directly on VM level (see my notes on cloud services above). The major drawback of this approach is lack of single place to maintain access rules. However, it makes some sense when you recall that each VM has own public port number for the same protocol.