For those of you who know about Vue3, You’ve abandoned Webpack and used Vite to build your project. Vite also supports custom plug-ins, but there is no official documentation for this part. I searched the Internet and found an article on how to write plug-ins. Translated down, I hope it can be helpful to you. Well, let’s take a look! Ps: I also tried to write a vite plug-in: convert MD to string, code address.

Writing a vite plugin

Here’s how Yuda describes Vite: “A browser-based native ES Imports development server. Resolves imports in the browser, compiles them on the server as needed, skips packaging altogether, and the server comes with it. It has Vue support, hot updates, Hot updates don’t slow down as more modules are added, and the same code can be packaged in rollup for production.”

Today we’ll look at how to write a simple Vite plug-in, code address.

Plug-in functions

Our plug-in will automatically generate vue-Router routes based on the Vue component directory, which I took inspiration from Nuxt’s routing capabilities.

Our directory structure:

src/
|-- pages/
    |-- about.vue
    |-- contact.vue
Copy the code

Automatically generated routes:

[
  {
    name: 'about'.    path: '/about'.    component: '/src/pages/about.vue'
 },  {  name: 'contact'. path: '/contact'. component: '/src/pages/contact.vue'  }, ] Copy the code

About Vite

Why did Vue3 choose Vite?

If you don’t know about Vite, you can watch the official explanation of Vite, or listen to the discussion of Yu Yuxi on Full Stack Radio. To understand what Vite is and why it exists.

Compared to Webpack, The build time of Vite is much shorter. Give Vite a try and I’m sure you’ll understand why you chose it!

Vite plug-in concept

At the time of this writing, there is no official documentation on how to write a Vite plug-in.

So, for now, the only way to get a deeper understanding of how to write a plug-in is to read the Vite source code.

We need to clarify some relevant concepts first to facilitate the subsequent work:

  • Dev Server: The browser can handle the ES module import of JS files.

However, you cannot directly handle imports of other file types. Every time the browser encounters an import in the code, it is first compiled through Vite’s Dev server and then supplied directly to the browser.

For example, the *.vue file is compiled on the development server before being sent to the browser.

These imports can be javascript, vue, or CSS files. It can be any other type of file, but you need to specify the mutation tool in Vite.

That’s why the Vite development server is so useful — it solves the limitations of the browser.

  • Rollup Production Bundle: For static content, no Vite development server is available in the production version. Therefore, Vite uses Rollup to package the code for the production environment.

  • Custom Blocks: Sometimes other libraries you use can add custom blocks to the vue file, such as

    or < Story >. You can use Vite to specify how to handle custom blocks.

Write our plug-in

We will automatically generate a vue-auto-routes.js file from which we will derive the array.

This file is a virtual file that is generated dynamically at development time (for the development server) and build time (for rollup).

Finally, we import the routing array into the code and we are ready to use it.

The VUe-router route is automatically generated

To generate the vue-auto-routes.js file, we need to parse the SRC /pages directory and convert it into some import statements and routing arrays.

Use node’s built-in FS module:

function parsePagesDirectory() {
  const files = fs
    .readdirSync('./src/pages')
    .map((f) = > ({ name: f.split('. ') [0].importPath: `/src/pages/${f}` }))

 const imports = files.map((f) = > `import ${f.name} from '${f.importPath}'`)   const routes = files.map(  (f) = > ` { name: '${f.name}',  path: '/${f.name}',  component: ${f.name}. }  `. )   return { imports, routes } } Copy the code

This function returns two arrays:

  • imports: import declare array, eg.import about from 'src/pages/about.vue'
  • routes: Route array, eg."{ name: 'about', path: '/about', component: about }"

Remember, these are strings right now,

Create an empty plug-in

The Vite plug-in is just an object. We can return an empty object first.

Create a js file plugin.js to use as a plug-in:

module.exports = function() {
 return {}
}
Copy the code

Then, use this in vite.config.js:

const viteAutoRoute = require('./plugin.js')

export default {
  plugins: [viteAutoRoute()],
}
Copy the code

If you’re careful, you might notice that we’re exporting a function instead of an object. This is to make it easier to add custom options to the plug-in later.

ViteAutoRoute ({pagesDir: ‘./ SRC /docs’})

The development environment

Now, use the routes we created earlier.

Use the vite plug-in option configureServer:

module.exports = function () {
  const { imports, routes } = parsePagesDirectory()

  const moduleContent = `
 ${imports.join('\n')}  export const routes = [${routes.join(', \n')}]  `   const configureServer = [  async ({ app }) => { // The code for koa  app.use(async (ctx, next) => {  if (ctx.path.startsWith('/@modules/vue-auto-routes')) {  ctx.type = 'js'  ctx.body = moduleContent  } else {  await next()  }  })  },  ]   return { configureServer } } Copy the code

First, create a string, moduleContent, that contains the required content to route the JS file.

Then we create the configureServer array for the middleware in the Vite Dev server.

Whenever Vite imports a javascript or vue file, it sends a request to that file to its Dev server, does some conversion if necessary, and sends it back in a form that the browser can handle.

When it encounters something like import {routes} from ‘vue-auto-routes’, it asks for @/modules/vue-auto-routes.

So what we’re going to do is intercept the request and return the body that we generated for moduleContent, declaring its type as JS.

Finally, we add the configureServer array to the returned object for use by Vite. When Vite saw this, it merged our list of 1 middleware with its own.

Now we can use these dynamically generated routes in our own routers:

import { createApp } from 'vue'
import { createRouter, createWebHashHistory } from 'vue-router'
import { routes } from 'vue-auto-routes'
import App from './App.vue'

const router = createRouter({  history: createWebHashHistory(),  routes, }) createApp(App).use(router).mount('#app') Copy the code

Now, we can run yarn dev to see how routing works, http://localhost:3000/#/about 🎉

Note that the Vue-router-Next we’re using is the upcoming VUE 3 router.

The production environment

However, when we run Yarn build it, it will not use the configureServer we just finished because in production it uses the Rollup compiled dev server instead of Vite.

Therefore, we need to add some other configurations to make it work in production:

const virtual = require('@rollup/plugin-virtual')

module.exports = function () {
  // This is the configureServer code defined earlier

 const rollupInputOptions = {  plugins: [virtual({ 'vue-auto-routes': moduleContent })],  }   return { configureServer, rollupInputOptions } } Copy the code

In this case, we used vite’s plug-in option rollupInputOptions. This allows us to define the plug-in functionality of Rollup.

We use @rollup/plugin-virtual with the module name and let the required JS content be returned.

Essentially, it does the same thing as a development server.

Now our automatic routing works in both local development and production environments.

Add custom blocks

Individual Vue pages may wish to provide additional options for routing.

For example, we might want to add additional options to our routes, or use custom route names.

To do this, we will re-implement the vue-cli-plugin-auto-routing route block to perform the following operations in the VUE component:

<route>
{
  "meta": {
    "requiresLogin": true,
  }
} </route> Copy the code

For this, we will use the vueCustomBlockTransforms option. This way, you can tell Vite what to do with custom blocks when it encounters a Vue file.

This is the last feature we’re going to add, so let’s look at it as part of the overall plug-in:

const fs = require('fs')
const virtual = require('@rollup/plugin-virtual')

function parsePagesDirectory() {
  const files = fs
 .readdirSync('./src/pages')  .map((f) = > ({ name: f.split('. ') [0].importPath: `/src/pages/${f}` }))   const imports = files.map((f) = > `import ${f.name} from '${f.importPath}'`)   const routes = files.map(  (f) = > ` { name: '${f.name}',  path: '/${f.name}',  component: ${f.name}.. (${f.name}.__routeOptions || {}),  }  `. )   return { imports, routes } }  module.exports = function () {  const { imports, routes } = parsePagesDirectory()   const moduleContent = `  ${imports.join('\n')}  export const routes = [${routes.join(', \n')}]  `   const configureServer = [  async ({ app }) => {  app.use(async (ctx, next) => {  if (ctx.path.startsWith('/@modules/vue-auto-routes')) {  ctx.type = 'js'  ctx.body = moduleContent  } else {  await next()  }  })  },  ]   const rollupInputOptions = {  plugins: [virtual({ 'vue-auto-routes': moduleContent })],  }   const vueCustomBlockTransforms = {  route: ({ code }) = > {  return `  export default function (Component) {  Component.__routeOptions = ${code}  }  `  },  }   return { configureServer, rollupInputOptions, vueCustomBlockTransforms } } Copy the code

We added a vueCustomBlockTransforms object that maps the key Route (our block name) to the function that returns the virtual JS file.

Added an additional field __routeOptions to the vueCustomBlockTransforms that maps to the code we declared in any custom

blocks.

Then, we generate code in the route (… (${balance ame}. __routeOptions | | {})) is used in this code.

This is why I imported the component in the vue-auto-routes virtual file and now have direct access to the fields that __routeOptions has added.

Now we can use $rout.meta.requiresLogin in the vue page component!

The end of the

Hopefully you know how Vite works and how to write some basic plug-ins.

See you next 💗💗💗

Level is limited, if there is a mistake in the article, please point out, thank you ~!

This article was typeset using MDNICE