0xProject / 0x-monorepo

0x protocol monorepo - includes our smart contracts and many developer tools
Other
1.41k stars 467 forks source link

general: Bundle size improvements & Tree shaking #1400

Open gkaemmer opened 5 years ago

gkaemmer commented 5 years ago

Hey guys! Was just going through our bundle size and came upon some (relatively) low-hanging bundle fruit.

(This issue is specifically about @0x/subproviders, but could probably be generalized to some other packages)

Expected Behavior

When I run:

import { MetamaskSubprovider, RPCProvider, SignerProvider }  from "@0x/subproviders"

I should not end up with dependencies such as eth-lightwallet, and web3 as a result.

Current Behavior

When I run:

import { MetamaskSubprovider, RPCProvider, SignerProvider }  from "@0x/subproviders"

I do end up with eth-lightwallet, web3, bip39, among others as a result, growing my bundle size by an unnecessary 800kB (grows gzip bundle by ~150kB).

Possible Solution

We've been using this workaround:

import { MetamaskSubprovider } from "@0x/subproviders/lib/src/subproviders/metamask_subprovider";
import { SignerSubprovider } from "@0x/subproviders/lib/src/subproviders/signer";
import { RPCSubprovider } from "@0x/subproviders/lib/src/subproviders/rpc_subprovider";

but obviously that's a bit brittle, and could change on an update.

I'd suggest making your packages tree-shakable, which (I believe) you can do with the following steps:

  1. Add an ES6-compatible build target called index.es6.js in addition to the index.js and index.d.ts files. This file should contain import and export statements instead of exports.blah = require("blah"). This is probably the trickiest step, and requires some special webpack config I think.
  2. Add "module": "lib/src/index.es6.js" to package.json so that a user's webpack can locate the special ES6 module.
  3. Add "sideEffects": false to package.json to tell webpack that it is safe to tree shake this module.

Steps to Reproduce (for bugs)

In an empty project, create an index.js file:

import { RPCProvider } from "@0x/subproviders";

Compare the bundle size to that of index2.js:

import { RPCProvider } from "@0x/subproviders/lib/src/subproviders/rpc_subprovider";

When they are the same, 🎉we're tree shaking! But now they are quite different 😢

Context

Was just trying to optimize our bundle size and remove some extraneous packages that seemed unused.

Your Environment

Package Version
@0x/subproviders 2.1.6

Also, relatedly

  1. It would be a big help to always import blah from "lodash/blah" instead of import * as _ from "lodash"! All of the 0x package seem to drag the entire lodash.min.js into the bundle, most of which is unnecessary.
  2. Do we need to use ethers everywhere? It's a really big dependency, and it seems like 0x only uses the ABI-encoding functionality from it.

Thank you so much! These really are some of the best ethereum libraries out there, and we love them very much. Let me know if I can help in any way.

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

LogvinovLeon commented 5 years ago

Removed the stale label and pinned because it's important and I'll look into it later

gkaemmer commented 5 years ago

Just updated a bunch of 0x libraries to their latest versions and ended up with 7-8 copies of lodash, we can fix by aliasing lodash in webpack config but still a funky default.

Also, +1 on removing ethers as a dependency if possible :). It's 100kb gzipped, which adds a pretty significant portion of the download/parse time

screen shot 2019-02-11 at 9 45 54 am
NoahZinsmeister commented 5 years ago

Just wanted to chime in and say that this is indeed an important issue for many @0x/subproviders consumers :)

fabioberger commented 5 years ago

Thanks for chiming @NoahZinsmeister. As a first step, we're going to move the GanacheSubprovider out of this package since it's adds a ton to the bundle size, but most devs using this package don't use it.

@dekz can you post an updated bundlesize analysis once we remove it? Then we can see what other low-hanging fruit exists.

coopermaruyama commented 4 years ago

here's what it's looking like over here (we use mainly asset-swapper and some utils)

~5MB parsed ~800kb gzipped

image

erickmiller commented 4 years ago

Much wow. Very lodash