brianleroux / tiny-json-http

:anchor: Minimalist HTTP client for JSON payloads.
172 stars 18 forks source link

vue-cli with tiny: Uncaught Error: Cannot find module 'http' #14

Closed alexpilugin closed 1 year ago

alexpilugin commented 6 years ago

stackoverflow: vue-cli-with-promise-based-http-clients-uncaught-error-cannot-find-module-http

I commented a line with import tiny from "tiny-json-http"; and it started working. It looks like the error is inside tiny package

brianleroux commented 6 years ago

Hmmm. this really bums me out. It is because of the transpile step you're taking. =/ it can't find HTTP because its built in to Node.

If you're using browserify --ignore-missing is the option that'd fix it.

alexpilugin commented 6 years ago

Yes. I am very confused as well since 'http' and 'https' are node libraries. I like your library, it's tiny and cutie :) and I wanted to use it everywhere where I could...

brianleroux commented 6 years ago

ya, idk, the whole transpilation thing is troubling. it def costs more than value it provides in my personal opinion.

tiny-json-http is wholly intended for use in NodeJS and not really meant for itself to be transpiled (even tho I do bundle it to get the filesize down further). One fix could be adding a "browser" field to package.json and then re-implementing all of tiny-json-http using browser apis but I def do not have the bandwidth to do that myself right now. The realistic option is to overrride whatever Vue does with whatever transpiler it uses to ignore Node built ins or use another library.

brianleroux commented 6 years ago

Closing for now but rest assured I will add browser compat someday! Thx for reporting 🙏🙇

ZebraFlesh commented 5 years ago

the whole transpilation thing is troubling. it def costs more than value it provides in my personal opinion.

Transpilation is a requirement for server side rendering: you have to do something with your templating language.

clintandrewhall commented 4 years ago

Wanted to raise this again, as I've been chasing my tail for a while using this in my Begin projects: this isn't just about transpilation. tiny-json-http does not play nicely with any packaging system, including Rollup and Webpack. Anyone using it should declare it as an external in either case, (and perhaps in others).

In Webpack, for example, tiny is eval'd inline... which means require isn't Node require, it's something else. This is because tiny is built with browserify, which of course adds a prelude. So tiny can't find http.

Might be worth including this limitation as a note in the README... unless you know of another workaround.

brianleroux commented 4 years ago

eh clint! are you transpiling your backend?

clintandrewhall commented 4 years ago

Yep, from TS to JS, and bundling each route:

https://github.com/clintandrewhall/begin-oauth-babel-shared-code-poc/

If I don't externalize tiny, my routes blow up:

Error: Cannot find module 'http'
    at s (webpack:///./node_modules/tiny-json-http/bundle.js?:1:331)
    at eval (webpack:///./node_modules/tiny-json-http/bundle.js?:1:488)
    at Object.1.http (webpack:///./node_modules/tiny-json-http/bundle.js?:1:670)
    at s (webpack:///./node_modules/tiny-json-http/bundle.js?:1:437)
    at eval (webpack:///./node_modules/tiny-json-http/bundle.js?:1:488)
    at Object.3../_read (webpack:///./node_modules/tiny-json-http/bundle.js?:1:4430)
    at s (webpack:///./node_modules/tiny-json-http/bundle.js?:1:437)
    at e (webpack:///./node_modules/tiny-json-http/bundle.js?:1:603)
    at eval (webpack:///./node_modules/tiny-json-http/bundle.js?:1:623)
    at eval (webpack:///./node_modules/tiny-json-http/bundle.js?:1:130) {
  code: 'MODULE_NOT_FOUND'

Traced it to the closure Webpack adds to a dependency:

/***/ "./node_modules/tiny-json-http/bundle.js":
/*!***********************************************!*\
  !*** ./node_modules/tiny-json-http/bundle.js ***!
  \***********************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

eval("/* WEBPACK VAR INJECTION */(function(Buffer, process, setImmediate) {var require;var require;!function(f) ...

I had a similar problem using Rollup, (note the auto-externalize plugin).

https://github.com/clintandrewhall/begin-oauth-babel-shared-code-poc/tree/200d9417d38dc617ac0fd3977f75279b9177cbd5

clintandrewhall commented 4 years ago

You can use this gist of a webpack.config.js to reproduce this specific issue:

npm run build npx sandbox Hit localhost:3333

The workaround for this repo is to externalize it and make sure it's installed in any routes that use the shared code. Not a deal-breaker, but a bit of a pain.

brianleroux commented 4 years ago

Ok. So, I don't do this because Node has a default module system and when we SSR we transpile our frontend into a function for the backend (instead of wholesale transpiling the backend and frontend). You can still use .ts files and just transpile those into .js files while using this module like a normal Node module at runtime. (I can whip up an example if you'd like.)

BIG DISCLAIMER: this isn't to say anyone here is bad or doing anything wrong. But I do want to talk a bit about this practice and you might not like what I'm about to say. We don't bundler our Lambda functions.

RANT

We don't bundle our Lambda functions because it objectively comes with more drawbacks than benefits. This isn't to say anyone who does bundle is doing it wrong. But we are definitely not doing it wrong EITHER. I've said this elsewhere but maybe need to do a longform blog. Using a bundler for AWS Lambda is a bad code smell.

While sometimes there is a performance argument to be made by bundling you are solving the symptom not the root cause. If you have bloat problems the better solution is to keep your functions single responsibility principle with the least deps possible. Functions smaller than five mb will coldstart sub-second. And five megs is A LOT of code.

END RANT


All that said, I want to help people by supporting this usage since this practice happens so much. We starting bundling this module itself because we needed to include the formdata logic and didn't want to bundle all the extra weight. Whether you pretend to or not this module is running in Node and will work for that by default. So what we are talking about here is non standard usage.

Most modules that deal w HTTP are pretty heavy as I'm sure everyone here knows but possible I can cook up a way to do this that satisfies both transpiler use cases (non standard, non default, proprietary languages, etc) as well as defacto standard nodejs runtime code.

Personal aside: I'm looking forward to esm getting unflagged in Node… since 2014!! Suspect we'll see a lot of rewrites for that and Deno in the coming months this module included. So maybe this can be part of that thinking.

clintandrewhall commented 4 years ago

Totally understand. From the Begin perspective, my whole goal was to find a quick, easy way to share common code between routes. It felt weird to be playing with an auth strategy for a web route (GET) and not be able to use it in my GraphQL (POST) route without copying the code wholesale. I think you're right, FWIW, but I was working to make serverless feel a bit more like other experiences, (which may be wrong, as you point out).

In terms of tiny, I think there's something worth playing with/fixing here, likely as a low priority. This is a heavily-used library, so I'd be loathe to change much. My point was more along the lines of any project using tiny that tries to package it, rather than externalize it, might fall down the same rabbit hole I did: trying to figure out why my configuration wasn't supplying http to my build.

ryanblock commented 1 year ago

As of 7.5 tiny is now bundled with esbuild, which uses plain require. It's a little chonkier, but I believe it should resolve this issue!