vite
vite copied to clipboard
Built-in Multi-Page App Support on Build
Clear and concise description of the problem
As a developer of multi-page apps, I would like have all of the pages automatically included when running the build command instead of manually configuring each path. Given it works as expected during development, this feels more like a bug in build than a feature.
Suggested solution
Either automatically, or provide a config to automatically, include all globbed HTML files in the Vite root as rollup inputs.
Alternative
It can be done through globbing in Vite config, or using a plugin, although I've found the plugin route to be unreliable.
Additional context
A post on my current solution to this can be found here
Have you tried https://github.com/IndexXuan/vite-plugin-mpa?
@IndexXuan this issue may be interesting to you.
Yes I have and it didn't work for me, to a point where it was easier to write the globbing I needed than try and trace the problem in the plug-in
On May 15, 2021, at 1:40 PM, patak @.***> wrote:
Have you tried https://github.com/IndexXuan/vite-plugin-mpa?
@IndexXuan this issue may be interesting to you.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.
@patak-js @Snugug I dont know why it didn't work for you. can you give more context ? this plugin in development: auto glob pages and configure vite options and rewrite url like vue-cli MPA. in build: auto glob pages and optimize structure like vue-cli MPA dist.
Also it support html template like vue-cli by https://github.com/IndexXuan/vite-plugin-html-template
Simple workaround:
{
build: {
rollupOptions: {
input: require('fast-glob').sync(['./**/*.html', '!dist']).map(entry => path.resolve(__dirname, entry))
}
}
}
@geordie2020 Normally you wouldn't traverse each subdirectory except for dist/
.
I'd suggest an allowlist rather than a denylist.
// vite.config.js
import glob from 'fast-glob';
rollupOptions: {
input: Object.fromEntries(
glob.sync(['./*.html', './pages/**/*.html']).map(file => [
// This remove `pages/` as well as the file extension from each
// file, so e.g. pages/nested/foo.html becomes nested/foo
path.relative(__dirname, file.slice(0, file.length - path.extname(file).length)),
// This expands the relative paths to absolute paths, so e.g.
// src/nested/foo becomes /project/src/nested/foo.js
fileURLToPath(new URL(file, import.meta.url)),
]),
),
},
// vite.config.js import glob from 'fast-glob'; rollupOptions: { input: Object.fromEntries( glob.sync(['./*.html', './pages/**/*.html']).map(file => [ // This remove `pages/` as well as the file extension from each // file, so e.g. pages/nested/foo.html becomes nested/foo path.relative(__dirname, file.slice(0, file.length - path.extname(file).length)), // This expands the relative paths to absolute paths, so e.g. // src/nested/foo becomes /project/src/nested/foo.js fileURLToPath(new URL(file, import.meta.url)), ]), ), },
https://rollupjs.org/configuration-options/#input
This helped me a lot, thanks friend!
// This remove `pages/` as well as the file extension from each // file, so e.g. pages/nested/foo.html becomes nested/foo path.relative(__dirname, file.slice(0, file.length - path.extname(file).length)),
☝️ This won't achieve the desired result, unfortunately, it will still get output as build/pages/nested/foo.html
. All HTML entries are built relative to root
directory, I didn't find a way to control this 😕
Even vite-plugin-mpa has this as an experimental feature:
Experimental: when building, organize the folder for you (like vue-cli) - e.g
dist/src/pages/subpage/index.html
will move todist/subpage/index.html
// This remove `pages/` as well as the file extension from each // file, so e.g. pages/nested/foo.html becomes nested/foo path.relative(__dirname, file.slice(0, file.length - path.extname(file).length)),
☝️ This won't achieve the desired result, unfortunately, it will still get output as
build/pages/nested/foo.html
. All HTML entries are built relative toroot
directory, I didn't find a way to control this 😕Even vite-plugin-mpa has this as an experimental feature:
Experimental: when building, organize the folder for you (like vue-cli) - e.g
dist/src/pages/subpage/index.html
will move todist/subpage/index.html
Maybe we can only keep the last 2 directories, like that:
path.join(...file.split(path.sep).slice(-2))
Not sure what you mean, could you be more specific? Vite doesn't allow changing output path of HTML files, I don't think they have plans to change this. #15612
Adding more various info in case it helps anyone reading this.
Configuring your static router to look for HTML files in pages/*
as a fallback might be a viable solution as well, and possibly the easiest workaround, I haven't tried it yet.
What I did in my project is created the following directory structure:
src/
index.html
about.html
blog/
index.html
...assets
then I set Vite's root
to src
. That way output is as I want it to be. Everything that's being imported must be in src
. But this setup leads to some annoying additional configs, like setting build.outDir
to ../build
because those paths are being computed relative to src
.
Regardless of which solution you choose, as far as listing HTML files goes, you can pass input paths to as an array to rollupOptions.input
and omit output paths altogether AFAIK.
// This remove `pages/` as well as the file extension from each // file, so e.g. pages/nested/foo.html becomes nested/foo path.relative(__dirname, file.slice(0, file.length - path.extname(file).length)),
☝️ This won't achieve the desired result, unfortunately, it will still get output as
build/pages/nested/foo.html
. All HTML entries are built relative toroot
directory, I didn't find a way to control this 😕 Even vite-plugin-mpa has this as an experimental feature:Experimental: when building, organize the folder for you (like vue-cli) - e.g
dist/src/pages/subpage/index.html
will move todist/subpage/index.html
Maybe we can only keep the last 2 directories, like that:
path.join(...file.split(path.sep).slice(-2))
I known, rollupOptions.input won't change the output path after building.
Is there a solution to this issue?
Multiple workarounds are mentioned throughout the conversation, depending on which kind you're looking for.
In the last meeting, we decided to prefer an explicit approach instead because we don't want users to accidentally build HTML files in test-results
or __tests__
, or an any potential name that they may not want. To make sure this works well in dev and build, dev should warn instead if it's accessing a HTML page that's not in the build list.
What we didn't discuss though (an idea I just had), is maybe Vite could probably a utility function to easily generate the input
with globs.
Inputs with globs, and/or excludes with globs, and warning if something isn't covered sounds like a good path forward
Multiple workarounds are mentioned throughout the conversation, depending on which kind you're looking for.
But sadly none of them really work.
It would be nice to for example have
src/
pages/
index.html
about.html
blog/
index.html
...assets
being built into
dist/
index.html
about.html
blog/
index.html
...assets
Or using any input directory for the pages. But this does not work at all and none of the workarounds work properly.
There are two issues:
- the lesser problem is that picking up the html pages as input requires fancy rollup configuration
- the bigger problem is that the produced output will be like
dist/src/pages/index.html
instead ofdist/index.html
The latter has no workaround besides setting Vite's root
to the subdirectory, resulting in undesired side effects and breaking other things.
@dagnelies exactly this supports vituum.dev as a Vite plugin :)
@lubomirblazekcz I think going by the docs it still builds only the immediate index.html with its assets.
I would echo that with @dagnelies and add to the thread that the paths in meta tags (og:
etc.) may have https://
paths, in which case it would be nice if they were transformed too. Also one may have inline JSON-LD tags that also contain https://
paths to to image assets, which would be nice to have transforme too. Or alternatively kept as-is and the file structure moved and optimized in-place (maybe with JS file locations aren't such an issue considering their usage).
It may be something like https://modern-web.dev/docs/building/rollup-plugin-html/ could help people who stumble up here like I did. I just want to a way to build fairly simple multi-page apps and retain structure so it works when deployed, with some optimizations. :)