14 ms·
JavaScript import maps are now supported cross-browser
- msoad 3y agoCan we use React with JSX in browser without any compiler using this? I'm sure people have tried it but I can't find it. I just want an `index.html` file that I can write React code in it and play around with things...
- toastal 3y agoReact is already often slow enough. Pushing compilation steps to the client is inefficient, especially when you consider that JSX compiles to basic functions and you could have used those functions since the first version.
- deleted 3y ago[deleted]
- hobofan 3y agoThat has been possible for some time with Babel[0] and was also referenced in the old React docs[1]. But, as stated there and in the sibling comment here, it's not really suitable for production use. [0]: https://babeljs.io/docs/babel-standalone#script-tags https://babeljs.io/docs/babel-standalone#script-tags [1]: https://legacy.reactjs.org/docs/add-react-to-a-website.html#quickly-try-jsx https://legacy.reactjs.org/docs/add-react-to-a-website.html#...
- davnicwil 3y agoFrom the react docs: "it makes your website slow and isn’t suitable for production" I don't really like blanket statements like this or think they are appropriate. It's so counter to the spirit of the web. Like, what does 'slow' mean in an absolute statement like this? It depends entirely on the system and usecase. It's just code at the end of the day. If it works for you, go for it!
- knute 3y agoIt's interesting that this is your perception of "the spirit of the web" whereas other people are going to say that requiring JavaScript at all is "counter to the spirit of the web".
- postdb 3y agoThere is the 1k jsx lib: https://nanojsx.io https://nanojsx.io Then again, if we are at this road now again, maybe they should just bring a lighter version of e4x as part of ES/JS.
- c-smile 3y agoIn Sciter I did just that - JSX is an integral part of JS compiler - patched version of QuickJS : https://gitlab.com/c-smile/quickjspp/-/blob/master/quickjs-jsx.h https://gitlab.com/c-smile/quickjspp/-/blob/master/quickjs-j... So in Sciter this works out of the box: <html> <body/> <script> function HelloWorld() { return <p>Hello <b>world</b></p>; } document.body.append(<HelloWorld/>); </script> </html> JSX expressions are compiled to calls of JSX(tag,atts,kids) function. That function can be redefined enabling different libraries to use JSX in the way they want, here is an example of using JSX with PReact: import { h, render, Component } from 'preact'; JSX = h; // let's use PReact::h() as a driver of JSX expressions See https://gitlab.com/sciter-engine/sciter-js-sdk/-/blob/main/samples/preact/clock.htm https://gitlab.com/sciter-engine/sciter-js-sdk/-/blob/main/s...
- anton96 3y agoThey are many libraries that use tagged template string to allow this, the most interesting to my eyes is the one made by preact dev. It's just named htm [0], it's made by preact but it can totally be used with react. The most interesting thing of this one is that uses no custom syntax for js variable, so @attribute something when you must pass an object as props. 0. https://github.com/developit/htm https://github.com/developit/htm
- throwaway290 3y agoIf it doesn’t have fragments, how do you implement something equivalent to this when mapping over items and every item has to output multiple roots? <React.Fragment key={idx}>
- anton96 3y agoYou can import the Fragment component of the React package or stack them directly, it works too. Normally, the empty bracket syntax should work, they have a few issues closed and open that talk about it in their repo.
- throwaway290 3y agoThanks! Interesting stuff
- CraigJPerry 3y agoDoes this mean that in theory i could skip the build/bundling step entirely? E.g. i could have a backend project in whatever language i wanted but then instead of having an npm frontend project, instead i could: 1. use a jsconfig.json and jsdoc to gradually type with typescript but without need for tsc since my editor gives me feedback anyway 2. use es modules to handle splitting and caching the various .js files of my app 3. use this import maps feature so that i can still gzip and add the digest of the file to the filename so that i can safely say cache every .js forever since if theres a change, the filename will differ and this feature means i can still import from friendlyname rather than friendlyname-hashed-value What am i missing from the bundle approach: Optimal file transfer - all in one js bundle, but if i have http2 then i don’t care because the overhead of multiple files is gone minify - i don’t care since i gzip anyway sourcemaps - i dont care since the files presented to the browser are the ones i wrote, maps are redundant I quite like react but i think i’d like simplifying my tool chain more and using something like htmx instead. EDIT: i want to qualify the “i quite like react” statement, i have pure components only, no useState, for state handling in the small i’m fine with pure useReducer’s but zustand is nicer for my cases since i can also use that to prevent subtree re-renders of the reducer/context barebones approach.
- deleted 3y ago[deleted]
- thrownaway561 3y agothe only thing missing is bundling CSS files. Rails has defaulted now to "pinning" javascript however, any css that maybe bundled with the package still presents an issue.
- madeofpalk 3y ago> instead of having an npm frontend project You probably still want to use a dependency manager (npm, yarn, etc) to pull in and own host your own dependencies. You don't want to pull your dependencies from an external source as that will only ever make your site less reliable. > use es modules to handle splitting and caching the various .js files of my app Yeah, I was surprised at how well es modules just worked when i put together this tiny repro https://idb-perf-repro.netlify.app/ https://idb-perf-repro.netlify.app/ (index.js imports two relative files) > use this import maps feature so that i can [...] add the digest of the file to the filename So you've still got build tooling and a layer of indirection. Maybe this is simpler, but you'll still need tooling to manage hashing files + creating import maps. I don't think import maps really gives you anything here, because if you're renaming all your files on deploy you may as well just update the imports as well, rather than using import map. > Optimal file transfer - all in one js bundle, but if i have http2 then i don’t care because the overhead of multiple files is gone Test and validate this. Does HTTP2 really remove all overhead from requesting 100s of files vs 1 large file? I don't think this is the case. > but i think i’d like simplifying my tool chain more and using something like htmx instead. Simplifying your toolchain by removing type safety from your views.
- toastal 3y agoReminder: vendor your imported scripts if you’re doing this. I shouldn’t have to trust or give data to a CDN to use your website. There isn’t a meaningful performance win either since browsers now cache per domain for privacy reasons. https://httptoolkit.com/blog/public-cdn-risks/ https://httptoolkit.com/blog/public-cdn-risks/
- LoganDark 3y ago> vendor your imported scripts i̶f̶ ̶y̶o̶u̶’̶r̶e̶ ̶d̶o̶i̶n̶g̶ ̶t̶h̶i̶s̶ FTFY I vendor everything my webpages need, better to ensure that the webpage always works as long as my server is up. Also means I can download the page and use it offline.
- ddalex 3y agoWhat does it mean to vendor the script?
- bheadmaster 3y agoI assume it means the same thing as to vendor anything else: to bundle dependencies as a part of your application instead of giving users "links" to the dependencies served by a third party.
- lelandfe 3y agoThey just mean "load your JS from your own site, not some other person's site"
- hnbad 3y agoTo elaborate on the more pragmatic answers: vendoring generally refers to adding the source code of a dependency to your source control repository rather than having an install step (or expecting libraries to be provided by system level package managers) as part of your development process. In JavaScript these days, dependencies are usually loaded from npm so avoiding the bundling step for client-side code would naively mean replacing those dependencies with links to a third-party service like unpkg, which serves code published to npm for the browser. As others have explained, vendoring in this case would mean shipping those dependencies as part of your application code so they are served from your own domain. Of course at the moment a lot of dependencies will likely simply not work if imported directly from the browser.
- jFriedensreich 3y agothats really cool but this will only be over when >external< importmaps and decent browser dev tool support is there too. inlining is a pain in most setups and when things don't work as expected its harder than it should be to find out why a prefix did not work.
- qubyte 3y agoI did a write up of how I use import maps to avoid bundling JS on my static site and cache modules more effectively. I mostly use JS for little experiments and generative art and such, so I have a number of utility modules. These get hashed and the names of each resolved in the import map. Original modules are kept for browsers without import map support (without the immutable cache header). There are a few gotchas. The browser won't use the import map to result an entry point in a script tag for example. Content security policy is a painful one too for static sites like mine (the import map counts as a script, so you have to hash the map and put that in the CSP header). https://qubyte.codes/blog/progressively-enhanced-caching-of-javascript-modules-without-bundling-using-import-maps https://qubyte.codes/blog/progressively-enhanced-caching-of-...
- cientifico 3y agoThis is awesome. This allows to improve my load times after each deploy by several factors. Be aware that the example that is provided in the article is quite dangerous. If for any reason the content of the script is altered, the user will execute it anyway. With normal scripts you have the integrity="sha-..." option that secures the content. With importmaps we only have a couple of github issues and no solution. https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity https://developer.mozilla.org/en-US/docs/Web/Security/Subres... https://github.com/WICG/import-maps/issues/221 https://github.com/WICG/import-maps/issues/221 https://github.com/WICG/import-maps/issues/223 https://github.com/WICG/import-maps/issues/223
- orra 3y ago> With normal scripts you have the integrity="sha-..." option that secures the content. With importmaps we only have a couple of github issues and no solution. Yeah, I think it's a Bad Thing for security, to release importmaps without integrity.
- deleted 3y ago[deleted]
- XCSme 3y agoSeeing this, it reminded me of an interesting topic: caching at browser-level the common external JS libraries, to achieve big performance improvements: https://github.com/w3c/webappsec-subresource-integrity/issues/22 https://github.com/w3c/webappsec-subresource-integrity/issue...
- e1g 3y agoAnd that reminds me of the rebuttal: such "embedding/blessing" of libraries would give them a considerable tailwind and stifle innovation. Suppose React/styled-components/Apollo/Highcharts is already available on the client. In that case, it becomes much harder to consider alternatives, and any new contenders (Vue/Solid/urql/emotion/etc) would never get traction.
- chrisweekly 3y agoYeah, cross-domain public caching had mostly theoretical benefits and never really worked that well in praxis. Glad browser vendors moved away from it.
- Mystery-Machine 3y agoI'd like to read mor about why it only has theoretical benefits. Do you have any links to share where I can learn more? Thanks!
- XCSme 3y agoCheck the link in my top comment. Most problems are related to the privacy. A website could always tell if you loaded the resource or had it in cache. If you had it in cache, it means you have previously visited a website that used the same library. Now, if multiple such inferences can be made, it could be used for many things like fingerprinting, for marketing purposes, for identifying a user's identity, etc.
- tourgen 3y ago[dead]
- SquareWheel 3y agoAt the risk of bikeshedding, what's with the syntax? Would it not make sense to stick closer to HTML tags? eg. <script type="importmap" name="browser-fs-access" src="https://unpkg.com/browser-fs-access@0.33.0/dist/index.modern.js"> The current implementation seems like something I'd have to look up every time I wanted to use it.
- lucideer 3y agoThis likely stems from the proposers building on existing "in-the-wild" development patterns: it's become a convention for DSLs in the JS development community. Consider similar for a larger amount of data: <script type="custom-dsl">{ "very": { "large": "json", "object": "with", "many": "keys" }</script> Even sticking strictly to JSON (the DSL can be any syntax), this has a few advantages to SGML-style attributes: 1. Supports nesting to any depth 2. Easier to deserialize from an in-memory object in the most common server-side languages 3. Supports easy developer/hacker copypasta into a JS file for debugging. 4. Broader/better expand/collapse support in text editors (in the case of very large lists) --- > I'd have to look up every time I wanted to use it I'd likely have to look up the HTML attribute names just as much - I recall having to do this a lot at first with the viewport meta when it was introduced - the only real hurdle to get over with this is to internalise the following pattern (which, as mentioned, some in the JS community are already familiar with): <script type="dsl-name">DSL SOURCE</script>
- ramses0 3y agoIt matches exactly the on-disk format for deno.json / import_map.json. Based on my limited experience with it, I was super-stoked to see it be basically: “oh, what I was messing around with last night when trying out deno!”
- WorldMaker 3y agoThe current implementation is so that you can `<script type="importmap" src="path/to/your/importmap.json"></script>`. JSON is a well-known on-disk data format with lots of tools that support working with it and manipulating it (including plenty JS itself including natively in the browser). You can even `<script type="importmap" src="https://your.fave.cdn.example.org/shared-importmap.json"></script> https://your.fave.cdn.example.org/shared-importmap.json"></s...` and share an importmap across multiple applications/projects.
- kmeisthax 3y agoSo, any progress on being able to bundle native modules and have them import properly into inline script tags? Right now if you want bundling you have to give up native modules, because the only way to get a browser to register a native module is by making a separate HTTP request for that module. The closest I could think of to doing this would be an importmap with a data URI per module, but I've no idea if you can load importmaps as separate files or if they have to be inlined. If they have to be inlined that defeats the purpose.
- wildpeaks 3y agoThat might be handy during development, but production would still need a "build step" for generating things like SRI hashes, asset filenames, sitemaps, etc.
- simonw 3y agoI built a tool relevant to this the other day. I was fed up of how hard it was to download ES modules from a CDN and store them locally so I could build apps without that CDN dependency, so I made this: pip install download-esm download-esm @observablehq/plot This downloads the ESM version of Observable Plot from the jsDelivr CDN, figures out its dependencies, downloads them as well (40 files total!) and rewrites their imports to be local, not CDN paths. More details here: https://simonwillison.net/2023/May/2/download-esm/ https://simonwillison.net/2023/May/2/download-esm/ I'm now considering adding import maps support: https://github.com/simonw/download-esm/issues/4 https://github.com/simonw/download-esm/issues/4
- softfalcon 3y agoOh no! You've gone through dependency hell so many times you've started writing your own package management! I'm only half kidding, this is pretty cool, but I'm also really sorry that it has come to this for you and your tooling!
- zeven7 3y agoThis is JS. Dependency hell is par for the course.
- jakelazaroff 3y agoGenuinely curious — what language do you think has good/better package management? Every time I start a Python project, for example, there's a bunch of time and frustration spent getting pip and virtual envs working.
- moron4hire 3y agoI haven't had any package management troubles with .NET in over a decade.
- HideousKojima 3y ago
- rektide 3y agoBut not in Workers/worklets. https://github.com/WICG/import-maps/issues/2 https://github.com/WICG/import-maps/issues/2 ESM was specced out in 2015. It hurts so bad that we are in 2023 & using modules in a modular way is still incredibly ill supported in the web ecosystem. :(
- paulddraper 3y agoI think modules work in a modular way, yes? Import maps are something new and different, largely for DX.
- zackmorris 3y agoWill this work with Subresource Integrity (SRI) so that assets can be fetched from a shared CDN securely? https://www.w3.org/TR/SRI/ https://www.w3.org/TR/SRI/
- tolmasky 3y agoIt's really wild seeing the tremendous amount of work being put in to ESM just to come up with a solution that still isn't as fast, secure, or ergonomic as bundling. 1. Import maps are basically a compile-time feature. I thought the point of all of this was to not have to have toolchains? 2. Imports significantly lag behind "old school" scripts in security. You can't use integrity hashes with them, and yet most the examples you see are about importing random scripts from all over the web. This is actually hilariously related to point (1), since you can only escape the realization that this is a feature a compiler is supposed to spit out if you direct the imports to some third party resource. So in order to contrive a situation where you would manually craft an import map, they are forced to show an example that is less secure than the stuff that has worked in every browser for 10 years. 3. Not directly related to import maps, but you'll probably end up using them together: in order to attempt to achieve similar performance to just bundling your code, the amazing solution we've come up with is to... put a <link rel="modulepreload"> tag in your head element for each script you want to be fetched immediately. Yes, so much better than the ridiculous old method of using a script tag for each script. Now you just use a link tag for each script instead. I'm sure someone will tell you that this is better because you don't have to do that. Yes, yes, so much better that the default behavior of script loading is slow unless you go read about a bunch of "tips and tricks" to get it working with reasonable performance. It's always great to take one concept like "importing a script" and turn it in a an entire ecosystem of terminology that spans languages and platforms, custom JavaScript syntax for the imports themselves, a set of different HTML tags for actually getting them into your page (script, link, etc.), and JSON for mapping names to URLs. Great. Super simple. ESM has always suffered from a weird shifting argument. Whenever you point out that the performance and security isn't great, all of a sudden it's a developer ergonomics feature, not meant to be for production. Then when you point you the ergonomics suck (like not being able to do bare imports), you're told you should be using it in tandem with a toolchain that auto-generates import maps or something. So what's the benefit? I already had a tool that could do that, and it worked in every browser and didn't ignore the the security advancements we made 10 years ago.
- MatthewPhillips 3y agoYou really don't have to worry about these things until your module graph is > 100 modules. You are falling into "all or nothing" thinking here, because you need tools in some use-cases doesn't mean that a feature is worthless. Not needing tools for small projects and then needing them for large projects is pretty good tradeoff.
- galaxyLogic 3y agoWhat's the main benefit of import-maps? Reading the article it seems to me you must code the import map which basically defines aliases for your scripts. Then you must use the aliases to actually get access to the scripts you want to use. You must specify the absolute URL of the imports whether you use import-maps or not so what's the benefit? Does this reduce the amount of code? I'm sure there is a benefit I just don't see it on first reading of this article.
- randall 3y agoBasically package.json but without package.json. IE no bundle JS is back. There are still some issues, specifically with things like React, where it's kind of hard to guarantee if you use React, you'll get the same version if you use it in "react-relay" etc. Deno has been very informative on this. They're adding package.json support to the runtime as a polyfill, but I'm hopeful they can swing back to import maps fully over time.
- galaxyLogic 3y agoI see. So the benefit is that you externalize your imports into a file separate from you code. Right? I can see the benefit of that. It is like meta-data about your module, kept separate from it. And several modules can use the same imports-map, right? That means amount of code needed gets less. Thanks for the explanation. I assume I got it right, did I? Or now I wonder, must the imports-map be defined in the same module where it is used?
- WorldMaker 3y agoNo, you might have one "global" importmap in your HTML file and that applies to the entire graph of modules you load after that, which also means that you can "chain" importmaps and can also do things like pin the versions of dependencies of dependencies in that top level importmap. That sort of thing will need package-management-like tooling and dependency "packages" built for it, but that gets back to the idea that importmaps in theory are a lighter weight replacement for package.json/package-lock.json files.
- endorphine 3y agoFWIW Rails 7 uses importmaps by default, foregoing the need for a JS bundler. Coming from backend development, this seems like a huge win for me.
- S201 3y agoI built a new Rails app with importmap-rails last year and it was an absolute joy to work with. Being able to forgo all of the JS compilation bs was a massive simplification. I've wasted so much time in the past dealing with Babel and Webpack so finally being able to kick all of it to the curb was a joyous day.
- la_fayette 3y agoI am responsible for a large microfrontend portal application, which consists of multiple modules and applications, which are wired at runtime with module federation. The build process is handled by webpack for each mudule... I just wonder, if import maps could replace module federation now or in the long run?
- Jarreddebeer 3y agoI find jspm's generator pretty useful for creating an import map, there is also a cli version: https://generator.jspm.io/ https://generator.jspm.io/