You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Current Behavior @transifex/native increases bundle size significantly when added as a dependency. Bundlephobia says it's 135.7kb minified and 43.2kb minified/gzipped, which is in line with what we're seeing in our bundles. This is larger than react and react-dom combined, which is fairly ridiculous.
Expected Behavior @transifex/native should ideally be more like 30-40kb minified.
Steps to Reproduce
Add @transifex/native as a dependency and bundle your application.
Possible Solution
I have four suggestions that could improve the situation. Two of these could be considered breaking changes and would require a major version bump, but would not necessarily be difficult upgrades for people to make. I've noted which ones below.
The general themes of these suggestions are:
Stop targeting very old browsers and Node versions
Give the application bundler more control over how this package and dependencies are handled
If any of these suggestions are interesting, we could split them out into separate issues. I'd also be willing to help with some of them.
Transpile Fewer Features
This would be a breaking change.
Currently all the packages in this repo use @babel/preset-env with defaults, which targets extremely old browsers, and thus has to emit quite a bit more code during transpilation.
I can't speak for all users of these packages, but we would be totally fine targeting ES2018+, removing the need to transpile most or possibly even all the code in @transifex/native. All major browsers have supported these features for nearly 4 years.
This is equivalent to browserlists' defaults and seems like a reasonable starting point.
People who care about older browsers still have the option of transpiling dependencies.
If I remove babel-loader from the browser Webpack config, the browser bundle goes from 136kb to 119kb.
Ship an ES Module Bundle
This would not need to be a breaking change, since it could be additive.
Browsers commonly support ES modules, and modern bundlers like Rollup and Webpack prefer working with ES modules. ES modules allow for easier size optimization through tree-shaking.
For people who care about older environments, you could continue shipping a UMD or CommonJS bundle alongside the ES module one.
If I enable experiment module output in Webpack and set output.library.type to 'module', the browser bundle actually increases slightly from 119kb to 120kb. I'm hopeful that we could make up for this in the final application with tree-shaking.
Remove Axios
This would be a breaking change.
The fetch API is widely supported in browsers and in all current versions of Node. It should provide functionality to replace Axios, which is 11.6kb minified/gzipped -- roughly a quarter of @transifex/native's size.
For people who care about older environments, you could provide a way to pass in a fetch function. They could then choose to pull in a fetch polyfill and pass that in.
If I remove Axios and replace it with fetch, the browser bundle goes from 120kb down to 91kb.
Treat Dependencies as External
This would not need to be a breaking change (IMO).
@transifex/native bundles its dependencies, but also lists them inside package.json under dependencies, which is redundant since they aren't actually needed at runtime. It should either:
Not bundle dependencies and mark them as external in Webpack
Bundle dependencies, but list them under devDependencies
I would prefer the first. That would:
Allow me to make minor/patch updates to those dependencies without updating @transifex/native itself
Give me more control over how they're bundle and transpiled
Allow combining them with other packages that might have common dependencies. (This would be the case with md5, which would save us 2.2kb minified/gzipped. Not huge, but I'll take free savings if I can get it.)
I can see there's further room for improvement in @messageformat/core, but I can take that up with that project if we can get started on some of the improvements here.
The text was updated successfully, but these errors were encountered:
Hey @edsrzf, those are some nice suggestions and we would appreciate your help.
For starters, I have created this PR: #204 that addresses the following and is reducing the bundle size for the browser version by around 40K minified:
Added the proposed browserslist query
Replaced axios with cross-fetch
For the latter, native fetch support is introduced in NodeJS 17+, so using cross-fetch looks like a safer path, so that we can support older Node versions as well.
For the next major release, I'd note that the oldest currently-supported version of Node is 18, and so it shouldn't be much of a leap for most to use native fetch. (Though technically fetch is marked as unstable until Node 21, so I guess you could wait wait a few years if you're worried about that.) I still think exposing a way to optionally pass a fetch implementation gives the best of both worlds.
Current Behavior
@transifex/native
increases bundle size significantly when added as a dependency. Bundlephobia says it's 135.7kb minified and 43.2kb minified/gzipped, which is in line with what we're seeing in our bundles. This is larger thanreact
andreact-dom
combined, which is fairly ridiculous.Expected Behavior
@transifex/native
should ideally be more like 30-40kb minified.Steps to Reproduce
Add
@transifex/native
as a dependency and bundle your application.Possible Solution
I have four suggestions that could improve the situation. Two of these could be considered breaking changes and would require a major version bump, but would not necessarily be difficult upgrades for people to make. I've noted which ones below.
The general themes of these suggestions are:
If any of these suggestions are interesting, we could split them out into separate issues. I'd also be willing to help with some of them.
Transpile Fewer Features
This would be a breaking change.
Currently all the packages in this repo use
@babel/preset-env
with defaults, which targets extremely old browsers, and thus has to emit quite a bit more code during transpilation.I can't speak for all users of these packages, but we would be totally fine targeting ES2018+, removing the need to transpile most or possibly even all the code in
@transifex/native
. All major browsers have supported these features for nearly 4 years.@messageformat/core
already uses the browserlist query:This is equivalent to browserlists'
defaults
and seems like a reasonable starting point.People who care about older browsers still have the option of transpiling dependencies.
If I remove
babel-loader
from the browser Webpack config, the browser bundle goes from 136kb to 119kb.Ship an ES Module Bundle
This would not need to be a breaking change, since it could be additive.
Browsers commonly support ES modules, and modern bundlers like Rollup and Webpack prefer working with ES modules. ES modules allow for easier size optimization through tree-shaking.
For people who care about older environments, you could continue shipping a UMD or CommonJS bundle alongside the ES module one.
If I enable experiment module output in Webpack and set
output.library.type
to'module'
, the browser bundle actually increases slightly from 119kb to 120kb. I'm hopeful that we could make up for this in the final application with tree-shaking.Remove Axios
This would be a breaking change.
The fetch API is widely supported in browsers and in all current versions of Node. It should provide functionality to replace Axios, which is 11.6kb minified/gzipped -- roughly a quarter of
@transifex/native
's size.For people who care about older environments, you could provide a way to pass in a
fetch
function. They could then choose to pull in a fetch polyfill and pass that in.If I remove Axios and replace it with
fetch
, the browser bundle goes from 120kb down to 91kb.Treat Dependencies as External
This would not need to be a breaking change (IMO).
@transifex/native
bundles its dependencies, but also lists them insidepackage.json
underdependencies
, which is redundant since they aren't actually needed at runtime. It should either:devDependencies
I would prefer the first. That would:
@transifex/native
itselfmd5
, which would save us 2.2kb minified/gzipped. Not huge, but I'll take free savings if I can get it.)I can see there's further room for improvement in
@messageformat/core
, but I can take that up with that project if we can get started on some of the improvements here.The text was updated successfully, but these errors were encountered: