Skip to content

Commit 6586588

Browse files
committed
clarify tradeoffs in tree-shakeability spec
1 parent 245ae87 commit 6586588

File tree

1 file changed

+75
-2
lines changed

1 file changed

+75
-2
lines changed

docs/tree-shakeability.md

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,81 @@ Split into `@eth-optimism/actions-sdk-core`, `@eth-optimism/actions-sdk-aave`, e
150150
1. **No config shape change**`ActionsConfig` remains the same. The developer's mental model doesn't change.
151151
2. **Leverages existing patterns** — The registry/factory pattern already decouples provider creation from the `Actions` class. Making `HostedProviderFactory.create()` async and using `await import()` inside each factory is a natural extension.
152152
3. **Well-contained breaking change**`createActions` becoming async (`Promise<Actions>`) is a single call site change for consumers. Most initialization code is already async (wallet setup, chain connections).
153-
4. **Solves both problems completely** — Optional peer deps fix install-time warnings/bloat. Dynamic imports fix bundle-time bloat by ensuring bundlers only include provider code that's actually imported at runtime.
154-
5. **Incremental adoption** — Can be rolled out in stages (peer deps first, then dynamic imports) if needed.
153+
4. **Incremental adoption** — Can be rolled out in stages (peer deps first, then dynamic imports) if needed.
154+
155+
### Tradeoffs & DX Impact
156+
157+
This approach introduces a meaningful change to the consumer install experience. It's important to understand what changes and why.
158+
159+
#### Fundamental constraint: config cannot control installs
160+
161+
npm/pnpm dependency resolution happens at `npm install` time — before any code runs. The SDK's `ActionsConfig` is a runtime concept. There is no mechanism in the npm ecosystem for a package to say "if the consumer configures Morpho, install `@morpho-org/*` automatically." The only options are:
162+
163+
- **Hard `dependencies`**: always installed for every consumer (current behavior for Aave/Morpho/ethers)
164+
- **`peerDependencies`**: consumer must install manually; npm 7+ auto-installs non-optional peers, pnpm does not
165+
- **`peerDependencies` + `optional: true`**: never auto-installed, no warnings if missing
166+
167+
#### Before vs After: what a Turnkey + Morpho developer does
168+
169+
**Before (current published version):**
170+
171+
```bash
172+
npm install @eth-optimism/actions-sdk \
173+
@turnkey/core @turnkey/http @turnkey/sdk-server @turnkey/viem
174+
```
175+
176+
Aave, ethers v5, and Morpho packages auto-install as hard `dependencies` — even though this developer doesn't use Aave. Turnkey packages are peer deps and must be installed manually (same as before).
177+
178+
```ts
179+
const actions = createActions({ /* ... */ }) // synchronous
180+
```
181+
182+
**After (this branch):**
183+
184+
```bash
185+
npm install @eth-optimism/actions-sdk \
186+
@turnkey/core @turnkey/http @turnkey/sdk-server @turnkey/viem \
187+
@morpho-org/blue-sdk @morpho-org/blue-sdk-viem @morpho-org/morpho-ts
188+
```
189+
190+
All protocol and wallet dependencies are now optional peers. The consumer must explicitly install every provider's dependencies. Aave and ethers are no longer installed. However, Morpho packages (previously auto-installed) must now be installed manually too.
191+
192+
```ts
193+
const actions = await createActions({ /* ... */ }) // now async
194+
```
195+
196+
If a developer forgets to install a required dependency, they get a clear error at runtime:
197+
198+
```
199+
Error: Morpho lend provider requires @morpho-org/blue-sdk, @morpho-org/blue-sdk-viem,
200+
and @morpho-org/morpho-ts. Install them with:
201+
pnpm add @morpho-org/blue-sdk @morpho-org/blue-sdk-viem @morpho-org/morpho-ts
202+
```
203+
204+
#### Bundle-time: where dynamic imports help and where they don't
205+
206+
Dynamic `import()` behaves differently depending on the runtime environment:
207+
208+
**Node.js (no bundler):** Dynamic imports work as expected. Only the configured providers are loaded at runtime. If Aave packages aren't installed and the config doesn't request Aave, no error occurs — the `import()` is never called.
209+
210+
**Frontend bundler (esbuild, webpack, Vite/Rollup):** The bundler resolves dynamic import targets at **build time**, not runtime. This means:
211+
212+
- If `@morpho-org/*` is installed, the bundler follows `await import('./MorphoLendProvider.js')``MorphoLendProvider.js``@morpho-org/blue-sdk` and includes it in the output (either inlined or as a separate chunk depending on code-splitting support).
213+
- If `@aave/*` is NOT installed, the bundler cannot resolve the Aave provider's transitive deps and will either error or leave the import as a runtime expression.
214+
215+
**The real frontend bundle win is indirect**: because unused deps aren't in `node_modules`, the bundler can't include them. The dynamic import pattern makes this safe by deferring the resolution so that missing packages cause a runtime error (with a helpful message) rather than a build-time crash across all entry points.
216+
217+
#### Summary of tradeoffs
218+
219+
| | Before | After |
220+
|---|---|---|
221+
| **Install command** | Only wallet peer deps manually installed; protocol deps auto-install | All provider deps manually installed |
222+
| **Unused deps installed** | Yes (Aave + ethers for Morpho-only users) | No |
223+
| **Peer dep warnings** | Yes (all 10 wallet packages) | No (all optional) |
224+
| **`createActions` API** | Synchronous | Async (`Promise<Actions>`) — breaking change |
225+
| **Bundle (Node.js)** | All provider code loaded | Only configured providers loaded |
226+
| **Bundle (frontend)** | All installed provider code bundled via static imports | Only installed provider code bundled; unused providers absent from `node_modules` |
227+
| **Missing dep experience** | Build-time crash with opaque module-not-found error | Runtime error with explicit install instructions |
155228

156229
---
157230

0 commit comments

Comments
 (0)