8 ms·
This is nice, until its not. I have spent a fair amount of time over the last several years trying to make node act like the browser, or vice versa. It's doubly
by dexwiz 5y ago
This is nice, until its not. I have spent a fair amount of time over the last several years trying to make node act like the browser, or vice versa. It's doubly confusing to juniors who don't understand the difference between a language and a runtime. alert() looks like a standard function and should be specified by the ECMAScript Language Specification. But its actually specified by the HTML standard, because its Window.alert(), and Javascript's scoping rules let you call it simply as alert(). Trying to explain what's JS and what's Web is really difficult, and design decisions like this only muddy the waters.
- mattigames 5y agoThe people that don't understand the difference between a language and a runtime always need to learn it at some point if they keep working as programmers, and context issues exist on all branches of human knowledge, even English itself has this quirk where some words mean the opposite depending on the context (these are known as contronyms).
- cxr 5y ago> I have spent a fair amount of time over the last several years trying to make node act like the browser, or vice versa. And the right thing to resist doing either. It's to think about what "services" your program actually needs to be able to function and then to isolate those parts from the rest of your application by putting it behind a well-defined interface. In other words, the best way to fix the incompatibility problem caused by API mismatches is to never make the mistake of coding directly against the host platform's APIs to begin with. Trying to do it with compatibility shims to make one platform look like the other is a fool's errand. You end up running around trying to achieve parity with a mammoth API surface area (which might never have been especially well-designed to begin with...). Let's say you're implementing a program similar in scope to UNIX's file(1). For our example, though, suppose you're really only concerned with text files and specifically whether a given text file is using DOS-style CRLF line separators or UNIX-style LF terminators. You really only need two capabilities: a `read` operation to get the contents of a file and a `print` operation to show the output to the user. Does your program care whether that `read` is happening with a Web standards-backed FileReader or NodeJS's proprietary `fs` module? There's no reason it should. Design the best "system" layer that makes the most sense for your application's needs. You can see this implementation strategy in the way the TypeScript team wrote the code for the TypeScript compiler itself when it was made public. Even in the early days, it could run on multiple platforms—including NodeJS, JScript/Windows Script Host, and various browsers (old or new)—because it didn't overly concern itself with anything except its real job of lexing, parsing, and type-checking its inputs—wherever they came from—and then writing the output in a platform-agnostic way.
- IggleSniggle 5y ago> In other words, the best way to fix the incompatibility problem caused by API mismatches is to never make the mistake of coding directly against the host platform's APIs to begin with. Trying to do it with compatibility shims to make one platform look like the other is a fool's errand. You end up running around trying to achieve parity with a mammoth API surface area (which might never have been especially well-designed to begin with...). It seems like you're making a good point, but I'm confused by your comment. Do you believe we should avoid coding directly against the host platform's APIs, or do believe we should avoid compatibility shims? At some point, you need compatibility shims in order to avoid coding directly against the host platform's APIs. The most that your runtime strives to match existing runtimes, the less you need to worry about writing shims to improve compatibility.
- cxr 5y agoI'm referring to compatibility shims like the ones described: where you have two platforms, so you try to make one look like the other and then target that. I'm saying don't do that. > Do you believe we should avoid coding directly against the host platform's APIs, or do believe we should avoid compatibility shims? Avoid compatibility shims that lead to you writing your application's logic directly against platform APIs. You recognize that you need to read a file, so you write your application logic against the simplest possible interface you can think of that would let you do that: `read`.* You don't try to emulate either platform's API. This sounds like a bad deal, because neither platform provides native support for this interface, and the other approach is tempting, because you already get one implementation of the API for "free" (on whatever platform where that API is native), and you'd "only" have to write the compatibility shim for the other one (or re-use somebody else's shim). This is a mistake. For one thing, people end up misjudging the cost/benefits of each, and for another, the compatibility shim doesn't make the program easier to understand. You end up with quirks of that API infecting increasingly more parts of the program. * What you don't do is go off and design the best, elaborate, pluggable, most extensible abstraction layer that you can think of. You implement `read`.
- pvorb 5y ago> never make the mistake of coding directly against the host platform's APIs to begin with I regularly read this advice and I think it's bad in general. If you only ever work against an abstraction, you lose time and might get a worse end result than the one without the abstraction. And in the end, you might throw it away, if it doesn't prove successful. So move the cost for working with an abstraction into the future as much as possible, when you know the alternatives you have to abstract over.
- wbobeirne 5y agoTypeScript is really helpful for this because you can specify what runtime(s) you expect your code to run in with the `lib` configuration. Looks like Deno provides its own versions of libraries: https://deno.land/manual/typescript/configuration https://deno.land/manual/typescript/configuration
- runarberg 5y agoThere is a TC39 proposal for a standard library[1]. One of the ideas reserves a URL scheme built in modules. So to import from a language defined standard library you would use the "js" scheme (import Temporal from "js:temporal") and importing from the runtime you could potentially use e.g. "web" scheme (import AudioContext from "web:audio-context"). I really hope we will have something like that. It would both give us the option of never using magical globals and make the distinction clear whether the module comes from the language or the runtime. Although I can see a case where it could get annoying if you are writing for multiple runtimes and need to get e.g. fetch (import fetch from "runtime:fetch"). 1: https://github.com/tc39/proposal-built-in-modules https://github.com/tc39/proposal-built-in-modules
- gavinray 5y agoThis has also unfortunately been my experience, even when working with developers that have several years of experience writing JS. There seems to be a big gap in knowledge when it comes to boundaries between the language specification, runtimes, and innate abilities. People consistently confused about why they can't use JSX without a build-step, not understanding that JSX isn't "real", why doesn't fetch() work in Node, why does code in my Next.js app break randomly (server vs client render context). Lot of pain in trying to explain to folks that a browser and Node are two different universes that happen to speak the same general language. There's too much magic in this ecosystem and not enough emphasis placed on taking the time to understand the tools you work with, IMO.
- seanp2k2 5y agospeaking of next.js, it's always fun to watch web tech come full circle back to "maybe we should render this stuff before we send the bits, since servers and CDNs are real real good at sending bits real real fast, instead of making everyone render the same static stuff a billion times per day client-side". https://en.wikipedia.org/wiki/Movable_Type https://en.wikipedia.org/wiki/Movable_Type was generating static blogs back in 2001, and that's still a great idea 20 years later. I'm glad that "modern" JS thinking has finally caught up :)
- irrational 5y agoOne of my tasks at work is to support a website that was built 20 years ago. We keep talking about updating it to modern web standards. It sounds like, if we wait a little longer, our 20 year old site will be using modern web development techniques already ;-)
- o_m 5y agoThe javascript community is starting to move away from that now to just using server side rendering (with hydration). Static site generation works fine on smaller websites but gets really slow as the site grows.
- seanp2k2 5y ago
- dfabulich 5y agoI think it's even worse than that, because by being "webby" here Deno has committed itself to alert(); multiple browser vendors (including Mozilla) have advocated removing alert() from the web platform. (They want to do that because alert() "stops the world" by blocking the main thread event loop, and because they make it easy for a site to post a message that appears to come from Chrome itself, or from another website.) https://groups.google.com/a/chromium.org/g/blink-dev/c/hTOXiBj3D6A/m/JtkdpDd1BAAJ https://groups.google.com/a/chromium.org/g/blink-dev/c/hTOXi... > We’re on a long, slow path to deprecate and remove window.alert/confirm/prompt and beforeunload handlers due to their role in user-hostile event loop pausing, as well as phishing and other abuse mechanisms. We’ve been successfully chipping away at them in various cases, e.g. background tabs, subframes with no user interaction, and now cross-origin subframes. Each step is hard-fought progress toward the eventual goal, and we should consider carefully whether we want to regress, even in an opt-in manner. Rich Harris has a good blog post about this. https://dev.to/richharris/stay-alert-d https://dev.to/richharris/stay-alert-d
- seanp2k2 5y ago>beforeunload handlers ooh no, how will sites tell me that my free offer will expire if I navigate away? But on the serious side, this is useful for many antiquated apps (e.g. government stuff) that break tons of stuff if you attempt to re-submit a form, use the back button, etc, so I see that causing a ton of problems.
- michaelgrafl 5y agoYes. I work on applications that run for a long time in the browser with many subframes. The beforeunload event helps us clean up things and manage our applications' states better.
- Aeolun 5y agoYeah, especially after having had it for years, business leaders just do not understand why the browser would remove such a useful feature. And then you get questions like “So? Can we just stick with IE 10 then?” I still haven’t found a way to consistently send a request while the tab/browser is closing.
- binarynate 5y agoWhy is having a different API other than window.alert() a better alternative, though? That just makes it confusing in a different way; that you have to know to use different APIs depending on whether you're targeting the browser or server.
- asiachick 5y agoIsn't that just basic programmer knowledge. Basic in as "you need to learn the difference between a language and the environment its in". I can run C# in Unity. The number of functions I can call is vastly different than running it outside Unity. I can run Lua in 100s of runtimes, all with different functions available. JavaScript can be used to script Adobe apps. The functions available are different than the browser. This is just normal. Is it confusing for a new programmer? Maybe. Is it something they should learn to distinguish? Yes!
- eyelidlessness 5y ago> Isn't that just basic programmer knowledge. Basic in as "you need to learn the difference between a language and the environment its in". I don’t think the answer to this is boolean. For instance: > I can run C# in Unity. The number of functions I can call is vastly different than running it outside Unity. If one is learning both in tandem, coming from a background with a language with different scoping rules, knowing the distinction even exists and should be a consideration might not even show up in reading materials. Sure, it’s an important skill to learn, but it’s not especially transferable. I know how it works in some environments and still find it baffling in others where I even know how to read the code. (Example: Java treats methods as locally scoped functions; I still have no idea how to distinguish them without running the code in a debugger. But I don’t write Java! I have a limited understanding of what’s in scope reading it.)
- deleted 5y ago[deleted]
- michaelcampbell 5y ago> This is nice, until its not. What things aren't like this?