Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bug]: Browser build is used in CF workers environment #1548

Closed
remihuigen opened this issue Sep 6, 2024 · 17 comments · Fixed by algolia/api-clients-automation#3680
Closed
Labels

Comments

@remihuigen
Copy link

Description

After migrating from v4 to v5 (which was confusing in itself, as others have mentioned), I'm encountering weird issues with the algolia client in production. Such as: algolia.generateSecuredApiKey is not a function or ReferenceError: XMLHttpRequest is not defined

I did some digging in the output of the production build, and noticed:

// .wrangler/tmp/chunks/_/algolia.mjs

function algoliasearch(appId, apiKey, options) {
    return {
        ...searchClient(appId, apiKey, {
            timeouts: {
                connect: DEFAULT_CONNECT_TIMEOUT_BROWSER$3,
                read: DEFAULT_READ_TIMEOUT_BROWSER$3,
                write: DEFAULT_WRITE_TIMEOUT_BROWSER$3,
            },
            requester: createXhrRequester(),
            algoliaAgents: [{ segment: 'Browser' }],
            authMode: 'WithinQueryParameters',
            responsesCache: createMemoryCache$3(),
            requestsCache: createMemoryCache$3({ serializable: false }),
            hostsCache: createFallbackableCache$3({
                caches: [createBrowserLocalStorageCache$3({ key: `${apiClientVersion}-${appId}` }), createMemoryCache$3()],
            }),
            ...options,
        }),
        /**
         * And other methods from the full client, not relevant to this issue
        */
    };
}

Apparently the browser build is used, and not the node js build. But I can't figure why this is happening...

I'm using a Nitro server in a CF workers environment. Version of Algolia client is 5.2.5, but it's been having this issue since at least 5.2.1

for context, this is how the client is set up 👇

// utils/algolia.ts
import { algoliasearch } from "algoliasearch";
export const useSearch = (opt: { session: Session}) => {
    const { appId, publicKey } = useRuntimeConfig().algoliaSearch.onderwijsloket
    const client = algoliasearch(
        appId,
        opt.session?.algolia?.apiKey ? opt.session.algolia.apiKey : publicKey,
        {
            baseHeaders: {
                'X-Algolia-UserToken':  opt.session?.itemId || 'anonymous',
            }
        }
    )
    
    return client
}

Client

All

Version

5.2.5

Relevant log output

No response

@shortcuts
Copy link
Member

shortcuts commented Sep 6, 2024

Hey! Thanks for reporting and keeping up with the upgrade :)

Looking at https://developers.cloudflare.com/workers/wrangler/bundling/#conditional-exports everything looks correctly defined in our exports, but it seems to in the end fallback to our default field, which should be used for browser only

was it working on v4? maybe it used one of the root fields https://github.com/algolia/algoliasearch-client-javascript/blob/v4/packages/algoliasearch/package.json#L12

cc @Haroenv maybe you know

@remihuigen
Copy link
Author

@shortcuts I'm not 100% sure it was working in v4, since I haven't done a production build with v4.

Primary reason for that was algolia/api-clients-automation#3608

If you really need to know if v4 was working I could find out, but that would take some effort / time

@shortcuts
Copy link
Member

shortcuts commented Sep 6, 2024

@shortcuts I'm not 100% sure it was working in v4, since I haven't done a production build with v4.

Thanks for letting me know!

If you really need to know if v4 was working I could find out, but that would take some effort / time

No worries it's not necessary, it could just have gave hints on how to resolve the issue


One workaround here could be to import algoliasearch node directly: import { algoliasearch } from "algoliasearch/dist/node"; or the cjs version if esm isn't supported import { algoliasearch } from "algoliasearch/dist/node.cjs";

@remihuigen
Copy link
Author

Already tried that (in local dev), but got

[plugin node-resolve] Could not resolve import "algoliasearch/dist/node" in /Users/remihuigen/local-projects/clients-onderwijsin/onderwijsin-api/server/utils/onderwijsloket/algolia.ts using exports defined in /Users/remihuigen/local-projects/clients-onderwijsin/onderwijsin-api/node_modules/algoliasearch/package.json.

"algoliasearch/dist/node" is imported by "server/utils/onderwijsloket/algolia.ts", but could not be resolved – treating it as an external dependency. 

[worker reload] [worker init] Package subpath './dist/node' is not defined by "exports" in /Users/remihuigen/local-projects/clients-onderwijsin/onderwijsin-api/node_modules/algoliasearch/package.json imported from /Users/remihuigen/local-projects/clients-onderwijsin/onderwijsin-api/.nuxt/dev/index.mjs

  at __node_internal_captureLargerStackTrace (node:internal/errors:496:5)
  at new NodeError (node:internal/errors:405:5)
  at exportsNotFound (node:internal/modules/esm/resolve:366:10)
  at packageExportsResolve (node:internal/modules/esm/resolve:713:9)
  at packageResolve (node:internal/modules/esm/resolve:899:14)
  at moduleResolve (node:internal/modules/esm/resolve:973:20)
  at defaultResolve (node:internal/modules/esm/resolve:1193:11)
  at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:403:12)
  at ModuleLoader.resolve (node:internal/modules/esm/loader:372:25)
  at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:249:38)
  at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:39)
  at link (node:internal/modules/esm/module_job:75:36)

same thing for .cjs

@Haroenv
Copy link
Contributor

Haroenv commented Sep 9, 2024

I believe you should use the fetch requester, which isn't used in any build by default in v4 or v5

@remihuigen
Copy link
Author

remihuigen commented Sep 9, 2024

as in

import { searchClient } from "@algolia/client-search";
import { createFetchRequester } from "@algolia/requester-fetch";

const client = searchClient("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY", {
  requester: createFetchRequester(),
});

??

@remihuigen
Copy link
Author

remihuigen commented Sep 9, 2024

@Haroenv createFetchRequester only mitigates part of the problem: i can now send search queries... The root cause (i.e. using browser build) is not solved.

For example; I still can't use the generateSecuredApiKey method, since this is not present in the browser build (i think?)

// .wrangler/tmp/chunks/_/algolia.mjs

function algoliasearch(appId, apiKey, options) {
    return {
        ...searchClient(appId, apiKey, {
            timeouts: {
                connect: DEFAULT_CONNECT_TIMEOUT_BROWSER$3,
                read: DEFAULT_READ_TIMEOUT_BROWSER$3,
                write: DEFAULT_WRITE_TIMEOUT_BROWSER$3,
            },
            requester: c(),                                                // this used to be createXhrRequester()
            algoliaAgents: [{ segment: 'Browser' }],                       // Still using browser build
            authMode: 'WithinQueryParameters',
            responsesCache: createMemoryCache$3(),
            requestsCache: createMemoryCache$3({ serializable: false }),
            hostsCache: createFallbackableCache$3({
                caches: [createBrowserLocalStorageCache$3({ key: `${apiClientVersion}-${appId}` }), createMemoryCache$3()],
            }),
            ...options,
        }),
        /**
         * And other methods from the full client, not relevant to this issue
        */
    };
}
TypeError: algolia.generateSecuredApiKey is not a function
    at handler (file:///Users/remihuigen/local-projects/clients-onderwijsin/onderwijsin-api/.wrangler/tmp/pages-UfLJjG/chunks/routes/onderwijsloket/v1/index.get.mjs:27:43)
    at _callHandler (file:///Users/remihuigen/local-projects/clients-onderwijsin/onderwijsin-api/.wrangler/tmp/pages-UfLJjG/chunks/runtime.mjs:5322:22)
    at Object._handler [as handler] (file:///Users/remihuigen/local-projects/clients-onderwijsin/onderwijsin-api/.wrangler/tmp/pages-UfLJjG/chunks/runtime.mjs:5303:12)
    at null.<anonymous> (file:///Users/remihuigen/local-projects/clients-onderwijsin/onderwijsin-api/.wrangler/tmp/pages-UfLJjG/chunks/runtime.mjs:5373:43)
    at null.<anonymous> (async file:///Users/remihuigen/local-projects/clients-onderwijsin/onderwijsin-api/.wrangler/tmp/dev-LtXzox/jnqps3t0ul.js:175914:19)
    at async Object.callAsync (file:///Users/remihuigen/local-projects/clients-onderwijsin/onderwijsin-api/.wrangler/tmp/pages-UfLJjG/chunks/runtime.mjs:9925:16)
    at async toNodeHandle (file:///Users/remihuigen/local-projects/clients-onderwijsin/onderwijsin-api/.wrangler/tmp/pages-UfLJjG/chunks/runtime.mjs:5712:7)
    at async ufetch (file:///Users/remihuigen/local-projects/clients-onderwijsin/onderwijsin-api/.wrangler/tmp/pages-UfLJjG/chunks/runtime.mjs:6157:17)
    at async jsonError2 (file:///Users/remihuigen/local-projects/clients-onderwijsin/onderwijsin-api/node_modules/wrangler/templates/middleware/middleware-miniflare3-json-error.ts:22:10)
    at async drainBody (file:///Users/remihuigen/local-projects/clients-onderwijsin/onderwijsin-api/node_modules/wrangler/templates/middleware/middleware-ensure-req-body-drained.ts:5:10)
    ```

@shortcuts
Copy link
Member

Hey @remihuigen, I think the issue is that we don't provide a package.json#exports.default for node, so it fallbacks to browser. I also now provide a workerd exports algolia/api-clients-automation#3680 which should properly hint cf

@shortcuts
Copy link
Member

Hey, I'm releasing the 5.4.0 which provides a new worker exports field. Tested on miniflare is seems to resolve the module correct, let me know if it's not the case :)

@remihuigen
Copy link
Author

@shortcuts Yup, module now resolves to the node build! It did introduce a new TS error though

Property 'generateSecuredApiKey' does not exist on type 'Algoliasearch'.ts(2339)

It also brought me back to the issue I started out with two weeks ago [unenv] crypto.createHmac is not implemented yet!, which was resolved with algolia/api-clients-automation#3608 in 5.2.2, but reintroduced in 5.4.0 🤔

@shortcuts
Copy link
Member

Could you please provide a minimal reproductive example? I've tried my best with vitest and miniflare here but it seems to work 🤔

@remihuigen
Copy link
Author

I'll check downstream first. I'll circle back if there is no solution there.

Thanks though!

@shortcuts
Copy link
Member

Seems like it firebase resolves to a browser build too rather than the node one 🤔 Does it solves the issue when using import { algoliasearch } from "algoliasearch/dist/node"? I'll check their docs if they recommend anything

@si1k
Copy link

si1k commented Sep 11, 2024

@shortcuts, You responded as I was deleting my comment (thank you!) since using "moduleResolution": "Bundler" in my tsconfig.json was the issue on my end.

import { algoliasearch } from "algoliasearch/dist/node" doesn't change anything.

It appears I can fix the issue by swapping my tsconfig.json file to the below instead of ESNext + Bundler.

"module": "NodeNext",
"moduleResolution": "NodeNext",

@shortcuts
Copy link
Member

@shortcuts, You responded as I was deleting my comment (thank you!) since using "moduleResolution": "Bundler" in my tsconfig.json was the issue on my end.

Ahhh good to know you resolved your issue then!

@ayuhito
Copy link

ayuhito commented Sep 28, 2024

Hi @shortcuts, sorry to ping you here. Was algoliasearch/lite intended to be part of the fix?

I just migrated to v5 for Worker support and using the lite client does return the same ReferenceError: XMLHttpRequest is not defined errors.

import { algoliasearch } from 'algoliasearch'; // Works and what I'm currently using as a workaround!
import { liteClient as algoliasearch } from 'algoliasearch/lite'; // Doesn't work

@kvkenyon
Copy link

I'm getting Property 'generateSecuredApiKey' does not exist on type 'Algoliasearch'. in 5.6.1 using nextjs. Any ideas? When I run the code it works just my builds are failing in production.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants