jeffijoe / awilix

Extremely powerful Inversion of Control (IoC) container for Node.JS
MIT License
3.53k stars 134 forks source link

Cloudflare build fails due to Node APIs #368

Open QuentinDutot opened 6 days ago

QuentinDutot commented 6 days ago

Importing only createContainer from awilix causes the build to crash.

It seems that listModules (which relies on fast-glob) is being implicitly included, even when not used which is a problem as Cloudflare Pages and Workers have limited support for Node.js APIs (with nodejs_compat).


Workaround : import from the browser build and manually assign the types

import type { asFunction as asFunctionTyped, createContainer as createContainerTyped } from 'awilix'

// @ts-expect-error
import { asFunction as _asFunction, createContainer as _createContainer } from 'awilix/lib/awilix.browser.js'

const asFunction: typeof asFunctionTyped = _asFunction
const createContainer: typeof createContainerTyped = _createContainer
jeffijoe commented 6 days ago

Never used CF so I’m not familiar with their limitations. What do you suggest? Also, are you using esm?

QuentinDutot commented 6 days ago

Yes esm only, after some digging :

QuentinDutot commented 6 days ago

Some ideas :

1. "browser" is an "agnostic" export Same as now it uses no runtime specific features but it needs some changes:

2. do not automatically load the modules loadModules should accept an array of modules that :

jeffijoe commented 6 days ago

For option 1, what would need to be added to package.json? Wrt types, if the package export is set up, wouldn't the types be loaded correctly?

Option 2 would be changing an API that has been stable for many years which I'm not too fond of, but it could be done - do you know if moving loadModules to a top-level function that accepts the container as the first parameter would work with CF as long as you don't explicitly import loadModules?

There's already awilix-vite which supplies a loadModules that is compatible with import.meta.glob for Vite.

QuentinDutot commented 6 days ago

Option 1 I was thinking about this kind of exports in package.json :

"exports": {
  ".": {
    "import": "./lib/awilix.js",
    "types": "./lib/awilix.d.ts"
  },
  "./browser": {
    "import": "./lib/awilix.browser.js",
    "types": "./lib/awilix.d.ts"
  }
},
import { asFunction, createContainer } from 'awilix/browser'

Option 2 Yes moving loadModules to a top-level function should work. Same as listModules, if not used it would get treeshaked. Sounds like the best option as it would benefit not only CF env but also all non-Node envs

jeffijoe commented 6 days ago

It seems like Option 1 is backwards-compatible and solves the immediate problem, so I think we should go for that for the time being.