Open CalinZBaenen opened 2 years ago
I reiterate over the reasons in a concise fashion on DEV in You should be able to use module scripts in the file://
protocol!.
It will basically act as a recap to my post:
<script src=""></script>
.<script>
tags needed to point to every
required file, and the scripts have to all be in dependency-resolution order.async
or you risk them loading in the wrong order.import
/export
syntax looks way nicer than a bunch of <script src=""></script>
s being spammed.Why are file:
URLs important to you? If anything I think we should invest in making them less necessary to deploy applications.
@annevk
Why are
file:
URLs important to you?
Because I, for example, want to redistribute a project, maybe a small app, maybe a game, just something I did for fun, to other people so they can then in enjoy it.
I don't want to, nor should I have to, set-up a web-server just to host it.
And is it reasonable that I expect my end-client, my friends who don't know much about tech/programming, or the random people that download it from me, to set up a server so they can host it? - Personally I don't think it is, but maybe we're just not seeing eye to eye.
But maybe I suffer from "little kid" syndrome and complaining for no reason because I'm just a lazy fifteen year-old that uses Arch.
I would probably use this. I like being able to make the online and offline versions of a small Javascript project the exact same files, instead of having to package them differently and keep track of builds. (This is especially convenient with the way publishing to itch.io works.) I've had some success using the tool "Browserify" to hammer module-based code into the classic-script square hole, but it's not seamless.
@pshaughn
I've had some success using the tool "Browserify" to hammer module-based code into the classic-script square hole, but it's not seamless.
Hammer it?
So it's forcefully shoved into this position it (probably) shouldn't be in?
I mean, that explains why it wouldn't feel seamless.
Upon further examination I have deduced that this would also be good for web-design or JavaScript classes.
This could be utilized to teach students about modular program design while staying relevant to the web or graphics design course.
Also, as @dveditz claims, people at Mozilla haven't reached a proper consensus on whether CORS for such a feature is necessary:
The Mozilla folks are reviewing this design and are not uniformly convinced that CORS is necessary for a default no-credentials, content-type restricted (which we already wanted) request. Obviously we have not reached internal consensus but didn't want silence to be interpreted as agreement.
With that said, that means this idea isn't fully off the table and I'd like to at least appreciate that. :)
@annevk
If anything I think we should invest in making them less necessary to deploy applications.
By the way, what do you mean by this?
How are they necessary currently?
I just see them as a tool, and a convenient way to have a document on your computer.
@annevk
Why are
file:
URLs important to you?Because I, for example, want to redistribute a project, maybe a small app, maybe a game, just something I did for fun, to other people so they can then in enjoy it. I don't want to, nor should I have to, set-up a web-server just to host it. And is it reasonable that I expect my end-client, my friends who don't know much about tech/programming, or the random people that download it from me, to set up a server so they can host it? - Personally I don't think it is, but maybe we're just not seeing eye to eye.
This so much. I am not a web dev, but I am currently working on a small game using web tech. It is great it works on PC, Xbox, Android and others outside of the box, but the requirement for having a web server is super annoying. More so when Gamepad API needs to be in secure context, which applies file:// protocol (yay) and having a secure context for your web server is a rabbit hole nobody wants to delve in when they do small side project for fun.
@nerudaj, while I like the idea some things should be reworked to allow the file://
protocol, I feel like that's quite a big request to make.
It also isn't really relevant as this Issue is specifically for ES6 module support.
@nerudaj, while I like the idea some things should be reworked to allow the
file://
protocol, I feel like that's quite a big request to make. It also isn't really relevant as this Issue is specifically for ES6 module support.
I am not sure if we understand each other. I am not proposing any new feaures, I just expressed support for your issue as the exactly the same problems as you have are troubling me as well.
I might have not been clear in regards to secure context - some cool features are locked behind secure context (which applies to file protocol as well) and some are locked behind CORS (like ES6 modules). But since the CORS lock does not overlap with secure context (and I am not experienced enough with web to understand why), there is this weird space where you can have A or B but not both at once, unless you deploy a web server and pay for certificate for HTTPS.
But I would have been perfectly content if the stuff you are proposing was implemented as it would cause the overlap I currently lack.
Aren't all these use cases better handled by the many online services available, like jsfiddle, codepen, stackblitz, glitch, etc. ? Some of these even offer to link to your version control service so you can "work together" in good conditions, they even come with plenty of various prebuilt configs et al.
As for sharing, it's just a link, while with js files directly you'd need to manually bundle all these files, at least in a zip file, each of your users would then have to unbundle it, if they do modifications to it that soon becomes a nightmare to know who has which version.
And it's accessible to any device.
@Kaiido but using tools like JSFiddle you see the code the user may be confused or scared off by that. I don't want that.
Also that brings back the problem of only being available online. (Possibly?)
Some of these services like glitch.com do offer single link to the preview directly, you don't need to have the code next to it, it's a real website.
You can also install a ServiceWorker to make your assets available offline if that's a must.
Ps: And people should be more afraid of downloading something on their computer and then running it than running it from the web directly.
You can also install a ServiceWorker to make your assets available offline if that's a must.
Well I'd prefer to have the whole game offline.
Ps: And people should be more afraid of downloading something on their computer and then running it than running it from the web directly.
True but browsers are restrictive for that reason. I can get behind that.
I think it's still fun to use HTML and JS this way. - Consider me making a little 2D Minecraft/Terraria like clone in HTML/JS for fun because those are easy to make simple projects in.
Or take a look at E3D, something I couldn't of made when I was as young as I was if JavaScript and HTML wasn't as accessible as it is now.
Regardless though, this isn't about removing restrictions, this is about breaking down an necessary boundary.
The behavior is of modules is something we can already emulate if we run the scripts in the exact order they need to be loaded in.
Ps: And people should be more afraid of downloading something on their computer and then running it than running it from the web directly.
What is worse? People downloading something from github where they can check the code to see if it malicious or downloading homebrew APK they can't check? You cannot expect people will stop doing unsecure things when the alternative means they have money/skill to deploy web app or go through app verification process to get it on the store.
When people are learning, they need to learn fast, not to be bogged down by production setup (they need to learn that at some point, but a later one). And they usually have friends who are willing to be testers for their stuff. And it is really nice to write a multiplatform app that I can deploy on my device and use it without internet (which is exactly what I am using Javascript for).
Yes, people should be cautious what they are downloading off the net, but I don't see that as a counter argument for the issue in question.
Aren't all these use cases better handled by the many online services available, like jsfiddle, codepen, stackblitz, glitch, etc. ? Some of these even offer to link to your version control service so you can "work together" in good conditions, they even come with plenty of various prebuilt configs et al.
Well.. internet is still not available for everyone, everywhere, so working exlusively in a cloud environment is not ideal. And I doubt they're as good IDEs as VS Code is.
The original discussion this issue spun from was about "will CORS requirement negatively impact adoption of modules". For me, the answer is yes. As @CalinZBaenen summarized it, we can develop using legacy features or as @pshaughn mentioned, we can use hammers of questionable quality to convert code to classic script tags. But is that really necessary?
@nerudaj
The original discussion this issue spun from was about "will CORS requirement negatively impact adoption of modules".
Actually, this isn't how I originally approaches the issue.
I approached it the same way I did here, by ranting about CORS.
However I think this would be an interesting entrypoint for the issue, and maybe I should assess this that way in a later comment.
Actually, this isn't how I originally approaches the issue.
I think part of the reason I thought this would be a hit of a feature is because languages like Rust, Java, C++, Python, etc... all support some kind of componentization regardless of the program's "context" (the environment it's running in*).
One final note about modules is that they'd give us, and not much, but at least a little bit of a namespacing system for libraries, which is something that'd be suuuper helpful when debugging in local HTML and JS files.
So, I've thought about my argument from the whole "will CORS requirement negatively impact adoption of modules" angle.
And, while it's against my own beliefs or what I want available in the file:
URI scheme, no.
Even though it's a weak point against my argument not to have module-scripts, because they inherently need to be locked away for actual security purposes, having a CORS restriction didn't impede the adoption of XMLHttpRequest
and fetch
in peoples' code.
we can use hammers of questionable quality to convert code to classic script tags.
IMO the worst part is that "normal", inline <script>
tags can't be async
or defer
red but modules can be.
Now, people reading this may be like "bUt yoU cAn pUt async
and defer
on NoRMal <script>
tAgs iF thEy HAve A sOurCe.", and yes, I'm aware dear reader.
The problem is, when you're importing a library file by file and try to use async
, that library will come crashing down because there's only a small chance that all scripts will load in the right order.
CC: @nerudaj, @pshaughn
Oh hey. Look what I found.
Yet another StackOverflow question on why their script got denied.
. . . Could you possibly guess why?
So, I've thought about my argument from the whole "will CORS requirement negatively impact adoption of modules" angle. And, while it's against my own beliefs or what I want available in the
file:
URI scheme, no.Even though it's a weak point against my argument not to have module-scripts, because they inherently need to be locked away for actual security purposes, having a CORS restriction didn't impede the adoption of
XMLHttpRequest
andfetch
in peoples' code.
I wasn't suggesting it impedes the adoption for everybody. I meant that for me, this is a serious argument why to not adopt modules. Somebody might feel the same, others don't. That was just my stance.
Hey folks. A gentle reminder that every time you comment here, it emails the 648 watchers of this repository. If there are no new technical arguments being made, I suggest taking this discussion elsewhere; the proposal is already pretty clear.
@domenic Where do you suggest I bring the tangential conversation?
So, I'm writing some JavaScript for a project I want to have on my webpage locally, in my filesystem, and my JS file is huge (178 lines so far).
The main chunk of it is a huge class
with methods, but I feel like I could make it neater if I had access to modules so I could reliably split my code up into function
s (without having to worry about <script>
loading order).
Here's an obfuscated version of my class with comments removed, names shortened and obfuscated, and minimal newlines;
just imagine how it would look with doc-comments, comments, whitespace, proper but long names, etc...
class PgmIntf {
static sg(v=0) { PgmIntf.color = (PgmIntf.color & 16711935)+((g & 255) << 8); }
static sb(v=0) { PgmIntf.color = (PgmIntf.color & 16776960)+(b & 255); }
static sr(v=0) { PgmIntf.color = (PgmIntf.color & 65535)+((r & 255) << 16); }
static t15(v=0, m=undefined) {
if(typeof v !== "number" || Number.isNaN(v)) v = 0;
if(v === 0 || v === 16777215) return v;
const v1 = v & (255 << 16);
const v2 = v & (255 << 8);
const v3 = v & 255;
if(m?.constructor != Map) m = P15;
{
const s1 = map.get("1") ?? [0, 255];
const s2 = map.get("2") ?? [0, 255];
const s3 = map.get("3") ?? [0, 255];
const ld1 = Infinity;
const di1 = NaN;
const ld2 = Infinity;
const di2 = NaN;
const ld3 = Infinity;
const di3 = NaN;
for(let sn = 0; sn < s1.length; sn++) {
const diff = Math.abs( s1[sn]-v1 );
if(diff < ld1 || lw1 === Infinity) {
ld1 = diff;
di1 = sn;
}
}
for(let sn = 0; sn < s2.length; sn++) {
const diff = Math.abs( s2[sn]-v2 );
if(diff < ld2 || ld2 === Infinity) {
ld2 = diff;
di2 = sn;
}
}
for(let sn = 0; sn < s3; sn++) {
const diff = Math.abs( s3[sn]-v3 );
if(diff < ld3 || ld3 === Infinity) {
ld3 = diff;
di3 = sn;
}
}
}
/* <Incomplete...> */
return COMPUTED_VALUE;
}
static #update() {
const e = document.getElementById("sitespecific-element");
try {
const code = ColorpickerProgram.#hex;
e.style.property = code;
e.title = code;
} catch(e) {
console.info(`${e.message}: ${e.name}`);
}
}
/* <Omitted methods...> */
static set map(v=null) {
if(v == undefined || v == null) v = undefined;
if(v?.constructor === Map) this.#cm = v;
}
/* Getter for `map`. */
static #cm;
static #cl;
static #hx;
}
I'm frustrated by this issue too, so I wanted to add my two cents:
I'm recently trying to follow a vanilla javascript game dev course on youtube provided by freeCodeCamp. Everything has been in a single, growing JS file. I landed on this issue thread after trying to split out some classes into a separate JS file for organizational purposes and discovering that, hey! F me, that's not possible without spinning up a server!
This is a personal project that itself will never need to live on a live server. This is something that should not rely on an internet connection for me to work on. This is something intended to be basic for a beginner to slowly work up the learning curve.
I agree with @CalinZBaenen here that I should be able to work on a small side project without having to immediately shift my entire learning process to figuring out how to set up a local server just to organize my code.
I have made other small side projects before that were small local utilities and simple games which were also never intended to reside on an actual live server and similarly should have been able to benefit from the organization of files into ES modules.
I disagree with the suggestion to use JSFiddle/Codepen/etc because I should be able to run a set of local files without the requirement of an internet connection. Why should my small utility or beginner learning project depend on an internet connection?
I'm old and returning to programming after initially learning back in high school. Back then I could load up stuff locally and start learning easily. I'm trying to get my son into coding recently and this is issue just increases the learning curve on newcomers or forces them into less efficient organization of their code to avoid the issue.
Further, I fail to see where the security issue is here. A html document on the local filesystem is already capable of loading scripts file from the same filesystem, what difference does it make if those scripts loads additional files from the same scope? As others pointed out above, we could just as well include them via a bunch of Githubissues.
You should be able to load module-scripts in HTML via the
file://
protocol without a CORS error. - Here's why.So, one gripe I have with JavaScript is that "everything cool" is locked behind CORS. I don't seem to be the only one with this sentiment either, or at least we share the sentiment that we shouldn't need CORS-validation, as indicated by this issue, #1888, "is mandating CORS for modules the right tradeoff?".
Maybe it makes sense to lock cookies behind CORS, maybe it makes sense to lock reading files, even local ones, behind CORS. - But preventing importing code from another JavaScript file in the same, local directory, or any of its subdirectories, makes NO sense, and this Issue will explain why.
What are JS modules?
Sure. We should all know what JavaScript modules are, but there are some lurkers here, and I think regardless it would be nice to actually recap what exactly this feature is.
TL;DR A JavaScript E6 module is an easy way to package code together in an organized and orderly fashion, unlike what you'd get if you loaded a bunch of
<script src="./filename.js"></script>
s.A JavaScript module lets you share code between one or more files by using
import
/export
syntax, which isn't too different from most other languages.So, how do we get started? - Well, first, create a file called
test.mjs
,.mjs
is the extension for JavaScript Modules (Modular JavaScript?) and enter the following:Then, create a file called
main.js
and enter the following:Now, all you have to do to use these files is import them into an HTML file, and that's easy enough:
Now all you have to do is double click and viol-... Oh.. Nothing?
Oh, it's a CORS error.
This is what it looks like for me, someone using Chromium on x86_64 Arch Linux:
To get this to work you need to run a server using something like
node
.Once you do this you can finally alert my name.
[For Firefox/Librewolf, see this comment.]
What is an example of something someone would want to do?
So, I, like many people, sometimes like to get distracted and make a lot of random side projects they think would be fun to take on.
For me I wanted to make something with the HTML5
<canvas>
ses dubbed "Drawr", it'd make and manage canvases for you while you called builder-pattern like methods.For example you'd have this "
GfxArea
" type:Now, lets say I wanted to use this type in another file.
Maybe I'm constructing it. Maybe I'm using one of its static properties for something.
Either way, what I do with it should be up to me as the programmer.
What solutions are there currently?
There's two solutions. And only one is feasible if you want to make an HTML page that you can redistribute to anyone.
<script>
tags from<script src="./least_dependent.js"></script>
to<script src="./most_dependent.js"> </script>
rinse and repeat for however many libraries or extra program files we have, then we can finally do<script src="main.js"></script>
.So, option one.
That ain't so bad, is it? By most people's standards, no, it isn't.
By my standards, as someone who wants to do something simple, and cannot afford special services for hosting stuff, yes, it really is. - Not the end of the world bad, but it's up there.
Why's it bad? JavaScript is actively preventing HTML applications (intentionally) made for usage in the
file://
from having neater code.Apparently the reason we're even allowed to use
<script>
at all, according to @domenic, is because it was shoehorned in for compatibility reasons.To me this is a poor excuse and sounds like stubbornness.
Sometimes exceptions should be made when appropriate, and I believe now is that time because it would greatly reduce the amount of
<script>
tags needed in web-apps that run on thefile://
protocol, such as games being made by people who are new to the HTML/JavaScript ecosystem and would greatly increase the productivity of people who use JavaScript in their HTML.Lets see what option two can do far us...
You can probably already see the problem with this strategy, but it at least makes it possible to make applications that work on the
file://
such as games made by newbies to the HTML and JavaScript ecosystem.... But it's incredibly inefficient.
There are a few main issues I want to bring to attention:
<script>
tags. This is fundamentally against DRY (Don't Repeat Yourself) principles, and it makes the source-code unnecessarily bloated (I guess only by N-bytes, but still), especially if multiple HTML files need the same script(s).However if you can use module scripts and import stuff in
main.js
or wherever needed, you are able to write a minimal amount of<script>
tags.This means you can't have most of the
<script>
s in your program beasync
or you risk the possibility of loading out of order. However, this is not an issue for modules since the code is requested at virtually the same time the importing script loads.import
andexport
syntax.Sure, while we all have to learn what CORS is one way or another, the hard way or the easy way, this makes someone who's just trying to accomplish a simple task induced with the anxiety of figuring out what CORS is and how they can solve it.
And when some figure out what the solution is, they may become discouraged (like me).
Maybe these aren't great justifications, but there equally isn't great justification for gatekeeping it.
What changes would need to be made? (Especially in regards to Browsers.)
No changes would really need to be made other than
import
scripts, at least in thefile://
protocol, shouldn't be fetched through CORS, and if they are this specific scenario should be exempt so long as the imported file doesn't "leak outside" of the top-most folder. - The top-most folder would be decided by what HTML file is running.For example:
Why we shouldn't allow module-scripts in the
file://
protocol.I can't think of a single legitimate reason that this shouldn't happen.
If you'd like, block quote this and the previous sentence and leave your reply.
Even, as cited before, @domenic, confirms that there really isn't an incentive to keep this walled off other than "New features must use CORS, no exception.".
However, in direct response to that last quote, there's no way module scripts could face "bad security hygiene" because they're already implemented and have already been tested, porting the functionality over the the local-scope of the
file://
protocol shouldn't, in theory, be too difficult of a task, especially considering a number of environments support these ES6 modules.Final Notes
I believe a more flexible kind of scripting, one with packages, ES6 modules, should come to the
file://
protocol to the file protocol because its absence is confusing and has been the cause of a few StackOverflow posts, including: ES6 modules in local files - The server responded with a non-JavaScript MIME type, Javascript module not working in browser?, and Browser accepts "classic" js script-tag, but not ES6 modules — MIME error w/ Node http server.Module scripts also, when fully evaluated, have the same effect as loading a bunch of individual scripts, therefore it poses no threat to already-existing technologies.
CC: @domenic @annevk @jonco3