More webpack and javascript fun!

#1: Caching (with webpack)

Need to configure webpack to ensure files produced by webpack can remain cached unless their contents has changed

  • can use build-specific chunk hashes -> filename: ’[name].[chunkhash].js'
  • runtimeChunk: split out runtime code into separate chunks - also good practise to do a vendor chunk (eg lodash/react) -> cacheGroups
  • adding one module in your app will change the module.id in vendor files - use the NamedModulePlugin to use the module path instead of a numerical identifier

#2: How to escape async/await hell

What hell is: people write multiple statements one after the other and put an await before a function call
- Causes performance issues - many times one statement doesn’t depend on the previous one

What if we don’t use the await keyword?
- We get an unresolved promise (which we can use later)
- The compiler won’t wait for the function to execute properly

What can we do?
- Get the promise and then wait for it in another line

Steps to get out of hell
1. Find statements which depend on the execution of other statements - make things as parallel as possible
2. Group-dependent statements in async functions
3. Execute these async functions concurrently - take advantage of the event loop to run these async non-blocking functions concurrently

#3: BigInt: arbitrary-precision integers in JavaScript

  • Lets you store/operate on large integers even beyond
  • Makes it possible to correctly perform integer arithmetic without overflowing (eg. financial technology)
  • Usually represent large integer ids/timestamps as string because the ints lead to lots of bugs - BigInt fixes this
  • Big Int could lead to BigDecimal!

js decimal problem (0.1+ 0.2 !== 0.3)

> 0.1+0.2
<- 0.30000000000000004

Previously had to use libraries to do big int calculations - can now use native BigInt which will reduce load time, parse time, and compile time + have run time performance. Still need to polyfill BigInt

Number:
- Number type in js are represented as double-precision floats = limited precision
- Doing calculations on integers outside of the safe integer range (from Number.MIN_SAFE_INTEGER to Number.MAX_SAFE_INTEGER) potentially loses precision

BigInt:
- Can safely do things outside of the limit for Number
- To create a BigInt, add n to the end of any integer literal (eg. 123 -> 123n), can also use BigInt(123) === 123n
- Safe integer limits don’t apply to BigInt

eg:

BigInt(Number.MAX_SAFE_INTEGER) + 2n; //will be accurate

A New Primitive:

    typeof 123n 
// -> "bigint"
  • BigInt is never strictly equal to a number (42n !== 42) - to compare them, will need to convert (42n === BigInt(42))
  • When coerced to a boolean, BigInts follow the same logic as numbers (0n is falsey)

Operators:
- BigInts support most common operators, bitwise operations (|, &, <<, >>, and ^) perform bitwise arithmetic assuming a two’s complement representation for negative values (just like for numbers) - Two’s Complement
- Unary - works to make bigint a negative but, unary + is not supported because asm.js expects +x to always produce either a number o an exception
- Can’t mix operations between bigint and numbers (Bigint(2) + 2.5 -> ??? results in a TypeError)
- >>> (unsigned right shift does not work for BigInt because they are always signed

#4: Removing jQuery from Github Frontend

Why:
- Sometimes tech debt grows around dependencies that slowly loose value
- Some of the jQuery syntax doesn’t show intent properly - jQuery will select all of one type (did the author intend this?), and jQuery also silently skips expressions if they don’t match anything on the page
- jQuery is not compatible with Flow (or other static type checkers)
- Removing jQuery means you can rely on web standards more

Incremental Decoupling:
- Monitor number of jQuery calls
- Don’t allow importing jQuery into new code - use eslint to error
- Disable all subsequent eslint errors - shows devs its not up to coding standards
- People see the eslint disable in code reviews and prompts people to fix it
- Static type checking added confidence when refactoring code to vanilla js
- replace $.ajax with fetch()
- Incrementally remove jQuery modules that were no longer being used (creates a custom jQuery) - sped up JS
- Dropped old IE support and then didn’t have to worry about polyfills
- Only used JS as a progressive enhancement so that it would still work with JS disabled in the browser - then didn’t have to rewrite support in JS - could get rid of it altogether

Custom Elements:
- Component library native to the browser - nothing for the user to download, parse, compile
- Focussed on progressive enhancement when making elements

Polyfills:
- Use specific polyfills only when they are necessary for the user and not all the time (ie. to outdated browsers)

#5: Optimize your Application Bundle Size with Webpack

Use webpack-bundle-analyzer to visualize how big your project dependencies are.

First, install with npm install webpack-bundle-analyzer. Then, modify your webpack.config.js by adding:

var BundleAnalyzerPlugin = require(‘webpack-bundle-analyzer’).BundleAnalyzerPlugin;

//…
plugins: [
  new BundleAnalyzerPlugin(),
  new webpack.DefinePlugin({
    ‘process.env.NODE_ENV’: ‘"production"’
  }),
]
//… 

However you start your server, it should serve you a new page at http://localhost:8888 that has your projects visualizations and should be for the production version of your code.

When importing dependencies use:

import groupBy from ‘lodash/groupBy’

instead of:

import loads from ‘lodash'

Remove your source map for production to save on space by using: devtool: ‘eval-source-map’ instead of devtool: ‘eval’

gz compression: use compression-webpack-plugin - compresses assets and generates .gz files
de-duplicating: use dedupe-plugin - removes duplicates of equal/similar files from output, has overhead for entire chunk but can reduce file size
minimizing JS: use uglifyjs-plugin - minimizes all JS output of chunks
only include what’s necessary from module: use ignore-plugin - import selective modules