Skip to content

Commit

Permalink
chore: publish new feature
Browse files Browse the repository at this point in the history
  • Loading branch information
emosheeep committed Feb 10, 2024
1 parent e66e7e2 commit 6d22ebd
Show file tree
Hide file tree
Showing 10 changed files with 360 additions and 605 deletions.
785 changes: 272 additions & 513 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions workspaces/plugin/.changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"commit": false,
"fixed": [],
"linked": [],
"access": "restricted",
"baseBranch": "main",
"access": "public",
"baseBranch": "master",
"updateInternalDependencies": "patch",
"ignore": []
}
5 changes: 5 additions & 0 deletions workspaces/plugin/.changeset/quick-spoons-poke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'vite-plugin-virtual-mpa': minor
---

feat: add transformHtml hook
56 changes: 30 additions & 26 deletions workspaces/plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,32 +60,6 @@ export default defineConfig({
})
```

## Motivation

When building **MPA(multi-page-applications)** with Vite, we usually need a plugin that:

1. Has a template engine such as EJS, which can use one template to generate multiple files, and can customize the path of the generated files at build time.

2. Auto configurations for `rollupOptions.input` and provide the ability to configure the development server's proxy (primarily the History Fallback API).

There are so many MPA plugins for vite on the market, but it seems no one can do both of above at the same time. I filtered the following plugins based on name matching and downloads:

1. [vite-plugin-mpa](https://github.com/IndexXuan/vite-plugin-mpa): It can automatically configure the entry and provide the DevServer proxy configuration (history fallback), but we must adjust the directory structure according to the convention, and does not support template engines and virtual entry, and cannot define the path to generate files.

2. [vite-plugin-html-template](https://github.com/IndexXuan/vite-plugin-html-template): The author of this plugin is the same as vite-plugin-mpa, which is recommended by the author. It is primarily used in combination with the MPA plugin to provide template engine functionality, and also doesn't support virtual entry.

3. [vite-plugin-html](https://github.com/vbenjs/vite-plugin-html): It supports template engines only, but no virtual entry. You need to use multiple entry templates if you want to generate multiple files.

4. [vite-plugin-virtual-html](https://github.com/windsonR/vite-plugin-virtual-html): It supports virtual entry points, provides a rendering interface to customize template engines. But there's no built-in template engine, so it's a bit cumbersome to use.

Here, **"virtual entry"** means that multiple entry HTML files are rendered through only one template file.

They have their strengths, but they don't work very well. Either it needs to be used in conjunction or it is a significant change to the existing project structure. Sometimes I wonder if it is losing the advantage of template by implementing a template engine but requiring multiple template files.

This plugin is designed to solve these problems, and it has all of these capabilities at the same time. By combining virtual entry and template engine, users can generate different entry HTML with only one template, and can customize the output path of the entry file (no need to manually write scripts to move!). It also provides an interface to configure rewrite rules for the development server, so that the development can correctly request the entry file.

If your project is using Vite workflow and is an MPA application, you may want to give this plugin a try. It doesn't limit the technology stack, it doesn't matter if you use Vue or React or any other technologies.

## Options

```ts
Expand Down Expand Up @@ -125,6 +99,10 @@ interface MpaOptions {
* @see https://github.com/bripkens/connect-history-api-fallback
*/
previewRewrites?: RewriteRule,
/**
* Dedicated hook for transforming template HTML.
*/
transformHtml?: (html: string, page: Page) => string;
/**
* Use to scan directories that have similar structure to generate pages.
* Detected pages will be appended to `pages` option, page with name existed will be ignored.
Expand Down Expand Up @@ -284,6 +262,32 @@ export default defineConfig({
})
```

## Motivation

When building **MPA(multi-page-applications)** with Vite, we usually need a plugin that:

1. Has a template engine such as EJS, which can use one template to generate multiple files, and can customize the path of the generated files at build time.

2. Auto configurations for `rollupOptions.input` and provide the ability to configure the development server's proxy (primarily the History Fallback API).

There are so many MPA plugins for vite on the market, but it seems no one can do both of above at the same time. I filtered the following plugins based on name matching and downloads:

1. [vite-plugin-mpa](https://github.com/IndexXuan/vite-plugin-mpa): It can automatically configure the entry and provide the DevServer proxy configuration (history fallback), but we must adjust the directory structure according to the convention, and does not support template engines and virtual entry, and cannot define the path to generate files.

2. [vite-plugin-html-template](https://github.com/IndexXuan/vite-plugin-html-template): The author of this plugin is the same as vite-plugin-mpa, which is recommended by the author. It is primarily used in combination with the MPA plugin to provide template engine functionality, and also doesn't support virtual entry.

3. [vite-plugin-html](https://github.com/vbenjs/vite-plugin-html): It supports template engines only, but no virtual entry. You need to use multiple entry templates if you want to generate multiple files.

4. [vite-plugin-virtual-html](https://github.com/windsonR/vite-plugin-virtual-html): It supports virtual entry points, provides a rendering interface to customize template engines. But there's no built-in template engine, so it's a bit cumbersome to use.

Here, **"virtual entry"** means that multiple entry HTML files are rendered through only one template file.

They have their strengths, but they don't work very well. Either it needs to be used in conjunction or it is a significant change to the existing project structure. Sometimes I wonder if it is losing the advantage of template by implementing a template engine but requiring multiple template files.

This plugin is designed to solve these problems, and it has all of these capabilities at the same time. By combining virtual entry and template engine, users can generate different entry HTML with only one template, and can customize the output path of the entry file (no need to manually write scripts to move!). It also provides an interface to configure rewrite rules for the development server, so that the development can correctly request the entry file.

If your project is using Vite workflow and is an MPA application, you may want to give this plugin a try. It doesn't limit the technology stack, it doesn't matter if you use Vue or React or any other technologies.

## Default Rewrite Rules

As the examples above says 👆🏻, if you follow the conventions, this plugin will generate a default rule which will be applied to both dev and preview server, it looks like:
Expand Down
57 changes: 30 additions & 27 deletions workspaces/plugin/README.zh_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,35 +54,8 @@ export default defineConfig({
}),
],
})

```

## 插件对比

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

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

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

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

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

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

3. [vite-plugin-html](https://github.com/vbenjs/vite-plugin-html):只支持模板引擎,且不支持虚拟入口。

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

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

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

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

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

## Options

```ts
Expand Down Expand Up @@ -122,6 +95,10 @@ interface MpaOptions {
* @see https://github.com/bripkens/connect-history-api-fallback
*/
previewRewrites?: RewriteRule,
/**
* 处理模版 HTML 文件。
*/
transformHtml?: (html: string, page: Page) => string;
/**
* 用于扫描相似的目录结构,自动生成 pages 配置。
* 扫描到的配置会追加到 `pages` 中,具有相同 name 的 page 将被忽略
Expand Down Expand Up @@ -276,6 +253,32 @@ export default defineConfig({
})
```

## 插件对比

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

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

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

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

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

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

3. [vite-plugin-html](https://github.com/vbenjs/vite-plugin-html):只支持模板引擎,且不支持虚拟入口。

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

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

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

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

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

## 默认重定向规则

正如上面提到的👆🏻,如果你的配置遵循约定,插件将会自动生成一份重定向规则,这份配置会同时应用到开发和预览服务器,如下:
Expand Down
14 changes: 6 additions & 8 deletions workspaces/plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
],
"scripts": {
"prepublishOnly": "npm run build",
"dev": "vite build --watch",
"build": "vite build",
"watch": "tsup --watch",
"build": "tsup",
"changeset": "changeset",
"versions": "changeset version"
},
Expand All @@ -47,17 +47,15 @@
"connect-history-api-fallback": "^2.0.0",
"ejs": "^3.1.9",
"html-minifier-terser": "^7.2.0",
"picocolors": "^1.0.0"
"picocolors": "^1.0.0",
"tsup": "^8.0.1",
"vite": "^5.1.1"
},
"devDependencies": {
"@changesets/cli": "^2.27.1",
"@types/ejs": "^3.1.5",
"@types/node": "^18.19.15",
"typescript": "^5.3.3",
"vite": "^5.1.1",
"vite-plugin-checker": "^0.6.4",
"vite-plugin-dts": "^3.7.2",
"vite-plugin-externalize-deps": "^0.8.0"
"typescript": "^5.3.3"
},
"peerDependencies": {
"vite": ">= 2.0.0"
Expand Down
2 changes: 1 addition & 1 deletion workspaces/plugin/src/api-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ export interface MpaOptions<
/**
* Dedicated hook for transforming template HTML.
*/
transformTemplateHtml?: (html: string, page: Page) => string;
transformHtml?: (html: string, page: Page) => string;
/**
* Whether to minify html file. Powered by [html-minify-terser](https://github.com/terser/html-minifier-terser).
* @default false
Expand Down
10 changes: 7 additions & 3 deletions workspaces/plugin/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function createMpaPlugin<
previewRewrites,
watchOptions,
scanOptions,
transformTemplateHtml,
transformHtml,
} = config;
let resolvedConfig: ResolvedConfig;

Expand Down Expand Up @@ -212,8 +212,12 @@ export function createMpaPlugin<
const page = virtualPageMap[id];
if (!page) return null;
let templateContent = fs.readFileSync(page.template || template, 'utf-8');
if (transformTemplateHtml) {
templateContent = transformTemplateHtml(templateContent, page);
/**
* Transform before building.
* @see https://github.com/emosheeep/vite-plugin-virtual-mpa/pull/56
*/
if (typeof transformHtml === 'function') {
templateContent = transformHtml(templateContent, page);
}
return ejs.render(
!page.entry
Expand Down
7 changes: 7 additions & 0 deletions workspaces/plugin/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { defineConfig } from 'tsup';

export default defineConfig({
format: ['cjs', 'esm'],
entry: ['src/index.ts'],
dts: true,
});
25 changes: 0 additions & 25 deletions workspaces/plugin/vite.config.ts

This file was deleted.

0 comments on commit 6d22ebd

Please sign in to comment.