Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

transformIndexHtml hook gets the wrong html filepath when running Multi-Page #2958

Closed
yaquawa opened this issue Apr 12, 2021 · 13 comments
Closed

Comments

@yaquawa
Copy link
Contributor

yaquawa commented Apr 12, 2021

Describe the bug

transformIndexHtml hook gets the wrong html filepath when running Multi-Page.

Reproduction

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolvePath } from './utils'

export default defineConfig({
  plugins: [
    vue(),
  ],

  build: {
    rollupOptions: {
      input: {
        main: resolvePath('index.html'),
        landingPage: resolvePath('landing-page/index.html'),
      },

    },
  },
})

Project root directory structure:

  • index.html
  • landing-page
    • index.html

in the transformIndexHtml hook:

async transformIndexHtml(html, { filename }) { ... }

Go to /landing-page/
filename will be <root>/landing-page/index.html witch is correct.

but, if go to /landing-page/foo/
filename will be <root>/index.html which is the the wrong filename.

it really should be <root>/landing-page/index.html when the url is subpath of /landing-page/.

Sure I can fix this by add an additional middleware to the ViteDevServer, but it really should detect if it is a Multi-Page, if it is, add the routes for it automatically.

Reproduction

  1. clone https://github.com/ssr-glue/vite-plugin
  2. run yarn
  3. remove comment https://github.com/ssr-glue/vite-plugin/blob/755371d940fbea6365a38cab0f9c03e868f0db91/packages/playground/vue/vite.config.ts#L18-L27
  4. add console.log to log the ctx.filename, https://github.com/ssr-glue/vite-plugin/blob/755371d940fbea6365a38cab0f9c03e868f0db91/packages/vite-plugin/src/plugin.ts#L67-L78 then run yarn build
  5. goto packages/playground/vue run yarn dev
  6. goto http://localhost/landing-page/about to see the log
@github-actions
Copy link

Hello @yaquawa. Please provide a online reproduction by codesandbox or a minimal GitHub repository. Issues labeled by need reproduction will be closed if no activities in 3 days.

@yaquawa
Copy link
Contributor Author

yaquawa commented Apr 12, 2021

Hi, I have added the reproduction steps. Please take a look at. Thanks.

@anncwb
Copy link
Contributor

anncwb commented Apr 13, 2021

I am not sure if this is expected, vite is currently redirected to index.html locally, and the configuration build mentioned in the document https://vitejs.dev/guide/build.html#multi-page-app build.rollupOptions.input is just For the production environment.
The development environment is fixed to use index.html under config.root

return path.join(server.config.root, url.slice(1))

@yaquawa
Copy link
Contributor Author

yaquawa commented Apr 13, 2021

Hi @anncwb Thanks for replying!
The current behavior doesn't allow user to route on nested pages which is obviously a bug I think.

@bluwy
Copy link
Member

bluwy commented Mar 6, 2022

I second @anncwb. Vite currently performs a simple fallback when the route index.html is not found. Resolving subpaths to their own index.html (as shown in the issue description), feels like a special routing behaviour that should be implemented in userland via server middlewares. If Vite happens to support this today, it would be a breaking change too.

@poyoho
Copy link
Member

poyoho commented Mar 11, 2022

look expects to me
but if <root>/landing-page/index.html is SPA project too and /landing-page/foo/ load the <root>/index.html is also a problem? It does seem strange.

vite's documentation need to mention this.

@poyoho poyoho mentioned this issue Mar 11, 2022
4 tasks
@haoqunjiang
Copy link
Member

Some related issues #5757 #7095
Do we need to expose the history API fallback options like in webpack https://webpack.js.org/configuration/dev-server/#devserverhistoryapifallback?

@bluwy
Copy link
Member

bluwy commented Mar 11, 2022

I'm a bit wary of adding new options, but it does seem like doing so could provide a workaround for this PR.

@poyoho
Copy link
Member

poyoho commented Mar 12, 2022

you can use middleware in vite dev server to rewrite url what you want.

const { defineConfig } = require('vite')
module.exports = defineConfig({
  plugins: [
    {
      name: 'rewrite-middleware',
      configureServer(serve) {
        serve.middlewares.use((req, res, next) => {
          if (req.url.startsWith('/nested/')) {
            req.url = '/nested/'
          }
          next()
        })
      }
    }
  ]
})

so /nested/**/* will go to <root>/nested/index.html

@nneto
Copy link

nneto commented Jun 4, 2022

you can use middleware in vite dev server to rewrite url what you want.

const { defineConfig } = require('vite')
module.exports = defineConfig({
  plugins: [
    {
      name: 'rewrite-middleware',
      configureServer(serve) {
        serve.middlewares.use((req, res, next) => {
          if (req.url.startsWith('/nested/')) {
            req.url = '/nested/'
          }
          next()
        })
      }
    }
  ]
})

so /nested/**/* will go to <root>/nested/index.html

I'm having issues with trailing slashes. Using this example, I replaced startsWith('/nested/') for startsWith('\nested') and again index.html is used instead of /nested/index.html. Only if I access "/nested/" the index in the subdir will be used. (Although, that's a problem only in development. In production the trailing slash doesn't cause issues)

@ShivamJoker
Copy link

Any updated on this I am also having the redirection issue

@sapphi-red
Copy link
Member

you can use middleware in vite dev server to rewrite url what you want.

const { defineConfig } = require('vite')
module.exports = defineConfig({
  plugins: [
    {
      name: 'rewrite-middleware',
      configureServer(serve) {
        serve.middlewares.use((req, res, next) => {
          if (req.url.startsWith('/nested/')) {
            req.url = '/nested/'
          }
          next()
        })
      }
    }
  ]
})

so /nested/**/* will go to <root>/nested/index.html

It seems path rewriting does not work with this plugin.

const processNodeUrl = (
node: AttributeNode,
s: MagicString,
config: ResolvedConfig,
htmlPath: string,
originalUrl?: string,
moduleGraph?: ModuleGraph
) => {
let url = node.value?.content || ''
if (moduleGraph) {
const mod = moduleGraph.urlToModuleMap.get(url)
if (mod && mod.lastHMRTimestamp > 0) {
url = injectQuery(url, `t=${mod.lastHMRTimestamp}`)
}
}
const devBase = config.base
if (startsWithSingleSlashRE.test(url)) {
// prefix with base (dev only, base is never relative)
s.overwrite(
node.value!.loc.start.offset,
node.value!.loc.end.offset,
`"${devBase + url.slice(1)}"`,
{ contentOnly: true }
)
} else if (
url.startsWith('.') &&
originalUrl &&
originalUrl !== '/' &&
htmlPath === '/index.html'
) {
const replacer = (url: string) =>
path.posix.join(
devBase,
path.posix.relative(originalUrl, devBase),
url.slice(1)
)
// #3230 if some request url (localhost:3000/a/b) return to fallback html, the relative assets
// path will add `/a/` prefix, it will caused 404.
// rewrite before `./index.js` -> `localhost:5173/a/index.js`.
// rewrite after `../index.js` -> `localhost:5173/index.js`.
s.overwrite(
node.value!.loc.start.offset,
node.value!.loc.end.offset,
node.name === 'srcset'
? `"${processSrcSetSync(url, ({ url }) => replacer(url))}"`
: `"${replacer(url)}"`
)
}
}

@bluwy
Copy link
Member

bluwy commented Dec 29, 2022

Looking back, I think this is still expected. Vite default runs in SPA mode, so 404s redirect to /index.html. You can set appType: 'mpa' so that 404s stay as 404s. Redirecting to subpath index.html isn't how most servers and hosting providers work by default so it make sense to not support it. If you do have a custom server that supports it, you can create a custom plugin that injects a middleware to achieve that like the above examples. Closing with the reasons above.

@bluwy bluwy closed this as not planned Won't fix, can't repro, duplicate, stale Dec 29, 2022
@github-actions github-actions bot locked and limited conversation to collaborators Jan 13, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants