kit
kit copied to clipboard
Support Stripe in @sveltejs/adapter-cloudflare integrations
Describe the problem
Importing Stripe https://github.com/stripe/stripe-node in a +server endpoint https://kit.svelte.dev/docs/routing#server will work fine locally, but break the build when deployed to Cloudflare.
This is likely a critical use case for many SvelteKit projects on Cloudflare, and there seems to be some awareness of the problem as there are several issues like this: https://github.com/sveltejs/kit/issues/3564#issuecomment-1126809396 on the books, but there does not seem to be a replicable, working solution in any of them.
The Cloudflare team are clearly aware of the complexities around using Stripe in Workers, and announced "native support" for Stripe here: https://blog.cloudflare.com/announcing-stripe-support-in-workers but the demo repo referenced in that blog post uses a Webpack config: https://github.com/stripe-samples/stripe-node-cloudflare-worker-template/blob/main/webpack.config.js which rules it out as a SvelteKit solution.
Describe the proposed solution
At a minimum, an official, documented example of whatever set of configs is required to allow the import of Stripe in a +server endpoint without breaking the build, for a @sveltejs/adapter-cloudflare integration, somewhere in the SvelteKit repo or docs.
Even better would be something like this for @sveltejs/adapter-cloudflare integrations: https://github.com/srmullen/sveltekit-stripe
Alternatives considered
No response
Importance
i cannot use SvelteKit without it
Additional Information
The Cloudflare team is contributing to SvelteKit, which is great to see: https://github.com/sveltejs/kit/issues/6441 - @jrf0110 do you have any thoughts on this issue, or how Cloudflare might be able to help make this integration work?
Have you tried this?
const stripe = Stripe(<API_KEY>, {
// This is needed to use the Fetch API rather than relying on the Node http
httpClient: Stripe.createFetchHttpClient(),
});
@ak4zh Yes, unfortunately that does not work as advertised in this case. Even using Stripe.createFetchHttpClient() you get this in the build logs:
2022-09-04T13:18:42.380596Z
2022-09-04T13:18:42.380817Z > Using @sveltejs/adapter-cloudflare
2022-09-04T13:18:42.578683Z ✘ [ERROR] Could not resolve "events"
2022-09-04T13:18:42.579023Z
2022-09-04T13:18:42.579181Z node_modules/stripe/lib/stripe.js:48:29:
2022-09-04T13:18:42.579299Z 48 │ const EventEmitter = require('events').EventEmitter;
2022-09-04T13:18:42.579417Z ╵ ~~~~~~~~
2022-09-04T13:18:42.579527Z
2022-09-04T13:18:42.579637Z The package "events" wasn't found on the file system but is built into node. Are you trying to bundle for node? You can use "platform: 'node'" to do that, which will remove this error.
2022-09-04T13:18:42.579779Z
2022-09-04T13:18:42.608271Z ✘ [ERROR] Could not resolve "http"
2022-09-04T13:18:42.608547Z
2022-09-04T13:18:42.608684Z node_modules/stripe/lib/net/NodeHttpClient.js:3:21:
2022-09-04T13:18:42.608865Z 3 │ const http = require('http');
2022-09-04T13:18:42.608999Z ╵ ~~~~~~
2022-09-04T13:18:42.609114Z
2022-09-04T13:18:42.609226Z The package "http" wasn't found on the file system but is built into node. Are you trying to bundle for node? You can use "platform: 'node'" to do that, which will remove this error.
2022-09-04T13:18:42.60934Z
2022-09-04T13:18:42.609459Z ✘ [ERROR] Could not resolve "events"
2022-09-04T13:18:42.609585Z
2022-09-04T13:18:42.609696Z node_modules/stripe/lib/utils.js:3:29:
2022-09-04T13:18:42.609906Z 3 │ const EventEmitter = require('events').EventEmitter;
2022-09-04T13:18:42.610148Z ╵ ~~~~~~~~
2022-09-04T13:18:42.610314Z
2022-09-04T13:18:42.610447Z The package "events" wasn't found on the file system but is built into node. Are you trying to bundle for node? You can use "platform: 'node'" to do that, which will remove this error.
2022-09-04T13:18:42.610562Z
2022-09-04T13:18:42.610687Z ✘ [ERROR] Could not resolve "crypto"
2022-09-04T13:18:42.610817Z
2022-09-04T13:18:42.610953Z node_modules/stripe/lib/crypto/NodeCryptoProvider.js:3:23:
2022-09-04T13:18:42.611075Z 3 │ const crypto = require('crypto');
2022-09-04T13:18:42.61119Z ╵ ~~~~~~~~
2022-09-04T13:18:42.611299Z
2022-09-04T13:18:42.611416Z The package "crypto" wasn't found on the file system but is built into node. Are you trying to bundle for node? You can use "platform: 'node'" to do that, which will remove this error.
2022-09-04T13:18:42.611528Z
2022-09-04T13:18:42.611707Z ✘ [ERROR] Could not resolve "https"
2022-09-04T13:18:42.611852Z
2022-09-04T13:18:42.611978Z node_modules/stripe/lib/net/NodeHttpClient.js:4:22:
2022-09-04T13:18:42.612095Z 4 │ const https = require('https');
2022-09-04T13:18:42.612204Z ╵ ~~~~~~~
2022-09-04T13:18:42.612313Z
2022-09-04T13:18:42.612423Z The package "https" wasn't found on the file system but is built into node. Are you trying to bundle for node? You can use "platform: 'node'" to do that, which will remove this error.
2022-09-04T13:18:42.612533Z
2022-09-04T13:18:42.612878Z ✘ [ERROR] Could not resolve "crypto"
2022-09-04T13:18:42.613101Z
2022-09-04T13:18:42.613359Z node_modules/stripe/lib/utils.js:5:23:
2022-09-04T13:18:42.61356Z 5 │ const crypto = require('crypto');
2022-09-04T13:18:42.613714Z ╵ ~~~~~~~~
2022-09-04T13:18:42.613895Z
2022-09-04T13:18:42.614097Z The package "crypto" wasn't found on the file system but is built into node. Are you trying to bundle for node? You can use "platform: 'node'" to do that, which will remove this error.
2022-09-04T13:18:42.614313Z
2022-09-04T13:18:42.771244Z error during build:
2022-09-04T13:18:42.771526Z Error: Build failed with 6 errors:
2022-09-04T13:18:42.771681Z node_modules/stripe/lib/crypto/NodeCryptoProvider.js:3:23: ERROR: Could not resolve "crypto"
2022-09-04T13:18:42.771817Z node_modules/stripe/lib/net/NodeHttpClient.js:3:21: ERROR: Could not resolve "http"
2022-09-04T13:18:42.771962Z node_modules/stripe/lib/net/NodeHttpClient.js:4:22: ERROR: Could not resolve "https"
2022-09-04T13:18:42.772076Z node_modules/stripe/lib/stripe.js:48:29: ERROR: Could not resolve "events"
2022-09-04T13:18:42.772184Z node_modules/stripe/lib/utils.js:3:29: ERROR: Could not resolve "events"
2022-09-04T13:18:42.772302Z ...
2022-09-04T13:18:42.772443Z at failureErrorWithLog (/opt/buildhome/repo/node_modules/esbuild/lib/main.js:1624:15)
2022-09-04T13:18:42.772562Z at /opt/buildhome/repo/node_modules/esbuild/lib/main.js:1266:28
2022-09-04T13:18:42.772669Z at runOnEndCallbacks (/opt/buildhome/repo/node_modules/esbuild/lib/main.js:1179:65)
2022-09-04T13:18:42.772792Z at buildResponseToResult (/opt/buildhome/repo/node_modules/esbuild/lib/main.js:1264:7)
2022-09-04T13:18:42.772918Z at /opt/buildhome/repo/node_modules/esbuild/lib/main.js:1377:14
2022-09-04T13:18:42.773024Z at /opt/buildhome/repo/node_modules/esbuild/lib/main.js:678:9
2022-09-04T13:18:42.773136Z at handleIncomingPacket (/opt/buildhome/repo/node_modules/esbuild/lib/main.js:775:9)
2022-09-04T13:18:42.773242Z at Socket.readFromStdout (/opt/buildhome/repo/node_modules/esbuild/lib/main.js:644:7)
2022-09-04T13:18:42.773346Z at Socket.emit (node:events:390:28)
2022-09-04T13:18:42.77345Z at addChunk (node:internal/streams/readable:324:12)
2022-09-04T13:18:42.808906Z Failed: build command exited with code: 1
2022-09-04T13:18:43.877398Z Failed: an internal error occurred
@fredguest I see at few places https://github.com/stripe-samples/stripe-node-cloudflare-worker-template/blob/2f10d7341cb57699eb9614e2a0dfa62b2ec6eb98/webpack.config.js#L12 it’s suggested to edit webpack config resolve.fallback and set following
resolve: {
fallback: {
// Replace these libraries with no-ops as they have no polyfills and we
// are using fetch instead of http/https.
"child_process": false,
"http": false,
"https": false,
// Browser/worker polyfills required to replace Node libraries used by the
// stripe-node SDK.
"buffer": require.resolve("buffer"),
"crypto": require.resolve("crypto-browserify"),
"events": require.resolve("events/"),
"path": require.resolve("path-browserify"),
"stream": require.resolve("stream-browserify"),
}
},
I am not sure how to do that on vite, but you should try that.
I did a dirty fix for it a while back.
I just cloned the stripe-node repo and adapted it for cloudflare workers.
I remember I set the defaults to global fetch, removed fs.
Npm install it a look at the source for reference.
I might have time to do a pr to address this this month.
https://www.npmjs.com/package/stripe-cloudflare
or you might try to use vite alias to replicate the resolve.fallback. Don’t know if this would work
https://github.com/stripe-samples/stripe-node-cloudflare-worker-template/blob/main/webpack.config.js
Hey there — wondered if you’re deploying to Workers Sites or Pages. My current understanding is Pages doesn’t support node compat mode, which is required to make Stripe work ootb. (I recall a Cloudflare commit from a few months ago saying the blog post you mentioned didn’t actually work when they posted it, and node compat mode fixes it.)
more info: https://developers.cloudflare.com/workers/wrangler/configuration/
# wrangler.toml
# Add polyfills for node builtin modules and globals
node_compat = true
being in a wrangler.toml file, this means you have to use Workers Sites and not Pages. Pages is getting support for this soon I’m told. Hope this is correct/helpful!
Hey @mglikesbikes, ya the @sveltejs/adapter-cloudflare adapter is specifically designed only for use with Pages, so that's what I'm using. When you use this adapter you get the benefit of auto deploys etc, but you lose the ability to fine tune things with Wrangler, so this kind of bug needs to be addressed at the integration layer.
I did a dirty fix for it a while back.
I just cloned the stripe-node repo and adapted it for cloudflare workers.
https://www.npmjs.com/package/stripe-cloudflare
✨🎉🎇 This worked for me, thank you so much!
or you might try to use vite alias to replicate the resolve.fallback. Don’t know if this would work
https://github.com/stripe-samples/stripe-node-cloudflare-worker-template/blob/main/webpack.config.js
^^ I tried every combination to alias resolve http, https, and crypto... none of them worked.
Below is all the configs I could find, (none of these work)
import polyfillNode from 'rollup-plugin-polyfill-node';
import alias from 'esbuild-plugin-alias';
const config: UserConfig = {
plugins: [sveltekit(), polyfillNode()],
resolve: {
alias: {
http: false,
https: false,
crypto: 'crypto-browserify',
events: 'events/'
}
},
build: {
commonjsOptions: {
include: [/node_modules/, /stripe/]
}
},
ssr: {
external: ['http', 'https']
},
optimizeDeps: {
include: ['stripe'],
force: true,
esbuildOptions: {
plugins: [
alias({
http: false,
https: false,
crypto: 'crypto-browserify'
})
]
}
}
};
This issue has been fixed by this PR https://github.com/stripe/stripe-node/pull/1679 on the Stripe library.
Sveltekit + Cloudflare Pages Workers + Stripe now work together happily, without hacks or extra configs. 🤘