Writing Your First Vite Plugin

This ad is not shown to multipass and full ticket holders
JSNation US
JSNation US 2025
November 17 - 20, 2025
New York, US & Online
See JS stars in the US biggest planetarium
Learn More
In partnership with Focus Reactive
Upcoming event
JSNation US 2025
JSNation US 2025
November 17 - 20, 2025. New York, US & Online
Learn more
Bookmark
Rate this content

Vite is an essential tool for modern front-end development. We use it daily, but we know little about its inner workings. We write  .jsx or .vue files, but how do they get transpiled into .js files? There's likely some magic behind Vite's plugins, but how do they work?

In this talk, we'll start by creating a simple plugin and progress to more advanced ones. After this session, you'll understand how Vite plugins work and the overall flow, even without prior knowledge of Vite plugins.

With this new knowledge, you can perform computations during the build process that don't necessarily occur at runtime. This can naturally result in faster runtime performance. In some cases, the computation results are included directly in the bundle output, reducing the final bundle size (as you don't need to include the data or logic for the computation). Additionally, you can improve the developer experience by automating certain manual tasks.

This talk will introduce you to something you hadn't considered learning before. It will make you realize that it's not as difficult as you might have thought, and hopefully, this talk will boost your confidence in learning.

This talk has been presented at React Summit US 2024, check out the latest edition of this React Conference.

FAQ

VIT is a dev server, transpiler, and bundler used in front-end development to convert TSX and JSX files into JavaScript, which browsers can understand.

Rollup is a bundler that consolidates a chain of imported JavaScript files into a single file, helping to simplify the structure and improve performance.

VIT uses plugins to handle image imports by transforming them into JS modules. Rollup and VIT share a similar plugin architecture, allowing existing Rollup plugins to be used in VIT.

A VIT plugin typically includes resolve ID, load, and transform functions, which handle file identification, loading, and transformation respectively.

Yes, VIT has adapted Rollup's plugin architecture, allowing the use of existing Rollup plugins within VIT projects.

A virtual module allows handling static data at build time, enabling the bundler to include computation results directly in the output without the original business logic.

A VIT plugin can transform code using the transform function, which processes and modifies the code based on specific conditions or requirements.

The resolve ID function determines whether a plugin can handle a specific file or module by returning its ID, indicating its capability to process it.

JSON.stringify is used in Rollup plugins to ensure that the output is correctly formatted and meets Rollup's requirements for representing data.

You can reach out to the speaker, Eunjae Lee, on Twitter at @Ninja_Lee for more questions about VIT plugins.

Eunjae Lee
Eunjae Lee
19 min
22 Nov, 2024

Comments

Sign in or register to post your comment.
Video Summary and Transcription
Let's talk about writing your first Vip plugin. VIT, rollup, and Vip plugin are important tools in front-end development. Rollup is a bundler that can bundle JavaScript files into a single file. VIT goes through all the plugins and transforms files to JS modules. VIT and rollup have similar plugin architectures, allowing the use of existing rollup plugins in VIT. I'll discuss three plugin properties: resolve ID, load function, and more. Let's take a deeper look at the transform function. The resolve ID function determines the ID of the file or module, and the load function reads the file or module and returns its content. The transform function actually transforms the file or module into something else. For example, it can modify the code depending on the file extension. We can transform the result object into code by using object keys and map. This allows us to extract specific data and include it in the output. By making the code flexible, we can add additional information like 'built at' and utilize it for various purposes, such as displaying branch name or commit hash during deployment. You can implement various functionalities in the Vip plugin, such as reading Markdown files, implementing file-based routing, and creating domain-specific languages.

1. Introduction to VIT, Rollup, and Vip Plugin

Short description:

Let's talk about writing your first Vip plugin. VIT, rollup, and Vip plugin are important tools in front-end development. Rollup is a bundler that can bundle JavaScript files into a single file. VIT goes through all the plugins and transforms files to JS modules. VIT and rollup have similar plugin architectures, allowing the use of existing rollup plugins in VIT. I'll discuss three plugin properties: resolve ID, load function, and more.

Hello, let's talk about writing your first Vip plugin. In this talk, I'll talk about VIT, rollup, Vip plugin, and some examples.

My name is Eunjae, I'm from South Korea, currently based in France. I'm working at Cal.com, and I used to work at these amazing companies.

VIT is a very important tool in our front-end development. It's a dev server, transpiler, bundler, and it's everything. We write TSX and JSX, and these are the files that browsers don't understand. So we have to turn them into JavaScript files. And how do we do that? Probably VIT is doing something, and we know that Vip plugin is doing something.

But before we dive into Vip plugin, let's take a look at rollup first. Rollup is a bundler, and it has a huge impact on JavaScript library ecosystem. For example, we have source slash main.js, which is importing a.js, which is importing b.js, et cetera. We have this huge chain of imports, and rollup can bundle everything into a single file.

For example, we have main.js. It's importing message from message.js, and we're console logging message. And message.js is exporting hello world. And when rollup bundles it, we have this, dist slash output.js, and hello world is directly embedded here. And we don't see import or export statement, because rollup bundles everything into a single file. And with VIT, we import image URL from image.png, and when we run this code, VIT goes through all the plugins that are registered to this project. And it asks, can you handle that png? Can you handle that png? Can you handle that png? Oh, you can handle it. Then you should read the file and transform it to a JS module.

Rollup and VIT has very similar plugin architecture. Actually VIT adapted rollup's plugin architecture from the beginning. So I believe that's one of the biggest reasons why VIT has been successful from day one. Because we can use any existing rollup plugins in VIT. The plugin is an object with optional properties. And today, I'm going to talk about three of them. First, resolve ID. It returns the ID, and it can also interpret it as, can you handle it? So if this plugin returns the ID, it means it can handle it. Then it goes to load function, which literally loads the file or the module.

2. Understanding the Transform Function in VIT Plugin

Short description:

Let's take a deeper look at the transform function. The resolve ID function determines the ID of the file or module, and the load function reads the file or module and returns its content. The transform function actually transforms the file or module into something else. For example, it can modify the code depending on the file extension. In a real example, we can transform code to always consider it as production, removing unnecessary else clauses.

And then it can go to transform function, where you can transform the module into something else. Let's take a deeper look.

Resolve ID. What is the ID of this file or module? And here, ID means library name, file path, etc. We have this example. And when resolve ID is called, image.png string is passed as source parameter. And we can implement it like this. If source ends with .png, then we return source. By returning something, it gives the signal that this plugin is able to handle this source. And then it will go to load function.

And if it returns null, then it means, I don't know, maybe some other plugins can handle it, but not me. And load function reads the file or module and returns its content. Like, if we implement this load function in a stupid way, it's going to look like this. So it reads the file and just returns the file content. But in reality, it's more complicated. And transform, it literally transforms the file or module to something else. For example, if ID ends with .view, or if ID ends with .jsx, we can do something with the code and return the result. So if we have this Vue.js code, we can return this. And if we have this React code, we can return this. So when we talk about transpiler, actually, things happen in this transform function.

Let's do the real examples. We have this code. Console.log Node-inv, process.inv Node-inv. If that's production, then Console.log, this is production. If not, this is not production. We write this code, but in the end, when we deploy this code, we want this Node-inv to be production, right? And it means the if statement is always true. And it means we can get rid of this else clause. So we can rewrite this into this code. But this doesn't happen automatically. It takes our work to transform the previous code into this one.

3. Writing a Plugin to Transform Code with Rollup

Short description:

Let's write a plugin that transforms code using Rollup and rollup.config.js. We declare the input and output of the plugin, and in the source file, we have the code to be transformed. We use source.replaceAll to replace a specific string with JSON.stringify, ensuring the expected outcome. However, in a real implementation, it is important to parse the code and replace it properly.

So let's write a plugin that does this for us. In this example, I'm using rollup and rollup-c means I'm using rollup.config.js file. And here, I have this empty plugin, which has name and transform. And we declare input and output like this. And in the source, main.js, we have the same code, right?

Now we need to write the plugin to transform this to something else. So before that, let's go and npm run build. And it does nothing. And the output is the same as the source code. And let's console.log first. Source and ID. And we run it again. And we get source, which is literally the source. And ID is the full path of the file.

So what we can do is we can return source.replaceAll process.inf.nodeInf and JSON stringify production. And if I run it again, it's working. It's already working. Yeah. That was easy, right? But what about this JSON stringify? It's a little bit weird. Like, what if we just put production like this? And now something is weird, right? Production without quote. Actually this is a rule from rollup. So we always need to stringify for the outcome that we expect. Now it works again. Actually this implementation is stupid. Don't do this because I replace all. And it can replace wrong strings unexpectedly. So in reality, you need to parse the code and replace it properly. But this is just a demo.

4. Using Virtual Modules for Static Data Handling

Short description:

Let's take a look at an example where we extract user names from an API endpoint. We can also use virtual modules to handle heavy tasks with static data at build time. By writing a fit plugin, we can handle non-existing libraries and produce the desired bundle output.

So let's take a look at the second example. We have this API endpoint. And it provides this array of users. And we want to extract user name. So how would you do that? It should be something like this. We fetch from this URL and get the JSON and we map over the array and extract this user name. Of course, like error handling, I'm not doing that right now. But that's pretty simple. And we can do this.

But what if we need to perform a very heavy task? What if it is a very heavy task with static data that can be handled at build time? In that case, we can use virtual module. So virtual module, it's not inside patch.json. But somehow it works. It's weird, right? So for example, we have import usernames from non-existing library and we console.log high usernames. For example, we have users.js and it's exporting usernames and main.js is importing these usernames and console.log. And after bundling, we get something like this. So because the bundler bundles everything into a single file and removes all the import and export statement, usernames is embedded like this, right? Just like this.

When we use virtual module, although non-existing library is not in patch.json, bundler can somehow get this module and produce this bundle output. So in order to make this happen, we can write a fit plugin. And it's going to look like this. So resolve ID. And if source is non-existing library, then we can return source, meaning, yeah, let me handle it. I can do that. And then it goes to a load function. And if ID is non-existing library, then we can return a string which looks like this, a JavaScript module. In this example, I'm using a fit. And we have this empty plugin build time library. And it's using resolve ID and load function. And I put this plugin into plugins array. And we have this main.js which is importing usernames from my build time library, which doesn't exist at patch.json.

5. Handling Importing Non-existing Libraries

Short description:

We need to handle importing a non-existing library in our build process. To do this, we can fake the library using an object with a key-value pair. By implementing a fit plugin, we can resolve the import and return the desired bundle output. Instead of hard coding the value, we can provide a factories object and loop over it to store the key-value pairs.

And we have this main.js which is importing usernames from my build time library, which doesn't exist at patch.json. If I run build, it fails, of course, because rollout failed to resolve import my build time library. Because it doesn't exist at patch.json. So we need to fake it. So here we are putting an object. And usernames is a key and the value is the getter function. So let's make it a sync and fetch. And await. And we get the JSON. We can map and username. It's the same code we saw before in the slide.

So in plugin, resolve ID. If source is my build time library, we return my build time library, meaning I can't handle it. And if ID is my build time library, then it can return a JS module. And in this case, let's hard code first. Import const usernames, like this. And let's run it again. Now it's working. And if we look at this file, we have usernames. Yeah, it's working. If you compare this, this import statement has disappeared, and usernames is embedded in this output.

If I add one more thing here, yeah, it's still working. So instead of this hard coding, let's actually implement something. So we provide factories object. So the key is the name and the value is the getter function. Object keys, factories, and we loop it over. And getter is factories key. And value is like that. And if value is an instance of promise, we need to await this value. And we need to store this key value, right? So let's create result and result key is value.

6. Transforming Result Object into Code

Short description:

We can transform the result object into code by using object keys and map. This allows us to extract specific data and include it in the output. By making the code flexible, we can add additional information like 'built at' and utilize it for various purposes, such as displaying branch name or commit hash during deployment. This approach is useful for heavy computation and obtaining related information during the build process.

And let's take a break and console loop this result object. Yeah, it's still failing, but it's okay. Yes, result is an object with usernames and this array.

Now let's turn this result into like this. So object keys result. And let's do map here. And it looks like export const key. And JSON stringify result key, which is the value. And we join this array. And put it into a variable. And we return this code. And before that, let's console loop code first.

Run it again. Now we see a code export const usernames. It's working right. And here we can see it's working fine. And because we made it so flexible, we can have something else like built at. So here we can add built at and new date to ISO stream.

If you run it again, now you see we have export const usernames and also built at. And if we look at the file, it's still working well. In this example, we process data at build time. And the bundle output includes only the computation result, not the business logic. But of course, if the computational result is going to be an array of a million user names, then we shouldn't do that. So think about when to use it and where to use it. And you can use it for heavy computation and get related info, like latest commit or branch name. So imagine you're deploying a staging version. And on the top left corner, you can put branch name or commit hash. And you can also use it to get the local directory structure. So once bundled, you lose all the directory structure in the bundle output. But during the build time, you know the current project directory structure.

7. Exploring Advanced Functionalities in Vip Plugin

Short description:

You can implement various functionalities in the Vip plugin, such as reading Markdown files, implementing file-based routing, and creating domain-specific languages. The possibilities are vast, as demonstrated by the extensive list of Vip plugins available in the Awesome Vip Repository. Give it a try by experimenting in a new project. Reach out to me on Twitter at Ninja underscore Lee if you have any questions.

So you can read some Markdown file and get the front matter properties, or you can even implement your own file-based routing. And you can even implement domain-specific language if you want to go far.

So I've talked about build time versus runtime and virtual module. But actually, when it comes to Vip plug-in, these are just a part of a Vip plug-in. And these are small topics that I picked to demonstrate how Vip plug-in looks like and how it works.

So if you go to Awesome Vip Repository, it has a huge list of very interesting Vip plug-ins. And the possibility is really, really bigger than what you think. And give it a try. If you scan this QR code, it has this slide, but also a repository of multiple examples that show you how you can do things.

But I give you a warning. I've learned something new today. I believe I can apply this solution to my problem. Probably wrong. Okay, I have this problem. These are the possible solutions. Okay, this one makes the most sense. Then yes. So you should think this way. But now that we just learned this, give it a try, but not at your work. Just create a new project and play with it and see how it works. And just reach out to me if you have any question. I'm on Twitter at Ninja underscore Lee. Thank you for watching.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Modern Web Debugging
JSNation 2023JSNation 2023
29 min
Modern Web Debugging
Top Content
This Talk discusses modern web debugging and the latest updates in Chrome DevTools. It highlights new features that help pinpoint issues quicker, improved file visibility and source mapping, and ignoring and configuring files. The Breakpoints panel in DevTools has been redesigned for easier access and management. The Talk also covers the challenges of debugging with source maps and the efforts to standardize the source map format. Lastly, it provides tips for improving productivity with DevTools and emphasizes the importance of reporting bugs and using source maps for debugging production code.
The Future of Performance Tooling
JSNation 2022JSNation 2022
21 min
The Future of Performance Tooling
Top Content
Today's Talk discusses the future of performance tooling, focusing on user-centric, actionable, and contextual approaches. The introduction highlights Adi Osmani's expertise in performance tools and his passion for DevTools features. The Talk explores the integration of user flows into DevTools and Lighthouse, enabling performance measurement and optimization. It also showcases the import/export feature for user flows and the collaboration potential with Lighthouse. The Talk further delves into the use of flows with other tools like web page test and Cypress, offering cross-browser testing capabilities. The actionable aspect emphasizes the importance of metrics like Interaction to Next Paint and Total Blocking Time, as well as the improvements in Lighthouse and performance debugging tools. Lastly, the Talk emphasizes the iterative nature of performance improvement and the user-centric, actionable, and contextual future of performance tooling.
pnpm – a Fast, Disk Space Efficient Package Manager for JavaScript
DevOps.js Conf 2022DevOps.js Conf 2022
31 min
pnpm – a Fast, Disk Space Efficient Package Manager for JavaScript
Watch video: pnpm – a Fast, Disk Space Efficient Package Manager for JavaScript
pnpm is a fast and efficient package manager that gained popularity in 2021 and is used by big tech companies like Microsoft and TikTok. It has a unique isolated node module structure that prevents package conflicts and ensures each project only has access to its own dependencies. pnpm also offers superior monorepo support with its node module structure. It solves the disk space usage issue by using a content addressable storage, reducing disk space consumption. pnpm is incredibly fast due to its installation process and deterministic node module structure. It also allows file linking using hardlinks instead of symlinks.
Beyond Virtual Lists: How to Render 100K Items with 100s of Updates/sec in React
React Advanced 2021React Advanced 2021
27 min
Beyond Virtual Lists: How to Render 100K Items with 100s of Updates/sec in React
Top Content
The Talk discusses optimizing rendering of big tables using Flipper, a new version that is ten times faster with improved user interaction and richer data. It explores optimizing rendering with React, virtualization, filtering, sorting, and windowing techniques. The introduction of the Flipper Datasource packet simplifies handling updates, inserts, and removals. The performance of the Flipper data source package is excellent, even in a debug build of React, with minimal CPU usage. The Q&A session covers incremental sorting, dynamic row height, and the potential for two-dimensional virtualization in the future.
Durable Objects - Everything Everywhere All At Once For Not Very Much Money
React Day Berlin 2023React Day Berlin 2023
31 min
Durable Objects - Everything Everywhere All At Once For Not Very Much Money
Top Content
Watch video: Durable Objects - Everything Everywhere All At Once For Not Very Much Money
Durable Objects is a versatile programming paradigm by Cloudflare that allows for stateful and uniquely addressable server environments. It simplifies feature development, enables real-time updates through WebSocket connections, and provides a built-in key-value store for long-term storage. It can be used to create collaborative applications, manage data storage efficiently, and explore co-located compute and data at the edge. Other companies like Azure also offer similar technologies. Deno's KV and fly.io's Flame are innovative products that eliminate the need for provisioning databases and Kubernetes clusters.
Debugging with Chrome DevTools
JSNation Live 2021JSNation Live 2021
11 min
Debugging with Chrome DevTools
Top Content
Here are some tips for better utilizing DevTools, including using the run command, customizing keyboard shortcuts, and emulating the focus effect. Learn how to inspect memory, use the network panel for more control over network requests, and take advantage of console utilities. Save frequently used code as snippets and use local overrides for easy editing. Optimize images by using a more optimized format like AVIF and track changes in the network panel to see the reduced data size.

Workshops on related topic

React, TypeScript, and TDD
React Advanced 2021React Advanced 2021
174 min
React, TypeScript, and TDD
Top Content
Featured Workshop
Paul Everitt
Paul Everitt
ReactJS is wildly popular and thus wildly supported. TypeScript is increasingly popular, and thus increasingly supported.

The two together? Not as much. Given that they both change quickly, it's hard to find accurate learning materials.

React+TypeScript, with JetBrains IDEs? That three-part combination is the topic of this series. We'll show a little about a lot. Meaning, the key steps to getting productive, in the IDE, for React projects using TypeScript. Along the way we'll show test-driven development and emphasize tips-and-tricks in the IDE.
Mastering advanced concepts in TypeScript
React Summit US 2023React Summit US 2023
132 min
Mastering advanced concepts in TypeScript
Top Content
Featured WorkshopFree
Jiri Lojda
Jiri Lojda
TypeScript is not just types and interfaces. Join this workshop to master more advanced features of TypeScript that will make your code bullet-proof. We will cover conditional types and infer notation, template strings and how to map over union types and object/array properties. Each topic will be demonstrated on a sample application that was written with basic types or no types at all and we will together improve the code so you get more familiar with each feature and can bring this new knowledge directly into your projects.
You will learn:- - What are conditional types and infer notation- What are template strings- How to map over union types and object/array properties.
From Todo App to B2B SaaS with Next.js and Clerk
React Summit US 2023React Summit US 2023
153 min
From Todo App to B2B SaaS with Next.js and Clerk
Top Content
WorkshopFree
Dev Agrawal
Dev Agrawal
If you’re like me, you probably have a million side-project ideas, some that could even make you money as a micro SaaS, or could turn out to be the next billion dollar startup. But how do you know which ones? How do you go from an idea into a functioning product that can be put into the hands of paying customers without quitting your job and sinking all of your time and investment into it? How can your solo side-projects compete with applications built by enormous teams and large enterprise companies?
Building rich SaaS products comes with technical challenges like infrastructure, scaling, availability, security, and complicated subsystems like auth and payments. This is why it’s often the already established tech giants who can reasonably build and operate products like that. However, a new generation of devtools are enabling us developers to easily build complete solutions that take advantage of the best cloud infrastructure available, and offer an experience that allows you to rapidly iterate on your ideas for a low cost of $0. They take all the technical challenges of building and operating software products away from you so that you only have to spend your time building the features that your users want, giving you a reasonable chance to compete against the market by staying incredibly agile and responsive to the needs of users.
In this 3 hour workshop you will start with a simple task management application built with React and Next.js and turn it into a scalable and fully functioning SaaS product by integrating a scalable database (PlanetScale), multi-tenant authentication (Clerk), and subscription based payments (Stripe). You will also learn how the principles of agile software development and domain driven design can help you build products quickly and cost-efficiently, and compete with existing solutions.
Integrating LangChain with JavaScript for Web Developers
React Summit 2024React Summit 2024
92 min
Integrating LangChain with JavaScript for Web Developers
WorkshopFree
Vivek Nayyar
Vivek Nayyar
Dive into the world of AI with our interactive workshop designed specifically for web developers. "Hands-On AI: Integrating LangChain with JavaScript for Web Developers" offers a unique opportunity to bridge the gap between AI and web development. Despite the prominence of Python in AI development, the vast potential of JavaScript remains largely untapped. This workshop aims to change that.Throughout this hands-on session, participants will learn how to leverage LangChain—a tool designed to make large language models more accessible and useful—to build dynamic AI agents directly within JavaScript environments. This approach opens up new possibilities for enhancing web applications with intelligent features, from automated customer support to content generation and beyond.We'll start with the basics of LangChain and AI models, ensuring a solid foundation even for those new to AI. From there, we'll dive into practical exercises that demonstrate how to integrate these technologies into real-world JavaScript projects. Participants will work through examples, facing and overcoming the challenges of making AI work seamlessly on the web.This workshop is more than just a learning experience; it's a chance to be at the forefront of an emerging field. By the end, attendees will not only have gained valuable skills but also created AI-enhanced features they can take back to their projects or workplaces.Whether you're a seasoned web developer curious about AI or looking to expand your skillset into new and exciting areas, "Hands-On AI: Integrating LangChain with JavaScript for Web Developers" is your gateway to the future of web development. Join us to unlock the potential of AI in your web projects, making them smarter, more interactive, and more engaging for users.
Building Pinia From Scratch
Vue.js Live 2024Vue.js Live 2024
70 min
Building Pinia From Scratch
Workshop
Eduardo San Martin Morote
Eduardo San Martin Morote
Let's dive into how Pinia works under the hood by building our own `defineStore()`. During this workshop we will cover some advanced Vue concepts like dependency Injection and effect scopes. It will give you a better understanding of Vue.js Composition API and Pinia. Requirements: experience building applications with Vue and its Composition API.
Mastering 3D Web Development with TresJS ecosystem: A Vue.js Workshop
Vue.js Live 2024Vue.js Live 2024
119 min
Mastering 3D Web Development with TresJS ecosystem: A Vue.js Workshop
Workshop
Alvaro Saburido
Alvaro Saburido
Introducing "Mastering 3D Web Development with TresJS," a specialized workshop crafted for Vue.js developers eager to explore the realm of 3D graphics within their web applications. TresJS, a powerful custom renderer for Vue, is specifically designed to work seamlessly with Vue's reactive system. This workshop offers a deep dive into integrating sophisticated 3D visualizations and interactive experiences directly into Vue applications, leveraging the unique strengths of both Vue and TresJS ecosystems.
This workshop is designed for Vue.js developers looking to expand their skill set into the third dimension, UI/UX designers interested in incorporating 3D elements into web applications, and front-end developers curious about the potential of 3D graphics in enhancing user experiences. You'll need to be familiar with Vue.js to benefit from this workshop fully.
What You Will Learn- Introduction to TresJS: Discover the fundamentals of TresJS and how it integrates with the Vue ecosystem to bring 3D graphics to life.- Creating 3D Scenes with Vue: Learn to construct intricate 3D scenes utilizing Vue components, enhancing your user interfaces with dynamic and immersive visuals.- Interactivity and Animation: Master the techniques to make your 3D scenes interactive, responding to user inputs for a captivating user experience.- Integrating with Vue Features: Explore advanced integration of TresJS with Vue’s reactivity, composables, and the Vuex store to manage state in 3D web applications.- Performance and Best Practices: Gain insights into optimizing your 3D scenes for performance and best practices to maintain smooth, responsive web applications.