Alpha preview: Modern JavaScript in Rails 7 without Webpack

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

"we can ship a bunch of tiny files and it doesn't have impact on performance until you have hundreds of files"

$ find node_modules/ -name \*.js | wc -l
27161

oh well :(

(I do understand the proposed approach eliminates most of those, but that's still only until you add any js framework)

๐Ÿ‘๏ธŽ︎ 7 ๐Ÿ‘ค๏ธŽ︎ u/himdel ๐Ÿ“…๏ธŽ︎ Aug 17 2021 ๐Ÿ—ซ︎ replies

I applaud all efforts to reduce the complexity of JavaScript. The stories Iโ€™ve heard of maintaining npm-based codebases are horrifyingโ€ฆ

๐Ÿ‘๏ธŽ︎ 16 ๐Ÿ‘ค๏ธŽ︎ u/mperham ๐Ÿ“…๏ธŽ︎ Aug 16 2021 ๐Ÿ—ซ︎ replies

This should really be on /r/rails instead of /r/ruby since it's about Rails specifically

๐Ÿ‘๏ธŽ︎ 2 ๐Ÿ‘ค๏ธŽ︎ u/armahillo ๐Ÿ“…๏ธŽ︎ Aug 16 2021 ๐Ÿ—ซ︎ replies
Captions
this is a alpha preview of how rail 7 is going to allow you to create wonderful web applications using modern javascript without webpack or any other form of bundling or transpiling for the past several years rails has been shipping with webpack as the default way of writing javascript we've installed all the javascript ecosystem tooling package.js and node modules and whatever else have you straight into all new rails applications and that is a lot of complexity that for some applications is warranted and for a lot of other applications isn't warranted anymore and it is really this anymore part that i want to dig in to for a second um the the javascript ecosystem has advanced quite a lot uh particularly recently with some major new milestones that have been passed that has made this all possible so i wrote a blog post going over some of those major milestones and why now is the time to go much simpler with javascript and why it's now possible to do so i'll link that in the description below but briefly the three major points i cover are the fact that uh es6 is now available in all the major browsers microsoft has killed off the last holdout ie 11 it's been sunsetted so now we have a microsoft edge we have chrome we have safari we have firefox who all support es6 and es6 includes a javascript moduling system called esm which is really what we need to escape the transpiling step um together with es6 that it's just a wonderful javascript that's available natively in the browser now you don't need to transform the javascript you want to write into something else that the browser can execute second http 2 is now ubiquitous which means that the bundling step where we take a bunch of different files and turn them into one master file one huge file is no longer necessary we can ship a bunch of tiny files and it doesn't have an impact on performance until you get to hundreds and hundreds of files perhaps and in fact it has quite a lot of benefits in terms of caching when you expire just a tiny file and leave everything else still cached and finally there is import maps which allows you to refer to javascript modules with logical names rather than using the digest stamped file names that you would perhaps otherwise have to do which makes it far more cache compatible those are the three main reasons i go over in that blog post but i kind of admitted one key additional component which was the answer to yeah that's all good and well but what about node modules how are you going to allow people to rely on npm modules there's so much javascript libraries and tools and whatever out there we're not going to go back to downloading individual files and storing them in gems or in vendor or whatever the answer is javascript cdns there is a ton of innovation happening right now in javascript cdns there's things like skypac js deliver unpack esm dot sh that make it possible to have access to the entire npn library through the browser they simply compile everything and make it available on cdns so you can refer directly to links for these libraries without compiling them yourself which is really what enables us to skip the the whole installation of node and everything else because you're never going to compile any of these libraries yourself anymore you're just going to rely on them directly from the browser so those are the advances in the the javascript uh scene and the consequences for that for rails as i said is we can now ship rail 7 without webpack by default you can still use webpack if you'd like a dash dash webpack and you have everything as it was before but by default there won't be a webpack set up instead we will use a new set of gems that allows us to take advantage of these things like import maps and and so forth and i'm going to show that in this video in addition to that we're going to ship with hot wire by the fault instead of turbo links been shipping turple links for many years and hot wire includes a new and improved version of that called simply turbo and hotwire also includes a tiny javascript framework called stimulus that will be quite enough for lots of applications that they won't need to rely on anything else but as i said through these javascript cdns it's very easy to pull in other libraries and that'll work just fine and in fact this setup will work with everything from view to whatever else have you i'll show some of these examples in the demo that follows now so i'm going to demonstrate how all this works um using a very alpha version of all this new gear it's relying on a pr that has not even been merged into rails main yet so expect all of the specifics here to change quite a lot before it is time for release of rail 7. you probably won't be able to follow along with this tutorial in a few days from now command by command but it doesn't really matter what i'm interested in showing is the general feel of this new system and the power that it has so let's start by building a new rails skeleton as you can see it no longer installs all of the node stuff it runs a couple of installers from a few gems import map dash rails and hot white dash rails that simply alters this skeleton to to work with the new gear so let's uh set up a simple scaffold just to see what we have um pre-configured now because we've been running those two installers and um that is basically all we need to see the basics in motion here um i'm gonna start the server and we will have all the hot wire gear pre-configured and i'll show you that the main thing you'll be able to see here is that we are running the new turbo you see i'm looking at just these fetches here and as we jump back and forth between the links you can see that this is actually turbo running so let's go back and see how all this is set up you can see if i have a look at the elements we have now an import map that describes all the libraries and frameworks that we're using for this application you can see turbo rails is set up here we have stimulus we have a import map autoloader for it and some default controllers then there's a shim here that makes it such that this whole setup works with browsers that do not natively support import maps such as safari and firefox import maps are natively supported in chrome and microsoft edge but this shim is 7k i think and does the work for these other browsers and then finally we import this application which module which is essentially our entry point and i'll show you that as well so let's jump over to the editor here and i'll show you how this is all set up first we have a look at the application layout and you can see we're calling javascript import maps tags this was automatically set up by that installer for import map dash rails and that sets up the import map itself off a configuration object i'll show you in a second it sets up the shim and it calls the import on application so the import map itself is configured here in a special file which currently lives in initializer and which currently requires that you restart the server every time you make a change which is really annoying so i'm going to move this to config slash import map dot rb in the near future and make it reloadable but you can see here what this map does is essentially define all the modules that we want to depend on and make this translation of how esm should be able to find these when we make the bare lookups that hot wire hot wired slash turbo dash rail should point to turbo.js and turbo.js is made available in the asset pipeline through the turbo dash rails gem so that is a local file being referenced here you'll see that this is then sort of essentially all our load paths and then if we take a look at application js which is the file that's being called as our entry point you can see that we are importing two of those import mapped modules here a stimulus input map autoloader which essentially looks at um everything under controller slash in the import map and autoloads all those controllers automatically i'll show you more about that in a second and then it loads turbo rails i showed you turbo already running so what's neat here is that it's so easy to add on to this setup in this system i'll show you that by adding some more default rails features here from some of the other rails frameworks we can start by adding action text and we will do that by simply calling action text install this is an existing installer that has now been updated in rails main to use esm modules um so let's run that we've got to run bundle as it tells us to to get image processing going and then we're going to run db migrate to get the additional tables for action text then let's hook that up to our application here you can see first of all we've added tricks and rails text to the application entry point and they've also been mapped in the import map so they're available in both places but let's hook up that this post is going to have a rich text content and then we change the all text area to use the rich text as well and then as i said we gotta well don't have to restart the server because we haven't started yet we're gonna start the server now and then have a look at how that looks first you'll see here that the import map has been extended to now also include tricks and action text so if we go to make a new post here you'll see that we have the tricks editor available we can write rich text and then we can mark it up here and then this actually even works with active storage out of the box active storage javascript has also been updated to work with esm so we can upload a file here i'm just going to drag something in oh look at that um gonna save it and boom there you have it um that was all that was required to set up action text use a tricks editor have it all work off esm in that application js module well that's pretty neat but that's of course just frameworks that are included in rails already so let's have a look at something that we're going to make ourselves using stimulus first let's have a look at the stimulus controller that is essentially just an example controller that ships with this setup it's the hello controller and then let's hook that up to a page anywhere we're just going to use the post index data controller slash or equals low um and then let's see if we can get that essentially running we're just actually going to delete this post there we go okay hello world that's pretty neat that shows us that we didn't have to do any additional configuration because if you have a look at the import map you'll see that we're automatically pinning all of the controllers under controller in this directory and they're also automatically picked up whenever we make a change and you can see here uh what's neat is that there's no compile step there is nothing in the back sitting to to watch this we're simply serving these text files directly to the browser and the browser picks up the changes this is also true if we add another file let's do a goodbye controller here which is essentially the same thing and then goodbye world a little sad um adding this down here as uh goodbye and then let's see boom that is added on as well so you see we're automatically picking up these files nothing needs to be configured because we have that pin that runs on the entire directory automatically mounts these things all right well let's do a slightly more interesting example that relies on a second library outside of what just ships with stimulus we can make a little md5 controller here under utilities utility is just showing you can nest these things as well uh we'll make an md5 controller and then i will just copy in this stuff here we don't need to connect anymore this one is going to work off of a click so we're going to make a convert action that takes an event uh first of all we need to cancel the default click so we don't go anywhere and then we're going to go have a look at that targets text content and we will convert that over to a md5 version of that so let's do md5 well of course we don't have an md5 library yet but let's set it up then we're going to import that um and then we need to declare that in our import map so let's go here and we're going to add a new library directly i'm just going to copy in something from let's take it from skypac skypac have these really neat easy to remember urls but they do some redirecting so in production you'll want to change that to something else that is pinned but we can just start here for now okay so now we have uh the md5 controller using a separate library that we've configured in our import map so let's hook that up here so that we can actually do something with it i'm just going to copy paste in a usage of that you see we map utilities dash md5 to that controller we just set up we're going to have a link that just called hash that and that's going to have an action that calls that convert action that we had on the md5 controller so we need to restart the server as i said this won't be necessary when we're all done with this and this is set up proper but for now it is such that we pick up that md5 library so now we have this new link and if we click it look at that hashtag again if we go back and have a look at the import map you can see that we are relying here on skypack to find it if we go have a look at everything here you can see that skypack is doing this lookup and then it's turning that into a few other fetches as well but that's all happening behind the scenes okay that's pretty neat um but an md5 library hooked up is not exactly the most exciting thing in the world so let's set our sites a little higher let's try to make something with view okay we're going to go back here and first set up view neatly this is set up here so we can just uncomment it now view is available to be imported we'll do something a little more interesting here we'll set up an additional directory here just call components and we will have some view components dot js and i am just going to copy and paste in some view components that are from the view js site so you can see what's going on here um we are importing view again from this import mapped bear identifier view and we need to link that up in application so we're going to import that here as well actually first we need to map it so let's map these new components we're going to do another one of those pinholes from javascript components and we can actually map it under something else we can just call it comps so you can essentially rename the file structure into what you want that to be looked up as the files themselves are still going to match what the files are but this is just an example showing how this could work so we're going to do comps and then we're going to do view components great and then we need to have the html that is needed for those view components let's paste that in you can see there's just one that's iterating over and then there's one that's calling a method for reversing the message since we've added again to the import map we're going to restart and then let's have a look at that whoa here you go again if you take a look at the import map we've added the new controllers are here the new components is mapped we have view lined up as well this is pretty neat it didn't take very much to do that and of course you can make it far more intricate and if you want to have you work together with turbo you're going to have to do a little bit more work of course to instantiate the view components once turbo load is called but we will leave that for an exercise for later day let's hit it in another library that's uh commonly used here let's add in some d3 i think we have that mapped up as an example yes this example uses esm which has this really neat feature of being able to bundle um libraries that have a lot of dependencies d3 have a lot of different components if you just look that up natively through skypac or something else like that it triggers quite a few requests but esm does sh you can pass a question mark bundle and it'll bundle it all up into a single file which is quite neat so we'll add another component here called d3 component dot js again i'm just going to paste in an example that i found somewhere it doesn't really matter what this code is what matters is that we are selectively importing just select and zoom from d3 and we've already put it into our import map so let's add it to our application js as well it's still on the comps it's the d3 component and then we need the svg that this d3 component works with this is just this simple square that we can use um again we added d3 we restart we have another look here and there you go there is a d3 component all set up we have a look at the network here starting to include quite a lot of stuff uh locally here we're not running http2 so we're not getting everything lined up but here you can see the d3 bundle being loaded pretty neat um but we don't have to rely on just having a single entry point for example on this page right now we are including um all the javascript stuff the tricks and action text setup to be able to do this editor but we don't really need it on this index page so what if we split those two things up into separate bits let's do that now so let's go to our application.js here and look at tricks and action text and we're gonna take these out and we're going to create a new file called rich text dot js paste that in here we need to pin it just like application we're gonna pin rich text and then we have to include it selectively so we're going to set it up such that we can add to the head in a different template here we're gonna add to the head in the form template because that is where we need these additional bits pasting that in we take the head content and what we need to import here is one of the things that was called automatically by javascript import maps tags with just application but here we're calling an import module tag for rich text so let's save that and have a look we're gonna have a look here and see that we no longer include tricks yep trucks tricks there's no tricks but if we go here well then something is not lined up um let's see what's actually going on here do we still not have tricks no we don't uh let's go to the import map we set up rich text we try to include it oh i don't think i restarted after i added the rich text import map see that's pretty annoying you will definitely want to get that fixed i hope to get that fixed shortly now you can see that we're loading tricks and we're loading um action text on just this page and if we go back here you can see that we don't have that so this is a way to sort of do selective loading all right one final test here one final example that i can show you which is kind of funny because when i wrote this up in the blog post i thought you know what no one's going to do this this isn't even possible but it is let's make a react component so the thing about react is if you want to use jsx you of course have to do compilation but you can actually do react without jsx so that is what we're going to try to do here we're going to set up the import map with react and react dom boom we had another twin i just have them set up on skypac right now and then we can go create another component here called react component js and i'm just going to paste in the simplest hello world example uh as you can see here we're not using jsx's is a little more cumbersome but it is certainly doable it's certainly workable i'm assigning that just to e so it's kind of a little bit more easy to use we have to add this component to here components react component and then we have to add the fact that this is expecting a reactive over on this page here id equals react and then we should see hello world um let's do one two three we have a few hello worlds and then we need to restart again because we've added the react pins would you look at that hello world one two three generated by react and again the neat thing is there is no compilation step on our side here so if we go back and we change hello react and go back here is of course instantly available so that is the new path that i've been exploring there's a lot of stuff left to do there's a lot of weird bugs i'm still working on things like module preloading to improve performance but this is very promising i'd say clearly much nicer to work with faster to set up no compilation times no webpack configurations and so on and so forth again not necessarily for everyone there will be more complicated things as i said if you need to use jsx then this won't really do it for you but plenty of people will be able to use this i am looking into converting hay to use this we essentially just use stimulus with hay and a few other things so we should be able to convert this over and i'll continue to work on this for the release of rail 7 whenever that is going to be all right that's it hope you enjoyed this presentation and follow along as more updates come
Info
Channel: David Heinemeier Hansson
Views: 31,805
Rating: undefined out of 5
Keywords:
Id: PtxZvFnL2i0
Channel Id: undefined
Length: 27min 5sec (1625 seconds)
Published: Mon Aug 16 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.