Vue3 Vite项目打包静态文件之后无法以file协议访问

3,178 阅读1分钟

之前工作的时候用 vite 项目打包之后后端跟我说用不了,html都打不开,emmm...
vite 默认使用 ES Module 模块是不支持file协议的,需要使用插件来配置之后才可以正常使用file协议打开。

安装 @vitejs/plugin-legacy

yarn add @vitejs/plugin-legacy

vite3 版本以上还需要安装

yarn add terser

在 vite.config.js 里面使用并加上 base:"./"

import legacy from '@vitejs/plugin-legacy';
import vue from '@vitejs/plugin-vue';
import { defineConfig } from 'vite';

export default defineConfig({
  base:"./",
  plugins: [
    vue(),
    legacy()
  ],
});

路由改为哈希模式 createWebHashHistory

image.png

打包之后的html文件这样

<!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">
    <title>Vite App</title>
    <script type="module" crossorigin src="./assets/index-cd4486e7.js"></script>
    <link rel="stylesheet" href="./assets/index-9f3fdf99.css">
    <script type="module">import.meta.url;import("_").catch(()=>1);async function* g(){};if(location.protocol!="file:"){window.__vite_is_modern_browser=true}</script>
    <script type="module">!function(){if(window.__vite_is_modern_browser)return;console.warn("vite: loading legacy chunks, syntax error above and the same error below 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>
    <div id="app"></div>
    
    <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 crossorigin id="vite-legacy-polyfill" src="./assets/polyfills-legacy-f496a5dd.js"></script>
    <script nomodule crossorigin id="vite-legacy-entry" data-src="./assets/index-legacy-75662b69.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
  </body>
</html>

需要把 script 标签里面的 nomodule,crossorigin 属性删掉
删掉含有 type="module" 的标签
data-src 属性换成 src。

建议写一个node脚本来处理

安装 fs 模块

yarn add fs

新建一个js文件

image.png

// 如果运行报错 Cannot use import statement outside a module 换成
// const fs = require("fs");
import fs from "fs";

const htmlPath = "./dist/index.html"; // 打包后的html文件路径
const htmlText = fs.readFileSync(htmlPath, 'utf8');
const htmlArr = htmlText.match(/.*\n/g) || [];

let result = "";

htmlArr.forEach(v => {
  v = v
    .replace(/script ?nomodule\s?/g, "script ")
    .replace(/\s?crossorigin\s?/g, " ")
    .replace(/data-src/g, 'src');
  if (!v.includes(`script type="module"`)) {
    result += v;
  }
});

fs.writeFileSync(htmlPath, result, 'utf8');

console.log("处理完成");

在 package.json 里面配置脚本

image.png

执行

yarn html

image.png

处理之后的html

<!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">
    <title>Vite App</title>
    <link rel="stylesheet" href="./assets/index-9f3fdf99.css">
  </head>
  <body>
    <div id="app"></div>
    
    <script >!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 id="vite-legacy-polyfill" src="./assets/polyfills-legacy-f496a5dd.js"></script>
    <script id="vite-legacy-entry" src="./assets/index-legacy-75662b69.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('src'))</script>
  </body>
</html>

这样就可以双击html打开,使用file协议访问了

image.png