Skip to content

The transformIndexHtml hook can't get the real html in the context. #5851

@helianthuswhite

Description

@helianthuswhite

Describe the bug

I'm using the transformIndexHtml hook to replace all src values of <script> or <link>, just like this:

<script type=module crossorigin src=/assets/index.25a99b3b.js>
👇
<script type=module crossorigin src=http://localhost:3000/assets/index.25a99b3b.js>

It works well until i use the @vitejs/plugin-legacy plugin.

@vitejs/plugin-legacy will insert polyfills to the end of index.html, but i can't get it in transformIndexHtml hook.

For example the legacy index.html looks like:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
  <script async type="module" crossorigin src="/assets/index.935273ac.js"></script>
  <script type="module">!function(){try{new Function("m","return import(m)")}catch(o){console.warn("vite: loading legacy build because dynamic import is unsupported, syntax error above should be ignored");var e=document.getElementById("vite-legacy-polyfill"),n=document.createElement("script");n.src=e.src,n.onload=function(){System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))},document.body.appendChild(n)}}();</script>
</head>
<body>
    aaa
  <script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
  <script nomodule id="vite-legacy-polyfill" src="/assets/polyfills-legacy.c65045de.js"></script>
  <script nomodule id="vite-legacy-entry" data-src="/assets/index-legacy.57083f81.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
</body>
</html>

I actually get in my transformIndexHtml hook:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
  <script async type="module" crossorigin src="/assets/index.935273ac.js"></script>
</head>
<body>
    aaa
</body>
</html>

It seems strange before i read the code of vite. I just found the reason in the below function.

If the pre hook returns tags, these tags will be injected after all hooks exec done. However, in this way, post transformIndexHtml hooks will never controller the real index.html!
image

I think it's a bug so i report it. Looking forward to be replied : )

Reproduction

https://github.com/helianthuswhite/vite-test-demo

System Info

System:
    OS: macOS 11.6
    CPU: (8) x64 Apple M1
    Memory: 22.79 MB / 16.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 14.17.4 - /usr/local/bin/node
    Yarn: 1.22.11 - /opt/homebrew/bin/yarn
    npm: 7.18.1 - /opt/homebrew/bin/npm
  Browsers:
    Chrome: 96.0.4664.55
    Safari: 14.1.2
  npmPackages:
    @vitejs/plugin-legacy: ^1.6.3 => 1.6.3 
    vite: ^2.6.14 => 2.6.14

Used Package Manager

npm

Logs

No response

Validations

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions