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

@aliyun-sls/vite-plugin-virtual-mpa

v1.12.1

Published

Out-of-box MPA plugin for Vite, with html template engine and virtual files support.

Downloads

42

Readme

vite-plugin-virtual-mpa ⚡

npm version awesome-vite weekly downloads license install size

开箱即用的 Vite MPA插件 📦,支持HTML模板引擎和虚拟文件功能,能够使用一份模板生成多个文件。

English | 中文

主要功能

  • 💡 EJS 模板渲染
  • 💡 完备的 TypeScript 类型提示支持,是一款小而美的插件
  • 🛠️ 自定义模板HTML文件的输出路径, 使用一份模板生成多份文件
  • 🛠️ 支持 MPA 多页面应用,为开发和预览服务器提供 History Fallback 支持.

使用方式

pnpm add -D vite-plugin-virtual-mpa # or npm/yarn
// vite.config.ts
import { createMpaPlugin, createPages } from 'vite-plugin-virtual-mpa'

// @see https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    createMpaPlugin({
      pages: [
        // 你可以直接在这里书写页面配置,也可以单独使用 `createPages` 函数并将结果传递到这里。
      ]
    }),
  ],
})

/**
 * 该函数仅仅是将参数转换为一个 pages 数组。
 * 它帮助你在插件之外创建页面配置,主要是为了能够拥有类型提示。
 * 同时在别处统一管理配置的方式可能也能帮助你简化 vite 的配置文件。
 */
const pages = createPages([
  // 你可以传递一个 page 对象或一个 pages 数组。
])

// @see https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    createMpaPlugin({
      pages,
    }),
  ],
})

Options

type FilterPattern = string | RegExp | (string | RegExp)[]
type RewriteRule = false | Rewrite[]
interface WatchHandler {
  (ctx: {
    server: ViteDevServer,
    file: string,
    type: Event
    /**
     * 可以调用这个方法更新页面配置
     * @params pages MPA 页面核心配置,这将会替换默认的 `pages`
     */
    reloadPages: (pages: Page[]) => void
  }): void
}

interface MpaOptions {
  /**
   * 是否在控制台打印log
   * @default true
   */
  verbose?: boolean,
  /**
   * 默认模板文件
   * @default index.html
   */
  template?: `${string}.html`,
  /**
   * 为开发服务器配置 fallback rewrite rules,只会处理 accept=text/html 的文件请求。
   * @see https://github.com/bripkens/connect-history-api-fallback
   */
  rewrites?: RewriteRule,
  /**
   * 为预览服务器配置重定向规则,配置方式同 rewrites。
   * @see https://github.com/bripkens/connect-history-api-fallback
   */
  previewRewrites?: RewriteRule,
  /**
   * 处理模版 HTML 文件,继承自 `transformIndexHtml`。
   * @see https://vitejs.dev/guide/api-plugin#transformindexhtml
   */
  transformHtml?: (
    html: string,
    ctx: IndexHtmlTransformContext & { page: Page },
  ) => IndexHtmlTransformResult;
  /**
   * 用于扫描相似的目录结构,自动生成 pages 配置。
   * 扫描到的配置会追加到 `pages` 中,具有相同 name 的 page 将被忽略
   */
  scanOptions?: {
    /**
     * 要扫描的目录,子目录名称将作为唯一的 page name。
     */
    scanDirs: string | string[];
    /**
     * 相对于扫描目录的入口文件路径
     */
    entryFile?: string;
    /**
     * 自定义虚拟文件的名称(输入文件名)
     * @param name 子目录名称
     */
    filename?: (name: string) => string;
  };
  /**
   * 当项目目录下有一些文件触发相应的事件如添加、删除、修改时,你可能想要重新加载 `pages` 配置 或 重启 ViteDevServer。
   * 你可以通过设置 `watchOptions` 来实现这一目的。
   */
  watchOptions?: WatchHandler | {
    /**
     * 指定需要**包含**的文件,基于 `Rollup.createFilter` 过滤
     * @see https://vitejs.dev/guide/api-plugin.html#filtering-include-exclude-pattern
     */
    include?: Exclude<FilterPattern, null>,
    /**
     * 指定需要**排除**的文件,基于 `Rollup.createFilter` 过滤
     * @see https://vitejs.dev/guide/api-plugin.html#filtering-include-exclude-pattern
     */
    excluded?: Exclude<FilterPattern, null>,
    /**
     * 想要监听的文件事件
     * @default ['add', 'unlink', 'change', 'unlinkDir', 'addDir']
     */
    events?: Event[],
    /**
     * 定义的文件事件触发后,执行自定义逻辑
     */
    handler: WatchHandler
  },
  pages: Array<{
    /**
     * 必填。该名称是一个不包含'/'的普通字符串,它用于生成默认的重定向规则。
     * 如果你想自定义生成文件的路径,请使用filename选项,而不是name选项。
     */
    name: string;
    /**
     * 相对于`build.outDir`的路径,应该以html结尾
     * @default `${name}.html`
     */
    filename?: `${string}.html`;
    /**
     * 更高优先级的模板文件,将会覆盖默认模板
     */
    template?: string;
    /**
     * 自动注入入口文件,如果设置了entry,需要移除模板文件中的entry
     */
    entry?: string;
    /**
     * 注入到模板文件的数据
     */
    data?: Record<string, any>,
  }>,
  /**
   * 是否使用 html-minify-terser 压缩 html 文件
   * @default false
   * @see https://github.com/terser/html-minifier-terser
   */
  htmlMinify?: Options | boolean,
}

Examples

点击链接 codesandbox 快速体验

// vite.config.ts
import { normalizePath } from "vite";
import { createMpaPlugin } from "vite-plugin-virtual-mpa"

const base = "/sites/"

// @see https://vitejs.dev/config/
export default defineConfig({
  base,
  plugins: [
    createMpaPlugin({
      htmlMinify: false,
      pages: [
        {
          name: "apple",
          /**
           * 文件名是可选的,默认将会是`${name}.html`,这个路径是相对于`build.outDir`
           */
          filename: "fruits/apple.html", // 将会在编译时输出到sites/fruits/apple.html
          entry: "/src/fruits/apple/index.js",
          data: {
            title: "This is Apple page"
          }
        },
        {
          name: "banana",
          filename: "fruits/banana.html",
          entry: "/src/fruits/banana/index.js",
          data: {
            title: "This is Banana page"
          }
        },
        {
          name: "strawberries",
          filename: "fruits/strawberries.html",
          entry: "/src/fruits/strawberries/index.js",
          data: {
            title: "This is Strawberries page"
          }
        }
      ],
      /**
       * 以下示例的 scanOptions 配置可以替换上面的 pages 配置,除了 data 的注入。
       */
      scanOptions: {
        scanDirs: 'src/fruits',
        entryFile: 'index.js',
        filename: name => `fruits/${name}.html`,
        template: '../../template.html',
      }
      /**
       * 通过该选项来配置 history fallback rewrite rules
       * 如果你像上面这样配置页面的话,那下面的这份配置将会自动生成。
       * 否则你需要自己编写重定向规则。
       */
      rewrites: [
        {
          from: new RegExp(normalizePath(`/${base}/(apple|banana|strawberries)`)),
          to: (ctx) => normalizePath(`/fruits/${ctx.match[1]}.html`),
        }
      ],
      /**
       * 配置预览服务器的重定向规则,配置方式同 rewrites
       */
      previewRewrites: [
        // 如果产物目录没有 index.html,你需要手动配置规则,以便服务器能正确找到入口文件。
        { from: /.*/, to: '/home.html' },
      ],
      /** 自定义处理模板内容 */
      transformHtml(html, ctx) {
        return {
          html,
          tags: [
            {
              tag: 'div',
              injectTo: 'body-prepend',
              children: `[Auto Injected] Page name: ${ctx.page.name}`,
            },
          ],
        };
      },
    }),
  ],
})

插件对比

使用vite开发构建 多页面应用(MPA) 的时候,我们通常需要一个具备以下能力的插件:

  1. 具备模板引擎如ejs,能够使用一个模板生成多份文件,且能自定义构建时生成文件的路径。

  2. 自动配置 rollupOptions.input,并提供能力配置开发服务器的代理(主要是history fallback api)。

市面上有非常多的关于vite的MPA插件,但他们却几乎没有能同时做到以上两点的。根据名称匹配度和下载量,我筛选到以下插件:

  1. vite-plugin-mpa:可以自动配置入口,并提供开发服务器代理配置入口(fallback rule),但必须按照约定调整目录结构,且不支持模板引擎和虚拟入口,也无法定义生成文件的路径。

  2. vite-plugin-html-template:这个插件的作者和vite-plugin-mpa是同一个人,算是作者推荐的配套插件,主要是和mpa插件组合使用以提供模板引擎功能,同样不支持虚拟入口。

  3. vite-plugin-html:只支持模板引擎,且不支持虚拟入口。

  4. vite-plugin-virtual-html:支持虚拟入口,提供了渲染接口,可以定制模板引擎。但没有内置模板引擎,用起来有点麻烦还是。

其中,"虚拟入口" 的意思是,通过一个模板文件,渲染出多个入口html文件。

其他插件大同小异,他们各有所长,但用起来总不趁手。要么需要搭配使用,要么对现有项目结构的改动较多。有时候我也好奇,既然实现了模板引擎,却又需要多个模板文件,这样做岂不是失去了模板的优势。

而这个插件便是为了解决这些问题,它同时具备上面提到的所有能力。通过结合虚拟入口和模板引擎,使得用户只需要一份模板就可以生成不同的入口html,且能自定义入口文件的输出路径(再也不用手动写脚本移动了!)。同时也提供了接口为开发服务器配置rewrite rules,以便开发时能够正确地请求到入口文件。

如果你的项目正在使用vite工作流且为MPA应用,不妨尝试一下这个插件,它不限制技术栈,与你是否使用vue还是react或其他技术无关。

默认重定向规则

正如上面提到的👆🏻,如果你的配置遵循约定,插件将会自动生成一份重定向规则,这份配置会同时应用到开发和预览服务器,如下:

{
  from: new RegExp(normalizePath(`/${base}/(${Object.keys(inputMap).join('|')})`)),
  to: ctx => normalizePath(`/${base}/${inputMap[ctx.match[1]]}`),
}

其中, inputMap 是一个name到对应虚拟文件的映射,结构如下:

{
  apple: 'fruits/apple.html',
  banana: 'fruits/banana.html',
  strawberries: 'fruits/strawberries.html',
}

请求Url/sites/apple/xxx将会被默认重定向规则处理并重定向到对应的url,也就是/fruits/apple.html(name 'apple' 对应 'fruits/apple.html', 其他同理),重定向后的路径将会基于viteConfig.base(这里是'/sites/')去寻找目标文件,所以最终的Url会变成/sites/fruits/apple.html.

关于虚拟入口文件

通常在开发时,我们的文件都是写在本地的,我们通过DevServer的代理能够通过url访问到本地对应的文件。虚拟文件也是如此,只不过对应的文件没有写到文件系统中,而是保存在内存中而已。

该插件通过模板系统生成了对应的虚拟文件,让你可以在开发时通过代理访问到内存中的虚拟文件,并在构建时生成到对应的目录下。

你完全可以认为这些虚拟文件是真实存在的,这将有助于你在脑海中构建关于虚拟文件的直觉,以便能够正确地编写代理配置。

关于 EJS 模板引擎

插件使用 ejs 模板引擎进行数据注入,除页面配置中提供的 data 外,插件默认会将以 'VITE_' 开头的环境变量注入所有的页面配置中,更多信息可以查看官网 —— envprefix