DEV Community

Pacharapol Withayasakpunt
Pacharapol Withayasakpunt

Posted on • Originally published at gist.github.com

4 1

Multiple page Vite on Github Pages with HTML5 History Mode

Indeed, one of the way is simply pre-render (e.g. with vite-plugin-ssr).

Nonetheless, it is possible to enable fallback (without redirect settings, which doesn't exist in Github Pages), if you don't want to pre-render, and sacrifice JavaScript-ness yet. The way is, to clone dist/index.html to dist/sub/route/index.html. (SSG's also have multple **/index.html.)

import { existsSync, mkdirSync, copyFileSync } from 'fs'
import { resolve as pathResolve, join as pathJoin } from 'path'

function cloneIndexHtmlPlugin(routes: string[] = []): PluginOption {
  const name = 'CloneIndexHtmlPlugin'
  const outDir = 'dist' // config's `build.outDir`
  const src = pathJoin(outDir, 'index.html')

  return {
    name,
    closeBundle: () => {
      // routes.push(...)

      routes.map((p) => {
        const dir = pathResolve(outDir, p)
        if (!existsSync(dir)) {
          mkdirSync(dir, { recursive: true })
        }

        const dst = pathJoin(outDir, p, 'index.html')

        // It is possible to edit HTML here, too.
        copyFileSync(src, dst)
        console.log(`${name}: Copied ${src} to ${dst}`)
      })
    },
  }
}
Enter fullscreen mode Exit fullscreen mode

And put the plugin in vite.config.ts

// https://vitejs.dev/config/
export default {
  base: `/${GITHUB_REPO_NAME}/`
  plugins: [cloneIndexHtmlPlugin()],
}
Enter fullscreen mode Exit fullscreen mode

Integrating with Vue 3 and Vue Router 4

VueRouter makes navigating easier, without full page reload; however, it does need a little extra config - baseURL.

import { createRouter, createWebHistory } from 'vue-router'

export const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    // Define your routes here
  ],
})
Enter fullscreen mode Exit fullscreen mode

Route names can be glob dynamically with import.meta.glob.

import { createRouter, createWebHistory } from 'vue-router'

export const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    // Does not allow string templating - `${PAGE_DIR}/**/*${PAGE_EXT}` does not work.
    ...Object.entries(import.meta.glob('../pages/**/*.vue')).map(
      ([p, component]) => {
        const PAGE_DIR = '../pages'
        const PAGE_EXT = '.vue'
        const PAGE_INDEX = 'index'

        let path = p.substring(PAGE_DIR.length, p.length - PAGE_EXT.length)
        if (path.endsWith(PAGE_INDEX)) {
          path = path.substring(0, path.length - PAGE_INDEX.length - 1)
        }
        if (!path) {
          path = '/'
        }

        return {
          path,
          component,
        }
      },
    ),
  ],
})
Enter fullscreen mode Exit fullscreen mode

cloneIndexHtmlPlugin should also glob - fast-glob is what import.meta.glob uses, so copy it.

import { sync as glob } from 'fast-glob'

// ...

      const PAGE_EXT = '.vue'
      const PAGE_INDEX = 'index'

      routes.push(
        ...glob(`**/*${PAGE_EXT}`, {
          cwd: 'src/pages',
        })
          .map((p) => {
            p = p.substring(0, p.length - PAGE_EXT.length)
            if (p.endsWith('/' + PAGE_INDEX)) {
              p = p.substring(0, p.length - PAGE_INDEX.length - 1)
            }

            return p
          })
          .filter((p) => p !== PAGE_INDEX),
      )
Enter fullscreen mode Exit fullscreen mode

Dynatrace image

Frictionless debugging for developers

Debugging in production doesn't have to be a nightmare.

Dynatrace reimagines the developer experience with runtime debugging, native OpenTelemetry support, and IDE integration allowing developers to stay in the flow and focus on building instead of fixing.

Learn more

Top comments (3)

Collapse
 
lexlohr profile image
Alex Lohr

Do you have a demo site on which this can be seen?

Collapse
 
patarapolw profile image
Pacharapol Withayasakpunt • Edited

patarapolw.github.io/jptools

There is no this link directly on the repo, but Environments: github-pages can be seen.

It is also deployed to Netlify (without netlify.toml), but unlike Vercel, it doesn't show up in "Environments".

Collapse
 
luckylooke profile image
Ctibor Laky

The link provided end up in 404 for me, but I have found the repo here: github.com/patarapolw/jptools 👍🙂

Scale globally with MongoDB Atlas. Try free.

Scale globally with MongoDB Atlas. Try free.

MongoDB Atlas is the global, multi-cloud database for modern apps trusted by developers and enterprises to build, scale, and run cutting-edge applications, with automated scaling, built-in security, and 125+ cloud regions.

Learn More

👋 Kindness is contagious

Explore this insightful write-up, celebrated by our thriving DEV Community. Developers everywhere are invited to contribute and elevate our shared expertise.

A simple "thank you" can brighten someone’s day—leave your appreciation in the comments!

On DEV, knowledge-sharing fuels our progress and strengthens our community ties. Found this useful? A quick thank you to the author makes all the difference.

Okay