vite-plugin-multipage
Adds multi-page application support to Vite.
Installation & Usage
First:
npm i --save-dev vite-plugin-multipage
Then, in vite.config.js
, something like this:
import { defineConfig } from "vite";
import solid from "vite-plugin-solid";
import multipage from "vite-plugin-multipage";
export default defineConfig({
plugins: [
solid(),
multipage({
// This is an optional object, defaults as follows:
mimeCheck: true /* mimeCheck: Set the MIME type on each request using
`mime-types.lookup()` */,
open: "/" /* open: Path to load when starting the server.
May be left empty and not open anything. */,
pageDir: "pages" /* pageDir: Path to the directory with the pages. */,
purgeDir: "pages" /* purgeDir: Path to be removed after building.
May be left empty to remove nothing. */,
removePageDirs: true /* removePageDirs: Change the final result from
"./page/index.html" to "./page.html". */,
rootPage: "index.html" /* rootPage: The entry point into each page. */,
}),
],
resolve: {
alias: {
"@": path.resolve(__dirname, "./"),
},
},
build: {
target: "esnext",
polyfillDynamicImport: false,
},
});
What does it do?
This plugin extends Vite to handle collections of single-page applications. By following a simple and adjustable naming convention, Vite will ultimately bundle your collection of pages as:
build.outDir: (./dist, by default)
./assets/ ./index/index.html ./pagetwo/index.html ... ./pagetwenty/index.html
The project directory for the above would maybe look like:
|--- ./package.json
|--- ./vite.config.js
|--- ./assets/
|--- ./components/
|--- ./pages/ # This is set by $pageDir.
|--- ./index/
|--- ./views/
|--- ./index.css
|--- ./index.html
|--- ./index.jsx
|--- ./pagetwo/
|--- ./index.css
|--- ./index.html # The HTML *must* match $rootPage!
|--- ./index.jsx
[....]
|--- ./pagetwenty/
|--- ./index.css
|--- ./index.html
|--- ./index.jsx
The contents of ./pagetwo/index.html
would resemble:
<!DOCTYPE html>
<html lang="en">
<head>
<title>example page</title>
<link rel="icon" href="/assets/favicon.ico" />
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
</head>
<body>
<noscript>you need to enable javascript to run this app</noscript>
<div id="root"></div>
<script src="/pages/pagetwo" type="module"></script>
</body>
</html>
And ./pagetwo/index.jsx
:
import { render } from "solid-js/web";
import "./index.css";
import logo from "@/assets/logo.svg";
function App() {
return (
<div>
<header>
<img src={logo} alt="logo" />
<p>you are on page 2 :(</p>
<a href="/pagetwenty">go to page 20 !</a>
</header>
</div>
);
}
render(App, document.getElementById("root"));
What's the catch?
There are some small caveats to keep in mind with this setup and it is all related to path resolving.
HTML files must link to files from the perspective of the project root. The
only allowed shortcut is that you may omit the .jsx
in links and the entire
/index.jsx
, such as using /pages/foo
instead of /pages/foo/index.jsx
.
JSX files need an @
alias to point to the project root when linking to
./assets/
and similar other files. It is not available from inside HTML.
Otherwise the linking perspective is from that of the current file directory.
You have several options when linking between pages from JSX due to link rewriting that this plugin does with the Vite server:
href="/"
will point to/pages/index/index.html
.href="/foo"
will point to/pages/foo/index.html
.href="/foo.html
will also point to/pages/foo/index.html
.href="/foo/index.html
will also point to/pages/foo/index.html
.
What convention you select to use will depend on your configuration of
removePageDirs
and if you will be doing path or hash based routing:
- Path based routing:
removePageDirs: false
, usehref="/foo"
- Hash based routing:
removePageDirs: true
, usehref="/foo.html"
- Single page sites:
removePageDirs: true
, usehref="/"
This plugin will rewrite /foo
to /pages/foo/index.html
to allow for
in-page path routing libraries to function. You will be responsible for doing
similar in your production server, where /foo
should be mapped to either
/foo/index.html
or /foo.html
depending on how removePageDirs
is set.
Finally, the $purgeDir
directory is removed. This typically will be the same
path as $pageDir
, however in the case of $pageDir
being set to src/pages
you will likely wish to set $purgeDir
to src
rather than src/pages
. This
is up to you, depending if you use the src
prefix directory and if you have
other directories you would like copied to the final build directory.
License
0BSD