export syntax) directly in the browser.
This is based on my blog post: Super Simple Start to ESModules in the Browser
[0:20] Then here, I'm going to need a script tag and inside of that script tag, I'm going to want to import. What are we importing? This appendDiv function, so we're going to import appendDiv from...This is going to be relative to this file and I'm just going to put them side-by-side.
[0:35] We're going to say from, and that filename is append-div.js, so we'll say append-div.js. Then, I want to appendDiv. The contents of my message here for that Div is going to simply say, "Hello from inline script." I'll save that. We'll call this index.html probably next right to our appendDiv. Then, I'm going to open that in my browser here.
[1:25] But it's treating it as a script, rather than a module. There are various differences between scripts and modules. One of those differences is that a module can use other modules and use module syntax, whereas a regular script cannot.
[1:57] Basically, what we need to do here is we need to serve this file on an HTTP server. If you have Node installed, you should be able to run npx serve and that will start up a server.
[2:27] If we look at our network tab and refresh, then we're going to see first, the browser request localhost which is just going to get the index.html served up by that serve module that we're using. Then, our index.html is going to request this appendDiv, and that's what the contents of that looks like.
[3:04] I'm going to import appendDiv from append-div.js, and then we'll call appendDiv with "Hello from external script." We'll save that as script-source.js right next to this. Then I'm going to go back to my index.html and want a new script tag type module with the source pointing to script source as a sibling of this index.html. We'll refresh here. Now we get "Hello from external script."
[4:00] For that same reason, we can't expect to leave the .js on here and expect that to work either. You'll notice that the "Hello from inline script" is no longer appearing here because we're getting an error loading appendDiv.
[4:29] While in node, you're able to leave the .js off and node can resolve that to the right file. In the browser, you can't do that. You have to make sure that the server is going to respond with the correct file based on the path that you give it.
[4:58] We'll call appendDiv "Hello from async script" and then we'll export go. We'll save this as async-script.js. Then I'm going to go to my script source and inside of here, I'm going to do a dynamic import, so that I'll get my async-script.js. Then I'll have my moduleExports object here, and I'll also have an error here. In the event of an error, that could be that the script erred when we were trying to evaluate it, or maybe that script doesn't exist, so the server sent back a 404.
[5:39] In any case, there was some error loading and running the module. I'll go ahead and add a console.error. "There was an error loading the script." Then we'll just go ahead and throw that error so that it propagates up. Then in the success case, we're going to add a moduleExports.go. We're going to be calling this go function.
[6:01] If we save that, then refresh here. We're going to get hello from our inline, from our external, and from our async script. If we have some error in here, like we leave off the extension, and so our server doesn't send back anything received "There was an error loading the script." We see that "Uncaught in promise TypeError -- Failed to fetch dynamically imported module."
[6:21] The reason for that was our server 404 because there is no resource at that URL. We also get the same thing if there's some sort of failure running the scripts. If we say, let's call foo. We refresh here, then we're going to get an error loading the script. In this case foo is not defined.
[6:38] In either case, whether loading the script in the first place is the problem, or there's a problem running the script, our error from our dynamic import will get run. There's one last cool thing that I want to show you here, and I'll do it in the script source.
[7:10] Here I've added an import for d3 from the "unpkg" service, and I added the query string module, which will update all the module imports to use unpkg links. Let's go ahead and copy this. We'll paste it here, so you can see what that's doing here. It is more unpkg URLs with more modules. We can get all of d3 loaded. Let's save this. We'll refresh.
[7:34] You'll see that it takes a little bit of time and that's because d3 is quite large. It's because we're loading all of these scripts. Now HTTP/2 with server push will make this a little bit better, so we don't have to make all of those requests. The server can keep on pushing those to us.
[7:51] That's a lot of modules and I don't expect us to be stopping or bundling anytime soon. This illustrates the point that what you put between these two quotes is a URL that resolves to some module that's served by some server.