-
Notifications
You must be signed in to change notification settings - Fork 1
Serve precompiled JavaScript to the browser #19
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
Comments
(Not starting a media type debate, but just wanted to note that) there are other media types for TypeScript which should be considered: |
Deno treating |
@KSXGitHub It's an artifact of multiple file formats sharing an extension (and historically being served without the [correct] media type). |
I have created denoland/dotland#1732, you may continue the discussion there. |
How could this be implemented?
I would like to see this feature implemented, and I am willing to PR if this won't be too time-intensive. I just don't know too much about how you'd like to see this designed :) |
This could just type strip or perhaps also transform down to ES6 for compatibility reasons (or maybe some query parameter to specify the target). Unfortunately I don't know anything about the current website's design to provide any guidance on implementing it and I'm not sure what's currently desired for the implementation. |
For now, compiling TypeScript to the latest version of ECMAScript that is supported by all major browsers is enough. Transforming it to ES6 may cause unnecessary performance regressions. |
This would be awesome. |
Side note, I would not make that difficult tango with User-Agents, I would just serve JS files with .js extension, simple and obvious. Either way I support this. I think this would make deno.land/x way more usable outside Deno too. In a way this would make Deno a better citizen in vanilla JS context. For instance sometimes I find a nice Deno library, and because most Deno code follows standards, I could import it in the browser. But I can't because <script type="module">
import { pathToRegexp, match, parse, compile } from "https://deno.land/x/[email protected]/index.js"
</script> Does not work, because Third Party Modules library could just compile all TS files to JS files when updated, then they would be usable in the browser as well. As a bonus, this would make a cool talking point: Why I like script tags sometimes? They are simple, and for instance I would not like to use TS and all the tools it require for simple demonstration snippets in a blog, I'd just use Allowing to use whole deno.land/x in script tags would dramatically increase the knowledge retention:
|
This could also be solved by a more general Web service that transpiles a TS file to JS on the fly, like any To make this easier, such a proxy worker could be offered by Deno and the second URL integrated into the |
I created a service called streif that transpiles TS on the fly to JS. You just need to prefix your URL with Code: https://github.com/KnorpelSenf/streif Disclaimer: I did not actually write any Rust before, and I also only spent a day on this project, so everything is super hacky and bad so far. I am aware of modules that do not work, and denoland/deno#14879 is an annoying problem for this plan, but I still think that this is a good proof of concept. Most importantly, I am very happy about contributions! :) |
I have considered the case where deno.land/x is imported deep in the dependency. In that case, we can use TypeScript in browser by replacing the URL using import-map. {
"imports": {
"https://deno.land/": "https://XtoY.com/convert?url=https://deno.land/"
}
} However, as the number of module registries other than deno.land increases, so does the size of the import-map. {
"imports": {
"https://deno.land/": "https://XtoY.com/convert?url=https://deno.land/",
"https://deno-modules.com/": "https://XtoY.com/convert?url=https://deno-modules.com/",
"https://awesome-registry.com/": "https://XtoY.com/convert?url=https://awesome-registry.com/",
"https://anything-registry.land/": "https://XtoY.com/convert?url=https://anything-registry.land/",
...
}
} I like the idea of Deno's decentralized module registries, so I'd like to vote for adding a UserAgent-based precompile feature to deno.land so that people can use the various module registries without hesitation. |
I don’t think editing existing code by replacing direct URLs with transpiled URLs is the main use case. Instead, it’s probably writing new code by copy pasting the transpiled URLs. Therefore one doesn’t need an import map. Also import map would prevent using any JS file from that registry because it would map every URL of that host regardless of the path. Not sure I understand your argument. How would integrate transpilation to deno.land help with any other registries? Instead they each need to implement such a feature themselves. While a standalone transpilation service could be used for any registry and not just deno.land. |
I agree that import maps won't solve the problem, for the reasons mentioned above. For streif, I implemented import/export statement transpilation in Rust (wasm) that prefixes all URLs automatically. That way, you can import a module through it, and all dependencies will be transpiled through it, as well. (I think there's currently a bug that this does not always work, but I'll try to fix it in the coming days, contributions as always welcome.) |
For example, my module imports the Deno standard library internally, so I thought it wouldn't work unless I replaced the import statement with an import map here. https://streif.deno.dev/https://deno.land/x/[email protected]/src/parser.ts However, as @KnorpelSenf said, it seems that the import map will no longer be needed once the ability to rewrite the import statement is added to streif.👍 Due to performance and security and the complexity of using two different URLs, I still want denoland to have on-the-fly transpiling, but I think it's a big step forward if a service like streif works. |
@wojpawlik pointed me to https://bundle.deno.dev/ by @johnspurlock which looks more mature. It takes a different approach, because it downloads all modules server-side and bundles them up before shipping them to the browser. This creates the overhead of having to bundle things, but that is probably rather advantageous keeping in mind that the browser can load all JS with a single request, rather than one request per module. I'm considering to drop streif again, unless someone can give a good reason why this approach should be pursued further. |
Neat tool, I just think these external bundlers have problem, do they exist five years from now? If they get popular the bandwidth costs etc. start to stack up. It would be nice to have official way to get JS files from deno.land directly. Bundling as one JS file should be optional, sometimes I want just couple of neat functions from functional libraries and not all. |
My wish was and still is for deno.land itself to serve the JS files to make it convenient for quick prototyping as well as quick experimentation in a browser's console (imagine just copy a link and paste it after |
True, but bundle.deno.dev will send back "cache forever" headers for "pinned" urls (assumed immutable based on commit hashs or release tags), so browsers will only fetch them once. Once Deno Deploy supports edge caching, I'll be able to cache bundle output on the edge itself for these pinned urls without having to re-call bundle at all.
This is a good point. I'm committed to hosting this as a service, on edge platforms like Deno Deploy to minimize headaches and costs.
bundle.deno.dev can point to any file that exports items, it does not need to be the top level package module. e.g. https://bundle.deno.dev/https://deno.land/[email protected]/datetime/formatter.ts However, it's true that it if that file has deps, those will be included in the output. You prompted me to create a new endpoint called transpile.deno.dev that only does transpilation of the given file, no bundling of deps e.g. https://transpile.deno.dev/https://deno.land/[email protected]/datetime/mod.ts Hope that helps! |
[*] Also, each call to bundle.deno.dev and transpile.deno.dev includes Server-Timing response headers, so you can check out how long each part of the bundling process took in dev tools -> network > timing (modulo how accurate Date.now() is on the edge platform) Once Deno Deploy supports edge caching, for example, you'll be able to tell which responses actually called bundle vs served quickly from the cache. |
@johnspurlock your service transpile.deno.dev should rewrite import statements to also transpile them. Otherwise a file with external dependencies cannot be used with your service. |
Good point, I agree! Pushed an update that rewrites remote .ts urls when in transpile mode To see it in action, start a new codepen: https://pen.new Use these contents in the html section: <!-- transpile.deno.dev example -->
<script type="module">
import * as mod from "https://transpile.deno.dev/https://deno.land/x/[email protected]/mod.ts";
console.log(mod);
document.body.textContent = 'Module exports: ' + Object.keys(mod).join(', ');
</script> In dev tools, note all .ts files (even the remote ones referenced via deps.ts) are served individually as js |
Awesome stuff. I'm glad someone finally did it. Now we just need someone from the Deno team to accept a PR that integrates this into /x and then we can close this issue and live on happily :) |
we are currently doing various architectural changes to the registry and website, so any PRs will get invalid pretty quickly. I will bring this up internally once our reworks are completed |
@crowlKats Wondering if there are any updates on this yet? A super rough guess at an ETA would be great if possible - e.g. "maybe some time in 2023". (Please feel free to ignore this comment if there are no updates/ETAs yet) |
The reworks are still somewhat underway, though this could be worked on now. However: this isn't high priority as we have quite a few other things that are being worked on, and especially as there are a bunch of 3rd party solutions for this problem. I cannot give an ETA as this isn't a feature that has been confirmed yet that we want, and in the current state of the new API server, this could be a bit of a problematic feature |
@crowlKats Thanks for the update! I think I'm at risk of raising points that you and everyone on the team already understand very well, but:
Regarding the browser compatibility story of the new
and @dsherret replied:
So, given that the I didn't know that this feature was potentially on the chopping block, so I'm wondering what the arguments against it are? The whole value-prop of Deno for me is the browser-compatibility story, and this is a pretty important part of that. This is the second-most upvoted issue on this repo, so I think other Deno users feel that way too. |
If I understand correctly, |
maybe my wording wasnt right; this isnt on the chopping block, it just hasnt been discussed extensively internally at all yet.
I personally would disagree; this would lock |
@KSXGitHub I disagree; if a third party module needs to use a package from npm, this shouldn't be a blocker for it not to be usable in browsers. |
|
Ah, gotcha 👍
I agree that hindering Also, I think people want to use At this stage I think the main priority should be "make the product good" - which I think was part of the reason for @ry's |
I agree that decentralisation is great, but it can already be achieved by keeping the CLI independent of Another point is this: The Node compat layer with all its features essentially is a tool to let (m)any package from npm run in the browser. That's a tremendous benefit because by building Deno tooling, we even mitigate the Node/browser incompatibility. In my opinion, that would be an impressive feature which would draw a lot of attention to Deno. Making an npm package browser-compatible rarely was easy, so if Deno would achieve this “accidentally” then I find this very attractive. |
I still think I need this feature.
It would be very useful if deno.land provided this feature. |
@ayame113 as a bandaid until they fix this, I just updated esb/est.deno.dev to accept targets of the form: as well as e.g. https://est.deno.dev/https/deno.land/[email protected]/encoding/csv/stream.ts Hope that helps! |
Uh oh!
There was an error while loading. Please reload this page.
Reason
It would be nice to be able to directly import TypeScript modules from the browser without having to use
deno bundle
.Suggestions
User-Agent
isDeno/<VERSION>
orAccept
containsapplication/typescript
, serve TypeScript code. IfUser-Agent
is one of the browsers andAccept
is*/*
, serve JavaScript code. IfAccept
containstext/html
, serve HTML document. Otherwise, serve TypeScript code.The text was updated successfully, but these errors were encountered: