mobily / ts-belt

🔧 Fast, modern, and practical utility library for FP in TypeScript.
https://mobily.github.io/ts-belt
MIT License
1.11k stars 31 forks source link

Possible to import one function at a time? (✨ Feature request) #18

Closed mittnavnermike closed 2 years ago

mittnavnermike commented 2 years ago

Love your lib! Though I'd share one of my thoughts. Didn't see anything about this in the docs. Sorry if I'm reraising a question.

As a person with bundle phobia, it would be nice if I could only import the functions that I need. To my understanding, the current way of importing is to import the whole function set for a given type i.e array. import { A } from '@mobily/ts-belt'

What about something like this:

LoDash approach import shuffle from '@mobily/ts-belt/a/shuffle' import shuffle from '@mobily/ts-belt/array/shuffle'

Tree-shaking I have mixed feelings about this one because in some libraries it doesn't really only give you the one function. Not to sure about how all this works, but it might have something to do with your compiler setup. Even though ergonomic to use I fear that in some cases it might not work as expected. import { shuffle } from '@mobily/ts-belt/a'

mobily commented 2 years ago

hello @mittnavnermike 👋 all ts-belt functions are tree-shakeable in the modern bundlers (webpack, rollup, parcel) even if you import the entire function set like the current recommended approach:

import { A } from '@mobily/ts-belt

I have already double-checked this by adding ts-belt in the following "benchmark" locally: https://github.com/mischnic/tree-shaking-example (esbuild on the other hand generates a much bigger bundle for all tested libraries)

file                size      error
------------------  --------  -----
webpack/ts-belt        0.8kb
parcel/ts-belt         0.8kb
rollup/ts-belt         0.8kb
esbuild/ts-belt       39.9kb

rollup/lodash-es      18.0kb
parcel/lodash-es      18.3kb
webpack/lodash-es     20.2kb
esbuild/lodash-es     57.9kb

rollup/lodash         70.6kb
parcel/lodash         70.7kb
webpack/lodash        71.1kb
esbuild/lodash       217.4kb

webpack/rxjs           9.3kb
parcel/rxjs           10.1kb
rollup/rxjs           10.1kb
esbuild/rxjs          37.6kb

webpack/remeda         2.1kb
rollup/remeda          2.2kb
esbuild/remeda         5.4kb
parcel/remeda          7.1kb

parcel/ramda           6.3kb
webpack/ramda          6.4kb
rollup/ramda           6.4kb
esbuild/ramda         13.8kb

rollup/ramdaBabel      6.5kb
parcel/ramdaBabel      6.6kb
webpack/ramdaBabel     7.6kb
esbuild/ramdaBabel    20.8kb

rollup/rambda          1.2kb
webpack/rambda         2.8kb
parcel/rambda          2.8kb
esbuild/rambda         7.0kb

rollup/rambdax         4.9kb
parcel/rambdax         6.4kb
webpack/rambdax        6.5kb
esbuild/rambdax       14.0kb

the ts-belt file content used in tree-shaking-example:

import { pipe, A } from '@mobily/ts-belt'

const isOdd = x => {
  return x % 2 === 0
}

const fn = x => {
  return pipe(
    A.range(2, x),
    A.filter(isOdd),
    A.join(', '),
  )
}

export const answer = fn(10)

you can import functions explicitly from each namespace but it requires some config changes, here's the example:

import { pipe } from '@mobily/ts-belt/pipe'
import { flatMap,mapWithDefault } from '@mobily/ts-belt/Option'
import { dropExactly, head } from '@mobily/ts-belt/Array'

const value = pipe(
  [1, 2, 3],
  dropExactly(2),
  flatMap(head),
  mapWithDefault(0, x => x * 3)
)

Configure path mapping in tsconfig.json:

"paths": {
  "@mobily/ts-belt/*": ["./node_modules/@mobily/ts-belt/dist/esm/*"]
}

Add babel-plugin-transform-imports and use it in babel.config.js:

['transform-imports', {
  "@mobily\/ts-belt\/((?!dist)\\w+)": {
    transform: function(importName, matches) {
      return path.resolve(__dirname, './node_modules/@mobily/ts-belt/dist/esm', matches[1])
    },
    "skipDefaultConversion": true,
  }
}]

let me know if this is what you wanted to achieve 😊

mittnavnermike commented 2 years ago

Thank you for a very detailed answer! I'll try your approach