kotarella1110 / vite-plugin-qiankun-lite

A simple Vite plugin for efficiently running MicroFrontend applications using qiankun
https://www.npmjs.com/package/vite-plugin-qiankun-lite
MIT License
9 stars 1 forks source link

Bug: vite 4.5 output incorrect html file #21

Closed zeyongTsai closed 6 months ago

zeyongTsai commented 6 months ago

if index.html has style tag that has a css rule , output html will repeat html in sytle tag.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content=".." />
    <style>
      body {
        width: 100%;
        height: 100%;
      }
    </style>
  </head>
<body>
<script type="module" src="/src/main.ts"></script>
  </body>
</html>

output

<!DOCTYPE html><html lang="en"><head>
    <script>
      const nativeGlobal = Function("return this")();
      nativeGlobal.__QIANKUN_WINDOW__ = nativeGlobal.__QIANKUN_WINDOW__ || {};
      nativeGlobal.__QIANKUN_WINDOW__["vue-app"] = nativeGlobal.proxy || nativeGlobal;
    </script>

    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="..">
    <style><!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content=".." />
    <style>
      body {
        width: 100%;
        height: 100%;
      }
    </style>
  </head>

  <body>
    <script>import((__QIANKUN_WINDOW__["vue-app"].__INJECTED_PUBLIC_PATH_BY_QIANKUN__ || "").replace(/\/$/, "") + "/src/main.ts")</script>

    <script crossorigin="">
      window["vue-app"] = {};
      const lifecycleNames = ["bootstrap", "mount", "unmount", "update"];
      import((__QIANKUN_WINDOW__["vue-app"].__INJECTED_PUBLIC_PATH_BY_QIANKUN__ || "").replace(/\/$/, "") + "/assets/index-b9d32e45.js").then((lifecycleHooks) => {
        lifecycleNames.forEach((lifecycleName) =>
          window["vue-app"][lifecycleName].resolve(
            lifecycleHooks[lifecycleName],
          ),
        );
      });
      lifecycleNames.forEach((lifecycleName) => {
        let resolve;
        const promise = new Promise((_resolve) => (resolve = _resolve));
        window["vue-app"][lifecycleName] = Object.assign(
          (...args) => promise.then((lifecycleHook) => lifecycleHook(...args)),
          { resolve },
        );
      });
    </script>

</body></html>

vite config

import vue from "@vitejs/plugin-vue";
import { defineConfig } from "vite";
import qiankun from "vite-plugin-qiankun-lite";
import { name } from "./package.json";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue(), qiankun({ name, sandbox: !!process.env.VITE_SANDBOX })],
  server: {
    cors: true,
    origin: "*",
  },
});

when I removed qiankun:remain-exports plugin,output normal.

zeyongTsai commented 6 months ago

I think here using AST only replaces the import js/ts statements with export * from, and skips over other statements that are unlikely to be exported and that are needed by qiankun's lifecycle.

https://github.com/kotarella1110/vite-plugin-qiankun-lite/blob/500e74b0a2a4a2cb633d251d946c6883df1678a0/packages/vite-plugin-qiankun-lite/src/index.ts#L28

if there is export * from ahead of css, the resource query would add a used parameter at the begin.

https://github.com/vitejs/vite/blob/aac695e9f8f29da43c2f7c50c549fa3d3dfeeadc/packages/vite/src/node/plugins/importAnalysisBuild.ts#L401-L402

html-inline-proxy plugin's RegExp: htmlProxyRE matches failed. ( it should resolve css text inside style tag )

return {
    name: 'vite:html-inline-proxy',

    resolveId(id) {
      if (htmlProxyRE.test(id)) {
        return id
      }
    },

    load(id) {
      const proxyMatch = id.match(htmlProxyRE)
      if (proxyMatch) {
        const index = Number(proxyMatch[1])
        const file = cleanUrl(id)
        const url = file.replace(normalizePath(config.root), '')
        const result = htmlProxyMap.get(config)!.get(url)?.[index]
        if (result) {
          return result
        } else {
          throw new Error(`No matching HTML proxy module found from ${id}`)
        }
      }
    },
  }

https://github.com/vitejs/vite/blob/aac695e9f8f29da43c2f7c50c549fa3d3dfeeadc/packages/vite/src/node/plugins/html.ts#L95

kotarella1110 commented 6 months ago

@zeyongTsai Thank you for your feedback! I will fix.