Nuxt modules are the de-facto way of extending our Nuxt applications with new behaviors and functionalities. Have you ever built your own? Why would you bother with hundreds of modules already out there? Let's answer those questions together and see why making your own modules in Nuxt 3 can both help you have a deeper understanding of how Nuxt works while also paving the way for you to get into open source!
Nuxt 3 Modules and Open-Source
From:

Vue.js London 2023
Transcription
Hi vue.js Live, thank you for having me. And let's start with some numbers, shall we? So what do you think 2 million refers to? Well, I gave you that one, that's the number of downloads nuxt.js had over the last 30 days. What can 16 million be then? Well, you probably saw that one coming, that's the number of downloads vue.js itself had over the last 30 days. So alright, vue is 16 million, Nuxt is 2 million. What can 14 million be in that story? Must be something big. Well, turns out that's the number of downloads Nuxt modules altogether had over the last 30 days. Interesting stat, huh? Well, this can only mean two things. First of all, like maybe one person installed 14 million modules over the last 30 days. Or that on average, every Nuxt project uses seven modules. Math cannot figure out which one is true. But well, to me this definitely means that Nuxt modules are a central part of Nuxt. And I'd like to talk to you about them today. So let's talk about Nuxt modules. We'll see what they are about, how you can make some, but also more importantly, why you'd like to make some. And finally, we'll see how they can help you to get involved and get started with open source thanks to Nuxt modules. So let's talk about that. But well, first of all, I'm Lucie Haberer. I'm from France, as you probably guessed from my accent. I started my developer journey working with MediaWiki, the software Wikipedia runs on. But nowadays I'm working at Prismic as a developer experience engineer. I'm having fun at Prismic managing its company open source ecosystem, and Prismic is a CMS and page builder. Finally, I'm a proud Nuxt contributor and core team member. I've been working with Nuxt for almost six years now. So you start to see the link with this talk. But anyway, enough with chatting. Let's get to the talk. And I want to try something a bit with this talk to make it interactive. Just a bit. Don't worry. So I built this thing that works like a carot. Except there's no funny music and you don't get more points for being fast. But basically it allows me to prompt you about something. And the first thing I'd like to prompt you about is have you ever written a Nuxt module? So please, grab your smartphone and scan one of those QR codes to submit your answer. Alternatively, you can just follow the links if you're on a laptop. And well, let's see what it's about. Well, that's, well, not going to lie, that's what I expected. That's great. Most of us didn't write Nuxt modules here. And that's perfectly fine. So well, let's talk about them. What are Nuxt modules? And also, no worries. If you're new to Nuxt and don't know what it is, I will make it beginner-friendly so everyone is able to follow along. So Nuxt, as some of you might know, it's a meta framework for vue.js. And from its documentation, modules are nuxt.js extensions which can extend its core functionality and have endless integrations. Pretty powerful, huh? But basically, what this means is that Nuxt modules are like add-ons to Nuxt. You can add them and update Nuxt with that. And concretely, this means that you can make, like the first module to make your Nuxt website a PWA, up to like flashing connected lights in your room if there's an error with your code, for example. I certainly did that later. But well, and from a concrete approach, Nuxt modules are registered inside Nuxt config. So it can be a package name you have installed, a module that you have locally, or just the module code directly. And you can provide options to module using this direct syntax or specific config keys declared by module. So okay, that gives us a relative understanding of what Nuxt modules are about. But well, let's just add some details to that. First of all, as we've seen, there's like Nuxt module for everything. And talking about PWA earlier on, well, guess what? There's a Nuxt module for that. It takes care of all the gotchas related to making that possible, and it's easy to set up. Another random example, you want to connect to your favorite CMS, and you don't know what to do. Again, there's a module for that. It's maintained by a wonderful person. What more to ask? But okay, sure. There are also a lot of other great CMS modules out there, including our storyblock friend over there. So you can go check out any of them. But you got my point. With Nuxt Free, you want to integrate with something. Well, chances are that there's the next module for that. And you can go check out this website for the Nuxt.com for Nuxt modules for the most comprehensive list of modules available out there. So all right. Let's just now refocus on Nuxt Free modules. And I want to tell you something really important about Nuxt Free modules is that you can make your own. Don't believe me? Well, I can prove that. Chances are that if you're working with Nuxt, you're a developer. It happens that developers do write code sometimes. And well, Nuxt modules are made just of that. And I don't know, but between you and me, I can see a pretty straight line from you to Nuxt modules, so you can make Nuxt modules. All right. More realistically, why would you want to make Nuxt modules of your own, especially with so many modules already out there? Well, there's multiple reasons for that. First of all, as we've seen, Nuxt modules can do pretty much anything. And in that regard, they are an excellent way to abstract code from different projects and share it to you reliably. This works great if you're an agency making websites for others or an enterprise managing different internal applications. I personally did so when I was working as a freelancer, and I had some modules to manage meta-helpers, transform Nuxt plots in a particular way, or even output statistics about my project. Another great reason to make Nuxt modules of your own is to facilitate integration with the tool you use. Indeed, while there are modules out there for tailwind or sentry, why not be one about a specific tool you use? In that case, why not create it? Maybe it's an internal tool, maybe it's something else. I don't know. And it doesn't need to be super fancy to get started. So, all right. Sure. There are reasons to create Nuxt modules out there for everyone. But how do we do it? Well, that's what I'm about to show you. Let's learn how to create Nuxt free modules together, and we'll do that concretely. So, the best way to get started and to create a Nuxt free module is to use Nuxt C, Nuxt Free CLA. And with that, with this command, we can bootstrap a Nuxt module, and then we just have to install dependencies with whatever package manager floats your boat, and you're up and running. But because I don't have any trust in the Wi-Fi connection of this room, I already did that ahead of time right here. So, well, we launched Nuxt Free, we launched Nuxt C, and we ended up with that project. So, what does it look like? Well, let's take a minute to tour that product structure. First of all, we have a few directories. We have the source directory, that is the source code of our module. We have some tests by default. We can forget about those for now. And we have a playground directory. This playground directory is just the Nuxt application configured with our module locally that we'll use to develop our module. Then we have the package.json file here. So inside it, there's a few things interesting to note. First of all, it's already configured to be shipped properly to npm. You don't have to worry about that. Then if we look at the scripts, there's multiple of them, the prepack scripts takes care of building a module, and it's using this fancy Nuxt module build command. This is an in-house builder developed by Nuxt on top of Rollup and all the cool tools, and basically just making sure that your code is bundled correctly the way Nuxt wants it to be bundled to be used properly within the next project. That's great, because you don't have to go through the headache of configuring a bundle or learning one just to ship your module. Then we have multiple dev commands. Those are used to interact with our playground when developing our module. We'll make use of them later on. Finally, we have a ready script that is a default one we use on all the community modules at Nuxt. It's just like a one script, launch it all, and deploy it to npm, but you can fine-tune it to your liking if you need to. Regarding dependencies, well, we have NuxtKit installed. This is a collection of utilities provided by Nuxt to develop modules. We'll make use of it later on. And finally, we have NuxtModuleBuilder, which is providing the build commands we've seen before. Then on our project, we have multiple root files. You know most of them, I'm sure. You can fine-tune them to your liking. One thing, though, if you plan to share your module with the community, it's nice to stick with the defaults, as this allows your module to share a consistent coding style with the other community modules available out there. Let's now focus on the src directory. Inside it, we have this module.ts file. This is our module entry point. And as you might have noticed, it's a typescript file. Indeed. With Nuxt, typescript is the default for modules because it results in a much improved developer experience for end users. But no worries. If you're not comfortable with typescript, you can still develop modules in plain javascript. But as this will get us a bit off track for today, we'll stick with that file. But everything will look like plain javascript. No worries about that. If we now peek inside it, as you see here, there's already some boilerplate code in it. Let's explain it. First of all, we're importing a few UTTs from NuxtKit, namely defineNuxtModule here. And we'll make use of them later on. Then we have an interface. It's a way to describe an object structure in typescript. But as promised, no typescript black magic today, so we can safely ignore it. And then we have our module export right here, which makes use of the defineNuxtModule helper provided by NuxtKit. And our module is the object right here. So well, let's explain the structure of this object. First of all, we have the meta property. This is a collection of metadata related to our module. So name of our module, the config key we'd like to use inside NuxtConfig to resolve our module options. So if we check the playground here, we can see we can provide options for the main module key. There can be other type of metadata, like the module compatibility, but we don't need to know about those for today. Then we have the default key property here. This is where you can provide default options for your module that will get resolved against the options provided by your users to your module. Indeed, you can say that your module needs options to run. And if you don't want to provide all of them, you can set a default here. And finally, we have the setup function right here. This is what the code that will get executed by Nuxt when loading our module. It's a function that can be asynchronous if need be, but it's recommended to keep it synchronous, as otherwise it can have some performance headache. It receives two arguments, the options the user provided match against the default options we defined here, and the next object we can use to interact with Nuxt. And here we have some boilerplate code by default, but we can safely get rid of it, as we will come back later to it. So all right. That was a pretty dense section touring our module anatomy. And well, this is really the most important thing to know about it, but just recap what we learned. First of all, creating a module can be done with Nuxtinit. modules come with new defaults and a bundler by Nuxt. This is quite a new improvement in the developer experience of module. Nuxtkit is a set of helpers to develop our module, and modules are tasked by default, and finally, modules are defined using the new define-next-module helper also provided by Nuxtkit. So, as I said, just knowing the basic structure is already the most important part. But let's now try and do some few things with our module. But well, I'm a bit constrained with time today. So I only have time for one demo. So I want to ask you, do you want me to show you how a module can provide stylesheets and helpers to your project, or do you want me to show you how a module can integrate with Nuxt devtools, which is this new tool that we released with Nuxt earlier this year that is pretty exciting? So once again, please grab your phone and submit your vote, and well, I will demo one of those, too. All right, well, it's pretty even. But well, we have a majority for assets, so let's go with assets, and if we have extra time, we'll try to do the next devtools. We'll see. So, well, assets it is. And this is an interesting path to take, because it's maybe the most straightforward way for you to provide, to get value out of the modules you do. When we think about assets with a module, we think about the runtime directory, which is this directory, this right here, that I ignored until now. Inside it, you can provide any kind of assets you want your module to inject, whether it's a stylesheet, a view component, composables, or even 3d models, as we've seen before with Trezius. And, well, so let's start and do something really basic with it to start with. We'll start by just, like, try to provide a stylesheet. So right now, my next application, it has a white background here. We'll create a style.css file. We'll add some style to it. So I go, like, background. No, well, not background. There's a birdie. Background. Red. And now, once we have this style.css file, how do I inject it with my module? Well, we go back to our module here, and we need to do two things to inject it. First of all, we need to create a resolver. So to do so, we have already imported the create resolver helper from NextKit. So we'll go, like, const resolver equal create resolver. And we'll provide it with our module, like, the current file path. So import.meta.url, which looks a bit like dark magic, but basically, we're just creating a helper that helps us to resolve paths consistently within our file system. So once we have this helper, we can just access next.options.css, and we'll just push our we'll just push the path of our css file. So we go resolver.resolve, and we'll provide it with a path. So we'll go, like, inside runtime directory, and we want our css file. So now I can save that. Go back to my terminal, give a restart to my next server. And while Next is taking its time to restart, I'm on Windows, everything is still on Windows. What we can notice here is that to inject our css file, we just access next.options. Indeed, Next modules can read and update next.options, like, as they want from NextConfig. And so now, if we well, Next should be done restarting. You can now see we have our big flashy red background injected inside an application from our module. Great. So. So let's keep working with our module for a bit, and let's see how, for example, we can inject a plugin from it. So Next plugins are a thing in Next that allows you to inject things inside your runtime application. So default module starter comes with one. I just added this small, like, formatting utility here for the demo purpose. And so how do I inject this module inside my application for my module? To do so, I need to do three things. First of all, I need to resolve my plugin path. So again, I use my resolver, and I go resolver.resolve. And we just check the path for our plugin. So again, it's runtime for our slash plugin. We can get rid of the css extension. And then we need to go next to transpiler plugin. So go next options.build.transpiler.push, and we push our plugin to it. And finally, we make use of the add plugin provided by NextKit to tell Next that you need to load this plugin. So go add plugin, plugin. And now I can save all of that, give Next a restart. And again, while it's restarting, this time it should be faster because it's a bit warmed up. So in my playground here, I just made a log, like if it's available at my module, then I just make a log of it. And I can go back here, inspect the code. And as soon as it's loaded, we shall see our code showing up. If Next is collaborative. Okay, here we go. You can see here inside my console, I have the log of the formatting utilities we injected from our module. So, okay, well, that's the interesting thing. Let's do a third one. With Next, you might be familiar with auto imports. When you have components inside your imports directory, they are auto imported. You don't need to import them. Well, modules too can provide auto imports. So I created this imports directory inside my runtime directory here with a few utilities. Just a library, something that predicts a bitcon value. So thank you for liking my silly jokes. So how do I add this, all those utilities to import them in my next application? Well, to do so, I can just use the add import dir utility, also provided by NextKit. To it, I just need to do a resolver.resolve once again to resolve a find path. And I just give it the runtime and forward slash import. And this will make everything in this folder auto imported inside my next application. So here again, I can give my Next a quick restart. I can go check out my app here. I will uncomment this line right here. So right now, we see there's no type definition. Well, actually, here we go. We now have type definition from them because Next auto imported them for me and created this type definition for me. And if we go back to our browser here, to the console, we'll see we have the pong for the ping pong, the lower midsum, and the bitcon value for the next roundup. So all right. So this was an example of what modules can do. Of course, we can do a lot more, like adding auto imports for composables, adding auto imports for components, interacting with Nitro, you can do really powerful things with that, or also using Next lifecycle hooks and more. And many more. But don't fear of missing out. We documented plenty of use cases on Next module documentation. And you'll be able to follow that. So that's not all, folks. There's one last thing I need to talk to you about. There are some extra perks to learning Next modules. And the first one is that by learning Next modules, you'll get a deeper understanding of how Next works, its internals and behaviors. And this will allow you to troubleshoot Next issues you have with Next in a more easy way. And related fun fact to that, Next itself is partly made out of modules and relies on module APIs. Another thing that by being familiar with Next module structure, this allows you to have a better understanding of the module you use. In that regard, feel free to go ahead and have a look at the source code of the module you use. For example, if you have a look at Next color module source code, we can see it's using this neat pattern of using a Next alias to inject its options inside Next runtime. Well, that's how I learned a lot about Next, really. And you can do, too. Second thing, now that we're familiar with Next, our Next modules work and everything, this all empowers you to contribute to the ecosystem. You found a bug while using a module? You can fix it. You're craving for a feature on your favorite module? Go and append pull request. This community is really friendly to newcomer. And personally, that's how I became comfortable with open source and started my journey. And you can do, too. And if you don't know where to get started, again, just head to next.com for a module for a comprehensive list of community modules available with Next 3. So, that was my talk. Next modules in open source. I really hope you learned a few things about Next modules. There are ways to extend Next functionality. And basically, you can make Next modules for your team, your company, or for the whole community. Next is structured with Next 3 and comes with an improved developer experience. Learning that structure gives you a better understanding of Next and allows you to get involved in the community. We can find all the resources about this talk, slides, source code, transcript and more at luci.fred. You can follow me on Twitter for more about Next and more of my nonsense. Thanks, everyone. Thank you. Thanks a lot, Luci. That was a really interesting talk. Feel free to go sit. And now let's dive deep into some questions. So the first one is... Just a second. All right. It's reloading, but since it's reloading, let me ask my question. How... Like, do you have some point when you decide, okay, now I need to create a Next module? Okay. Yeah. Of course, you don't need to jump straight away and create a module for everything because this would be overkill. As I said, like, modules are great to abstract things. But it's like whenever you want to abstract things, it's not coming for free. It has a maintenance cost over it. So you have to ask yourself, well, is it worth it to abstract that? And if the answer is yes, then modules are an option for you to abstract this code and share it across multiple projects. Of course, if you're just a company, like, making just one eCommerce website, there might not be a lot of use case to creating modules because you're only working on one Next project. But if you're working in a bigger company with multiple Next projects or an agency making websites like on a daily basis for multiple clients, then there's an opportunity for you to create modules because you might end up using the same kind of code. Yeah, totally makes sense because otherwise you just spend time on abstracting all the logic and you actually don't gain anything from it. Okay, now we have some more questions. And the first one is, what's the weirdest Next module you've ever seen? Well, I guess it's one of the modules I made. It's called Next Hue. And basically, I don't know if you know, at my place, I have some Philips Hue light bulbs that are basically connected lights. I can make them blue, red and everything. And basically, I created the module that when there's an error within my Next application, it flashes those lights within my room in red, of course. And well, when I develop Next, it can do that. That was pretty fun to develop and pretty useless also. That sounds fun. The second one is, what is your favorite module you've created or contributed to? Well, of course, it's Next Prismic module. It's a great module you can use to integrate with Prismic or CMS. And well, it's really big. Okay, kind of expected answer. Next one is, how much do you worry about Next introducing changes that will break modules? Well, inside Next Core team, we really value a lot the module ecosystem because that's what allows Next to integrate so well with so many technologies. And so, we follow the same there and we really try our best to not introduce breakage for modulators and things that will break the module because this will eventually hurt the whole ecosystem. So, I know there has been a bumpy road to update from Next 2 to Next 3, and we're still working on that to make that upgrade path easier for everyone. I think Daniel will talk about that later on today. But yeah, well, we take that seriously and we try to not make maintaining module like an asshole for everyone. Okay, and in practice, how often that happens that you have some breaking changes you need to deal with? Well, Next 3 was obviously a big breaking change because it was introducing Next 3 view free support and also revamping everything from the core. Moving forward, we'll have more new major releases at a faster pace, like within once a year perhaps, but those will be more minor breaking changes and we'll have some automated way to make the update for you. Okay, thanks. The next one is, if already using a framework such as Quasar, at what point does it make sense to switch to Nuxt? Well, no, frankly, I'm not really familiar with Quasar, so I'm not sure I can give a straight answer to that. Okay. Sorry. No worries, then let's move to the next one. You hyped people to create Nuxt modules because the next question is, what Nuxt module do you believe is missing to create? Well, with Nuxt 2, Nuxt 2 lived for many years and so we had a really, really vast module ecosystem with plenty of modules that were, most of them were really great. With Nuxt 3, the ecosystem is still more tiny today, so there might be tools that we add like a Nuxt 2 module for it that we don't have yet a Nuxt 3 module for it. In that case, if you notice one of them, I know we're working on the off module right now, like you're free to join the effort and create that modules and migrate it to Nuxt 3 so that everyone is able to take advantage of it again. Okay. Now you've got some ideas. The next one is Nuxt compatible with vue 2? Well, Nuxt 2 is compatible with vue 2. Nuxt 3 is compatible with vue 3. And well, we don't plan to make Nuxt 3 compatible with vue 2 for various reasons, which I'm happy to discuss with you if that's your issue. Makes sense. Totally. Next one. Do you think vue should have a module system like Nuxt? Well, vue kind of has already a module system, which is called the plugin system that allows you to integrate with vue and create integration with it. For example, the Prismic module we provide to Nuxt is actually just mainly injecting a vue plugin we have that integrates Prismic with vue. And it's doing that under the hood along with some like other Nuxt customization. So if you want to create integration with vue, then you have to check out vue plugins, I guess. Or if you're thinking about like a build time integration, then maybe you want to have a look at vite plugins. Okay. Thanks for that. The next one is, does runtime directory have a special meaning in this example? Well, the runtime directory is more of a convention. However, with the Nuxt module builder command we have, it applies some specific configuration to its runtime directory. So it does some like transpilation of everything that's in it when building your module. And so while you kind of have to stick with it for that reason, and well, it's maybe configurable, but I won't talk more about that. Just a convention. Thank you. And a lot of questions, but this is a final one. All kinds of modules are posted on the website nuxt.com slash modules, or they need to pass something like a code quality check? Not really. Basically, like if you create a module to integrate with a tool because there's not one yet and you want to make it a community module, you just have to reach out to us and we'll help you like make that module an official community module. To do so, you just have to open a ticket or like an issue on GitHub on the Nuxt module GitHub, explain what you want to achieve and we'll help you when I get there and like make it like a Nuxt community module if you want to share it with the broader community. Okay, makes sense. But if you don't know where to get started already, you can create Nuxt module by just prefixing your module with Nuxt-IPHONE on npm. And well, we recognize those modules as community module even if they're not under the nuxt.js organization on npm. Makes sense. Our people here just want to break things so they're afraid. Nice. Thanks a lot, Lucy, for this interesting talk. Welcome. That's all from the questions. Just feel free to ask more questions in the speaker's corner if you have them. And yeah, make some noise for Lucy.