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