| 284 | } |
| 285 | |
| 286 | function memoize(func) { |
| 287 | const cache = new Map() |
| 288 | return (...args) => { |
| 289 | if (process.env.NODE_ENV === 'development') { |
| 290 | // It is very possible that certain files, when caching is disabled, |
| 291 | // are read multiple times in short succession. E.g. `product.yml`. |
| 292 | // So how expensive is it to read these files excessively? |
| 293 | // To answer that, we benchmarked it by sampling 10 files from the |
| 294 | // most common files that are used from `data/`. In fact, we ran 100 |
| 295 | // runs of 10 *different* files. About 80% of them were `.yml` files. |
| 296 | // As a median, it takes **0.5ms to read 10 files from disk** |
| 297 | // all in a sync manner. |
| 298 | // Since most files coming through here is `.yml` files (e.g. |
| 299 | // product.yml and ui.yml) if you also do the `yaml.load()` of the |
| 300 | // read content, that number becomes **2.1ms to read and parse 10 files**. |
| 301 | // So in conclusion, not a lot of time. |
| 302 | return func(...args) |
| 303 | } |
| 304 | |
| 305 | const key = args.join(':') |
| 306 | if (!cache.has(key)) { |
| 307 | cache.set(key, func(...args)) |
| 308 | } |
| 309 | const value = cache.get(key) |
| 310 | // If what was stored in the cache is a mutable, this time, return |
| 311 | // a shallow copy. |
| 312 | // Otherwise, what *might* happen is this: |
| 313 | // |
| 314 | // > const getNames = memoize(() => ["peter", "tucker"]) |
| 315 | // > var names = getNames() |
| 316 | // > names.push("ashley") |
| 317 | // > var names2 = getNames() |
| 318 | // > names2.push("charlotte") |
| 319 | // > console.log(names2) |
| 320 | // |
| 321 | // ["peter", "tucker", "ashley", "charlotte"] |
| 322 | // |
| 323 | // Note that these are shallow copies only. |
| 324 | if (Array.isArray(value)) return [...value] |
| 325 | if (typeof value === 'object') return { ...value } |
| 326 | return value |
| 327 | } |
| 328 | } |