Support multiple JS module formats with rollup

Having recently needed to produce a shared JavaScript npm package for internal sharing of functionality between applications I naively failed to consider the impact of the various competing module formats at large in the JS world, but luckily the solution is straight forward with the help of ‘rollup’.

The requirement was to make a shared JavaScript library to be shared between numerous React/Node applications, and make it available internally via an npm/yarn install by publishing it to an internal registry. All straight forward in theory, however there are competing module formats and you need to either pick one or support both.

The various formats are mainly CommonJS (CJS)(the original NodeJS module system), Async Module Definition (AMD), Universal Module Definition (UMD)(a combination of CommonJS & AMD) and ES6 Modules (ESM). Most require the use of “require” keyword to import modules, or in the case of ES6 modules the use of “import”. So why do I need to care about all this? Wouldn’t it be easier if just use the modern ES6 module format only. Well usually you would pick one to use for your app and mostly ignore the others, but when building a shared library you need to consider what’s used by the consuming application so that it can use your new library. Just using ES6 Modules makes it difficult for apps built using CommonJS to consume the library, and in my case I also found that consuming the library from a majority ES6 module based app was problematic and there is often something that requires the CommonJS format (I’m looking at you Node).

So whilst over time everything will standardise (maybe) on ES6 modules in the meantime I used rollup (https://rollupjs.org) to solve the problem. Rollup module bundler allows you to code in modern ES6 standard and then compile it down into other formats (e.g. CommonJS) in one bundle (or different bundles if you wish).

To make life even easier I found this excellent ts-library-template repo for a rollup based TypeScript JS library which fitted my needs perfectly. Rollup is configured to output both CJS and ESM formats.

output: [
  {
     dir: `dist/${dirname(pkg.main)}`,
     entryFileNames: '[name].js',
     format: 'cjs'
  },
  {
     dir: `dist/${dirname(pkg.module)}`,
     entryFileNames: '[name].mjs',
     format: 'esm'
  }
]

So when the library is compiled it will be able to be be consumed by both CJS and ESM based applications.

Advertisement

Window is undefined during SSR

If when server side rendering a React application (other JS frameworks are available) that makes use of the global window object during the initial render, or perhaps the global document object, then you may get an error stating “window is undefined”. This is because when the app is being rendered on the server side on the web server it is not within the browser environment and therefore it cannot access the global objects that the browser provides.

To resolve this issue you will need to check for the presence and validity of the window object before calling it. This could be done manually in your code but a simple widely used npm package can do the job for you – ‘global‘. A very small lightweight library tor require global variables. It is a common dependency on popular npm packages and so it may already be indirectly referenced in your app anyway, but install via ..

npm i global

Then in your code just add an import for window before using it like below. Now the lack of window object will be handled.

// import the global window variable
import window from 'global';

// you can now use window global object
const url = window && window.location.href ? window.location.href : ''

For more info checkout the npm page for global or the github repo LINK

Links:

https://npmjs.com/package/global
https://github.com/Raynos/global

NodeJS & HTTP Error 431

Photo by Vie Studio on Pexels.com

I recently found error responses from a Node JS microservice with HTTP error “431 Request Header Fields Too Large” but at first it seemed to be intermittent dependent on the test environment being used. Further investigations though found it to be a Node setting on the max header size combined with Node JS version changes and a few large cookies.

Error 431 Request Header Fields Too Large HTTP error indicates that the total size of the request headers (which includes cookies) is too large for the web server to accept. This often occurs where large cookies have built up maxing out the request size.

In 2018 Node (version 11.6.0) was updated to resolve a security vulnerability in this area – Denial of Service with large HTTP headers (CVE-2018-12121) and this resulted in the default max request headers size being reduced to 8kb (from 16kb), more info here (Interestingly 8kb was chosen as it was the NGINX default at the time). The default limit was eventually increased back to 16kb in v13.13.0 which means that if you happen to be running against a Node version between 11.6 and 13.13 then you will hit a 8kb limit but before or after those versions the limit won’t be hit until 16kb – which is the situation I was in recently.

If the default max header size for your node installation is not correct for you then it is easy to configure a new value using –max-http-header-size parameter.

--max-http-header-size=16250

Of course you shouldn’t set this value too high and should instead to configure it as low as feasible for your specific application.

Easy Upgrade Tool For NPM on Windows

Having recently needed to upgrade my version of NPM on a Windows machine, without upgrading my Node.js installation, I came across this excellent tool for doing just that without following a complex set of steps. Adding it here for others to find and for me to remember 🙂

The tool is called npm-windows-upgrade and can be found on GitHub. The tool simplifies the numerous steps previously required on Windows and is now the recommended approach by the NPM team.

npm-windows-upgrade tool

In the end I ran this tool several times to test out various versions and it worked well, upgrading NPM in place successfully.

Cheap Azure Hosting via Static Web Sites

Something that is pretty cool and not that well known is that you can now host your static web site in the cloud with Microsoft Azure just from your Azure storage account. The functionality is currently in preview only but its functional enough to get up and running quickly if you have an Azure account.

Why host a static site?

Whilst it does depend on your requirements many sites are quite capable of being static sites with no server side processing. The classic example is a blog site whereby the site could just serve up static html, images and JavaScript straight from disk as the content changes fairly infrequently.

The growth in JavaScript libraries and the functionality of frameworks like React.js make static sites even more viable. Using the power of JavaScript its possible to create rich powerful web applications that don’t need server side processing. There has been an explosion of static site generators over recent years that will take text or markdown files and generate a complete static site for you. Two very popular generators of note are Gatsby (React.js based) and Jekyll (Ruby) but there are literally hundreds of others as can be seen by this online directory: staticgen.com.

Hosting a static site in Azure

Of course you could always host a static site in Azure if you hosted it in a full featured web site (via a hosted VM or azure web site) but the beauty of a hosting a static only site is that you can host it straight out of storage area and so you don’t need to pay for any compute power which makes it extremely cheap (and even free). You just pay standard Azure storage rates which include a generous data transfer limit (about 5GB a month).

If you think about it hosting a static web site is just a natural extension for a cloud offering like Azure as they already host files and binary content on public URLs in Azure Storage. This new functionality though makes it more explicit and enables web site like functionality such as custom error pages. It is also possible to add your custom domain name to the site and link up SSL (although unfortunately at the moment SSL requires use of an Azure CDN which adds to the cost.)

So how do you host your site, well follow the official instructions here.

Once you have a web page being served by the default Azure storage URL you can proceed to add your own custom domain name using these steps.

Now you should have a fully working site, but to keep costs even lower we can utilise caching of our static content to encourage the client browser to cache the files thus reducing our data transfer costs. Luckily it is easy to set cache control settings on our Azure Blob storage items. This blog post by Alexandre Brisebois covers doing it in code but if you are just testing, or have a site that doesn’t change much you can do it manually via the Azure Portal. To do so enter your Azure Portal, browse to your Storage Account and then using Storage Explorer find the files you want to set caching for and go to their properties. In the Properties dialog you can set the Cache-control value in the HTTP header to something like…

 "public, max-age=86400". 

There are other alternatives to Azure for hosting static files and some offerings are very cheap or free. Some of these are more advanced than the current Azure offering and provide additional features such as integrated SSL and contact forms. One such vendor is netlify.com but there are others.

In summary, if you want to host a site cheaply and you dont really need server side processing then consider hosting a static site, and if you’re already using Azure then its a simple step to give it a go.

.

Useful React.JS Learning Resources

Below are some links that you might find useful for learning React.js and Flux, Facebook’s successful JavaScript UI framework.  There are a lot of resources out there but here are some of the best that I have collected for members of my team.

Introductions and overviews of React.js:

Flux:

Tutorials for Flux & React:

Books: 

Prefer the old school approach of reading a book then instead check out this: React.js Essentials by Artemij Fedosejev

NPM config for web access via a proxy

If you are using NPM for to install your JavaScript modules and you are sitting behind a corporate proxy server  with a strict firewall then you will likely be having problems. If NPM cannot find its way out to the web you will likely be getting a timeout error like the one below:

npm-logo

npm ERR! argv “C:\\node.exe” “C:\\nodejs\\node_modules\\npm\\bin\npm-cli.js” “install” “package1”
npm ERR! node v4.2.1
npm ERR! npm  v2.14.7
npm ERR! code ETIMEDOUT
npm ERR! errno ETIMEDOUT
npm ERR! syscall connect
npm ERR! network connect ETIMEDOUT 185.31.18.162:443
npm ERR! network This is most likely not a problem with npm itself
npm ERR! network and is related to network connectivity.
npm ERR! network In most cases you are behind a proxy or have bad network settings.
npm ERR! network
npm ERR! network If you are behind a proxy, please make sure that the
npm ERR! network ‘proxy’ config is set properly.  See: ‘npm help config’

To resolve this problem you need to tell NPM the address of your web proxy, including the username/password to authenticate, so that it can route outgoing HTTP requests via that proxy. NPM stores its configuration in a config file and can be edited via the console/terminal using “NPM Config” command. Use this command to set  set both the HTTP and HTTPS values replacing the username/password and proxy address with your custom values:

npm config set proxy http://username:password@yourproxy.yourcompany.com:8080/
npm config set https-proxy http://username:password@yourproxy.yourcompany.com:8080/

To view the current proxy settings, or to check that your change worked, you can run “npm config get” (as opposed to “npm config set”) to read the settings.

“npm config get proxy”
“npm config get https-proxy”

Alternatively running only “npm config get” will show ALL NPM config settings.

Should you want to remove the npm setting you can do it like this:

“npm config rm proxy””
”npm config rm https-proxy”

For more information checkout the NPM documentation here:https://docs.npmjs.com/misc/config

Succinctly Excellent Free Technical E-Books

There are a lot of free ebooks covering technical subjects, and there are a lot of ebooks that have excellent content however finding some with both attributes can be hard. Syncfusion have a collection of really good technical overview books that cover different subjects ‘succinctly’.

https://www.syncfusion.com/resources/techportal/ebooks

These are not 1000 page monsters but instead focus on providing enough to get you up and running without the fluff. They are free to download and very easy to read. I particulary recommend the JavaScript, HTTP and CSS ones. Oh and I nearly forgot to mention that they come in both PDF and Kindle formats.