小元
博客
详情文字在这里缓缓展开
静候你翻开这一页

Vite 打包后支持本地预览

让vite + vue3的项目,执行npm run build后得到的产物无需经服务器部署,在本地通过双击index.html即可运行。

让 VIte+Vue3打包后的项目,在本地通过双击 index.html 即可运行预览


   前言:

       因项目需要,要求项目打包后的产物能和以前的项目一样直接在本地进行预览,不需要行经服务代理,经过一番查询,仍然踩了很多坑,再加上最近忙于项目和其它事情,也有一段时间没更新了,遂在此记录,喜欢能对各位有所帮助,减少踩坑。

   

   问题分析:

       修改index.html文件,删除script标签中带有nomodule、crossorigin的属性,修改data-src为src,link同理,所有引入资源的路径前缀都应该是./开头即相对路径而非绝对路径。

       截图:

               1724814466331.png



   原因详解:

       打包后的index.html无法直接打开的原因在于以下几点:

           script标签:

               src:打包后的资源引入是通过”data-src“引入的,而data-src是一个自定义数据属性,不是标准 HTML 属性,它通常用于存储额外的自定义数据,所以它不会被浏览器自动处理或执行。这就意味着js脚本不会被游览器自动识别和加载。

               nomodule:它的用途主要是用于提供游览器兼容性的,标识一个脚本只应在不支持 ES6 模块的浏览器中执行,而现代浏览器支持 ES6 模块,不会执行带有 nomodule 的脚本

               crossorigin:用于控制跨源请求的安全策略,对于从其他域加载的脚本,如果不设置正确的 CORS 头,浏览器可能会拒绝加载脚本或限制某些功能。

               src:加载的路径为绝对路径,即以/开头的路径,导致找不到资源

       Link标签:

               crossorigin:用于控制跨源请求的安全策略,对于从其他域加载的脚本,如果不设置正确的 CORS 头,浏览器可能会拒绝加载脚本或限制某些功能。

               href:加载的路径为绝对路径,即以/开头的路径,导致找不到资源


   解决办法:

       一. 修改路径

           在vite.config.ts文件中修改base配置为相对路径。

export default defineConfig({
    plugins: [],
    base: "./",
    // 其它配置
})

       二. 修改路由模式

           修改路由模式为has模式,不然你可能打开会看见一片空白。

           在此处需要注意的是,如果访问的地址需要携带额外前缀如:http://custom/index.html中的custom,需要在路由创建地方进行配置。

import {createRouter, createWebHashHistory} from "vue-router";

const router = createRouter({
  history: createWebHashHistory("/custom"), // 如果不需要配置前缀,不传递任何参数即可
  routes,
});

       三:安装插件

npm i @vitejs/plugin-legacy -D

       插件安装完成后在vite.config.ts中使用该插件。

import legacy from "@vitejs/plugin-legacy";

export default defineConfig(() => ({
  base: "./",
  plugins: [
    vue(),

    legacy({
      targets: ["defaults", "not IE 11"]
    }),
  ]
})

       四. 创建脚本并执行

           1. 在任意磁盘目录下新建一个文件夹,文件夹名称为英文避免使用中文,创建完成后,在文件路径处输入cmd,进入cmd控制台。

           1724815690583.png


           2. 在cmd中输入npm init,然后一路回车,然后在目录中会多出一个package.json。1724815965598.png

           3. 在安装一个用于解析dom的库。

npm i jsdom -D

           4. 新建一个文本文档,把以下内容复制进去,然后修改文件名和后缀名为build.js。

const fs = require("fs");
const { JSDOM } = require("jsdom");


function loadFile() {
    try {
        console.log("文件读取中...");
        const dom = new JSDOM(fs.readFileSync("./dist/index.html"));
        console.log("文件读取成功");

        replaceScript(dom);
    } catch {
        console.error("未找到文件!");
    }
}


function replaceScript(dom) {
    console.log('文件编译中...');

    const tags = dom.window.document.querySelectorAll("*[type=\"module\"]");
    for(var i = 0 ; i < tags.length; i++) {
        const tag = tags[i];
        if (tag) tag.parentElement.removeChild(tag);
    }

    const nomoduleTags = dom.window.document.querySelectorAll("script");
    for(var i = 0 ; i < nomoduleTags.length; i++) {
        const tag = nomoduleTags[i];

        if (!tag) return;

        tag.removeAttribute("nomodule");
        tag.removeAttribute("crossorigin");

        if (tag.getAttribute("data-src") || tag.getAttribute("src")) {
            const src = tag.getAttribute("data-src") || tag.getAttribute("src");
            tag.removeAttribute("data-src");

            if (src && src.indexOf(".") !== 0) {
                tag.setAttribute("src", "." + src);
            } else {
                tag.setAttribute("src", src);
            }
        }
    }

    const linkTags = dom.window.document.querySelectorAll("link");
    for(var i = 0 ; i < tags.length; i++) {
        const tag = tags[i];

        if (!tag) return;

        tag.removeAttribute("crossorigin");
        const href = tag.getAttribute("href");
        if (href && href.indexOf(".") !== 0) tag.setAttribute("href", "." + href);
    }

    const html = "<!DOCTYPE html>\r\n" + dom.window.document.documentElement.outerHTML;
    fs.writeFileSync("./dist/index.html", html);
    console.log('文件编译成功');
}


loadFile();


           5. 把打包好的dist文件拷贝至该目录,此时内容应是如下结构

           1725347530351.png


           6. 在cmd中执行node build.js,提示编译成功,此时双击index.html即可正常预览。

           1724816943927.png

                       

           7. 脚本解释:

               该脚本主要执行了,查找dist目录下的index.html文件,然后解析它,在查找对应的属性和标签进行移除或修改。


如果感觉本文对您有所帮组的话点个赞在走把~,如您有任何疑问或见解欢迎您在下方评论区留言讨论

渝ICP备2024031078号-1
本网站一切内容不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
如无意中侵犯了企业或个人的知识产权等,请及时通过电子邮件(1102905617@qq.com)告知我,本网站将会给予删除。
最新公告
😊访客你好,很高兴你的到来,本博客仍在建设中,还有些许功能尚在开发中,最后祝你在此能有所收获。
💥小元博客第三代自2025年9月上线以来,2026/08/09日迎来了它的第三次更新本次更新内容如下:
1. 文章详情页样式变更,由原来的弹窗改为单独的页面。
2. 使用Nuxt对项目进行了SEO优化,优化了搜索引擎的抓取和索引。
3. 对验签进行了优化,降低了请求被误触发拦截的概率。
4. 移动端也正在稳步推进中,在不久的将来会与大家见面。
5. 修复了首页黄历节日不显示的问题,以及其它bug的修复。