JavaScript modules are supported by all of the evergreen browsers now. This has led me to experimenting with some ideas of how to tidy up JavaScript interops when using Blazor.
I feel like having the ability to use native JavaScript modules could lead to some clean abstractions around JS interopos. The following code works when adding the scripts manually to index.html.
Ex:
// FooHandler.js
function doFoo() { alert("Foo Triggered") }
export { doFoo };
// FooInterop.js
import { doFoo } from './FooHandler.js';
window.myNamespace = {
foo: doFoo
}
md5-0f0f88ea1802c30a0b20ea3216c15f44
md5-7abdd96087b507c1782d22da1c631469
md5-dfa13d14d85925320443e0fba6f67144
md5-f5154ca6f62ce1c91a593f70c5f697ff
<script src="_content/DownloadComponents/FooInterop.js">
md5-b0e5845c8684d522e27f235981af2684
<!-- Foo Handler is not needed because it's already imported via FooInterop -->
<script src="_content/DownloadComponents/FooHandler.js">
<script src="_content/DownloadComponents/FooInterop.js">
This approach may be a bit forward thinking since most JS devs use some sort of bundle tool like Webpack. However, modules are now recognized by the browser, so why not embrace it?
This is a good idea, @EdCharbeneau. Thanks for raising it!
What do you think would be the preferred way of indicating whether or not a given .js file should be injected with the type='module' attribute? It could be in the filename, for example MyStuff.module.js. Or we could tell developers to put some config in their .csproj, e.g., <ModuleScripts Include="MyStuff.js" />.
i like the Mystuff.module.js convention. makes it explicitly clear that a js file is a module.
My concern with myStuff.module.js is that existing JS libraries would need to be renamed. However it would make a nice option if we could have both suggestions implemented.
The .csproj approach works, I would suggest a wildcard option so you don't have to explicitly name each module.
<ModuleScripts Include="modules\**\*.js" />
or add an attribute to EmbeddedResource, this way it's extensible if new attributes are implemented.
<EmbeddedResource Include="modules\**\*.js" IsModule="true" LogicalName="..." />
<!-- output -->
<script src="./FooInterop.js" type="module"></script>
Other scenarios could include async and deferred.
```
```
ahh i see. well - if both can be provided … that will be a bonus for sure 😄
Wildcard makes sense in the ModuleScripts node … 👍
As a random note, JavaScript ecosystem seems to drifting towards .mjs as a signifier for script modules.
@richicoder1 JavaScript ecosystem or Browser support?
Ecosystem as far as I'm aware. Specifically Node.js, and Webpack/Babel.
Most helpful comment
i like the
Mystuff.module.jsconvention. makes it explicitly clear that a js file is a module.