npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

vite-ssr-middleware

v0.2.1

Published

"Middleware support for plugin vite-ssr"

Downloads

51

Readme

Vite-SSR-Middleware

This plugin adds Nuxt like middleware feature to Vite-SSR only for Vue.

Installation

This package requires vite-ssr and vue-router@next as peer dependency. Download it from npm (p)npm install vite-ssr-middleware or yarn add vite-ssr-middleware.

Usage

Usage is simple, there is no need to register this package like vueApp.use().

Creating Middleware

A middleware can have 3 arguments, 2 of them are necessary and 1 is optional. First parameter is unique name to middleware string Second parameter is handler (context, properties) => boolean | Promise<boolean> Third parameter is optional object, which can be defined in root handler object

Every middleware has to return boolean. If middleware returns true chaining will continue. If middleware returns false chaining will stop. Return false to use next() and redirect() inside middlewares. If returned value is true and next() or redirect() is used vue-router will throw error.

import { defineMiddleware } from 'vite-ssr-middleware';
import { useStore } from '../stores/mainStore';

// context is Vite-SSR context. Simply return type of useContext() from vite-ssr.
// Properties are empty object by default and can be customized in root handler.
export const authMiddleware = defineMiddleware('auth', (context, properties) => {
   // Vite-SSR 0.12.0 available context values
   const {
      next, // from vue-router
      to, // from vue-router
      from, // from vue-router
      isClient,
      request,
      redirect,
      initialState,
      url,
      writeResponse,
      response
   } = context;

   // Check if middleware runs on client side.
   // import.meta.env.SSR can be used here.
   if (isClient) {
      // we are going to talk about this later.
      const store = useStore(properties.pinia);
      if (store.auth) return true; // continue chaining

      // if user not signed in
      next('/login');
      return false; // Stop chaining because NEXT is used.
   }

   // if not client, it is server
   const authorization = request.headers.authorization;
   const isOK = CheckUserTokenAndReturnFalseOrTrue(authorization);
   if (isOk) return true; // token is correct, return true to continue chaining

   // In server side we have to use redirect() function and next() together.
   // on server side redirect() handles navigation but if next() is not called after,
   // it does not work and stuck on same page.
   redirect('/login');
   next();
   return false; // return false and stop chaining because next is used.
});

Creating Middleware Handler

There are 2 middleware handlers. One is simple and the other one is needed to be handled. Handlers need vite-ssr context, vue-router guard arguments and all middlewares as array. And can take properties as argument. properties can be accessible from any middleware.

Simple Handler

import { viteSSR } from 'vite-ssr';
import { middlewareHandler } from 'vite-ssr-middleware';
import App from './App.vue';
import { routes } from './routes';

// Store example with pinia
import { createPinia } from 'pinia';

// Import middlewares
import { authMiddleware } from '../middlewares/authMiddleware';

export default viteSSR(App, { routes }, (context) => {
   const { app, router } = context;

   const pinia = createPinia();
   app.use(pinia);

   // middlewareHandler must be used inside router.beforeEach
   const handler = middlewareHandler(context, [authMiddleware], {
      // this property is accessible in each middleware
      pinia
   });
   router.beforeEach(handler);
   //...
});

A Little Complex Handler

This handler is to create a handler function. Handler function will return true or false. If handler function returns true it means a middleware returned false and blocked chaining. Basically in this tutorial if false is returned from middleware it means next() or redirect() is called. You can use it for your own purpose If handler returns false it means none of middlewares called next(), so we have to call it manually.

import { viteSSR } from 'vite-ssr';
import { createMiddlewareHandler } from 'vite-ssr-middleware';
import App from './App.vue';
import { routes } from './routes';

// Store example with pinia
import { createPinia } from 'pinia';

// Import middlewares
import { authMiddleware } from '../middlewares/authMiddleware';

export default viteSSR(App, { routes }, (context) => {
   const { app, router } = context;

   const pinia = createPinia();
   app.use(pinia);

   // middlewareHandler must be used inside router.beforeEach
   // I pass pinia as property here because some middlewares need it.
   const handler = createMiddlewareHandler(context, [authMiddleware], {
      pinia
   });
   router.beforeEach(async (to, from, next) => {
      // if any one of middlewares returned false, isNextHandled = true
      // in this tutorial, return false means NEXT is used.
      // you can customize this for your own purpose.
      const isNextHandled = await handler({ to, from, next });

      if (isNextHandled) return;
      next();
   });
   //...
});

Defining Middlewares for Routes

To define middleware for routes we have to use middlewares array inside of route.meta. Middlewares array can store the value of middleware and name of it as string. This package does not remove middleware duplications!!!!

import { RouteRecordRaw } from 'vue-router';
import { authMiddleware } from '../middlewares/authMiddleware';

const routes = [
   {
      path: '/settings',
      component: () => import('./Settings.vue'),
      meta: {
         middlewares: [authMiddleware]
      }
   },
   {
      path: '/topsecret',
      component: () => import('./SecretPage.vue'),
      meta: {
         middlewares: ['auth'] // name of the middleware (first parameter)
      }
   }
];

Typed Custom Properties

You can create your own types for properties inside middlewares.

middlewares.d.ts

This file should ALWAYS! import something or export something. If no import or export provided this will break all types.

//or import something
import { App } from 'vue';

declare module 'vite-ssr-middleware' {
   interface CustomProperties {
      propertyForMiddleware: string;
   }
}
// a garbage type just to make this file as a module.
export type Integer = number;

Importing Middlewares Dynamically

Thanks to vite's import.meta.globEager function we can import files inside a directory so we won't import middlewares by hand.

I am assuming that we have a directory called middlewares and every file inside of this folder has default export which is middleware. Check: Glob Import

import { viteSSR } from 'vite-ssr/vue';
import { middlewareHandler, Middleware } from 'vite-ssr-middleware';
import App from './App.vue';
import { routes } from './routes';
import type { Middleware } from 'vite-ssr-middleware';

export default viteSSR(App, { routes }, (context) => {
   const { router } = context;

   // glob import will return an object of imports.
   // key is path and value is exported data.
   /**
    * Example: {
    *    './middlewares/authMiddleware.ts': {
    *       default: middlewareData,
    *    },
    *    './middlewares/loggerMiddleware.ts': {
    *       default: loggerMiddlewareData,
    *    },
    * }
    */
   const midwareGlob = import.meta.globEager('./middlewares/*.ts');
   const middlewares: Middleware[] = Object.keys(midwareGlob).map((key) => midwareGlob[key].default);
   const handler = middlewareHandler(context, middlewares);
   router.beforeEach(handler);
});
authMiddleware.ts
export default defineMiddleware('auth', () => true);
loggerMiddleware.ts
export default defineMiddleware('logger', () => true);

Vite Plugin Pages Example

If you are using vite-plugin-pages we cannot import middlewares and directly use them. But this library supports name of middlewares so we can use them.

<!-- I have to use prettier-ignore thanks to prettier :) -->
<!-- prettier-ignore -->
<route lang="yaml"> <!-- OR json or json5 -->
meta:
   middlewares:
      - auth
      - logger
</route>

Notes

Middlewares are called by array queue. Use handler inside of viteSSR function.