我的GitHub
0%

无星的前端之旅(三十)——Vite打包本地预览html

背景

最近写包,用vite+vue

结果写出来的东西无法本地打开

必须用http起来才能打开

很烦

找原因

我们使用默认模板的vite打包,生成的html

双击打开很明显在报错

提醒的提示写的很清楚了

file协议跨域

再多的原因我们不说了,搜一下都能搜到

方案一:修改打包产物

我们看打包产物的dist

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html lang="">
<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-hNmfXlPk.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-2ZaS5HyD.css">
</head>
<body>
<div id="app"></div>
</body>
</html>

type="module"就是这玩意

我们要做的就是用脚本移除它

1
2
cd /project
pnpm add @vitejs/plugin-legacy terser fs-extra -D

vite.config.ts

1
2
3
4
5
6
7
8
9
10
11
12
// vite.config.js
import legacy from '@vitejs/plugin-legacy'

export default {
// 注意这一句也要加哦
base:"./",
plugins: [
legacy({
targets: ['defaults', 'not IE 11'],
}),
],
}

新建一个handleHTML.js放在项目根目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 如果运行报错 Cannot use import statement outside a module 换成
// const fs = require("fs");
import fs from "fs-extra";

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修改build命令

1
2
3
4
5
6
{
"scripts": {
"dev": "vite",
"build": "vite build && node ./handleHTML.js",
}
}

好了,打包试试

得到index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="">
<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-C8tNBv1G.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-CujiCmXX.js"></script>
<script id="vite-legacy-entry" src="./assets/index-legacy-CFf1Cd_x.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('src'))</script>
</body>
</html>

你就可以看到页面了

但是点击页面跳转你会发现路径不对

改成hash模式就好了

方案二:打成一个文件

是的,你没看错,就是打包成一个html文件,什么拆包统统去死吧

1
pnpm add vite-plugin-singlefile -D

vite.config.ts

1
2
3
4
5
6
7
import { viteSingleFile } from 'vite-plugin-singlefile'

export default {
plugins: [
viteSingleFile()
],
}

直接打包,你会得到一个巨大的index.html文件

但是它已经可以访问了

我是阿星,阿星的阿,阿星的星!