vite打包静态文件打开显示空白的解决
笨钟 人气:0需求场景
- 本地调试访问打包的文件看是否有啥问题,方便定位线上问题
- 安卓手机需要去直接访问静态文件,而不是访问域名的情况
vite 打包生成的文件如果直接放在服务器中是可以正常访问的,但是本地直接访问打包生成index.html
文件就会提示以下问题。
- 访问的文件不存在,主要是因为路径配置问题。
- 提示跨域问题,不支持files协议,主要是因为esModule问题。
问题1:访问的文件不存在,主要是因为路径配置问题。
解决:在 vite.config.js
文件中配置
export default defineConfig({ ... base: "./", ... })
验证路径是否正常看浏览器中的network看文件是否加载正常
问题2. 提示跨域问题,不支持files协议,主要是因为esModule问题
对比webpack 打包静态文件是否可以正常访问
答案:正常
在vue.config.js 文件中配置
module.exports = { outputDir: 'dist', publicPath: baseUrl,
原理:开始通过file协议直接访问index.html,在index.html中静态引入index.js,在index.js中import test.js。在import的过程中需要http服务器去解析es6语法并添加header头信息去跨域引入test.js,但是file协议相当于通过资源管理器静态访问index.html,中间的过程没有http服务器参与解析,所以无法识别es6的import语法。
解决:将打包生成的文件改成为没有moudle的文件
step1:安装
$ npm install @vitejs/plugin-legacy
step2: 配置vite.config.js
import legacy from '@vitejs/plugin-legacy'; export default defineConfig({ .... plugins: [legacy({ targets: ['defaults', 'not IE 11'] }),vue()], build:{ target: ['es2015', 'chrome63'], // 默认是modules,百度说是更改这个会去输出兼容浏览器,尝试没啥作用,先配置吧 } .... })
step3:
在dist并列的文件夹中创建脚本文件 (用于替换module等关键词,省的每次得手动删除)toFile.cjs
创建 toFiles.cjs (为啥格式不是js为了执行命令不报兼容的错误)
import fs from 'fs'; console.time('转换耗时'); const distPath = './dist/index.html';//打包路径的index.html let htmlText = fs.readFileSync(distPath, 'utf8'); let resultText = ''; let htmlArr = htmlText.match(/.*\n/g) || []; htmlArr.forEach(str => { str = str.replace(/\s?nomodule\s?/g,' '); str = str.replace(/\s?crossorigin\s?/g,' '); str = str.replace(/data-src/g,'src'); if(!/type="module"/i.test(str)) resultText += str; }); fs.writeFileSync(distPath,resultText,'utf8'); console.timeEnd('转换耗时');
step4:
npm install fs // 安装fs node toFile.cjs // 执行脚本
step5: 查看 dist 文件夹中的 index.html
文件,查看是否没有module 、 crossorigin 等关键词,访问index.html
文件 查看效果
一般执行到这里基本是可以正常访问的,但是我的项目还是空白,后面观察加载的html结构发现router-view的组件没有加载上去,后面尝试将router.js 文件中history模式改成了hash,然后再重新打包执行上面的操作能够正常打开。
总结:
vite生成的文件会带有module,导致存在跨域问题,大多数项目开发都是将文件放在服务器中通过域名去访问,但是特殊情况需要直接访问静态资源。所以要去解决file存在跨域的问题。
反思:
- webpack为啥打包出的文件同样是file直接访问但是不存在跨域。
- webpack为啥打包出的文件不带module,但是file打包会带module。
借鉴其他的博文总结:
1、给引用文件设置type="module"等于给文件设置了私有作用域,xx.js文件成了单独的模块,运行在自己的私有作用域中,而不是全局作用域中。
2、虽然script标签自带跨域能力(这也是某些场合会通过jsonp结合script来请求资源的原因),但是这里的跨域是指的http协议(协议、域名、端口一致),file协议是不支持跨域的。
3、es6声明type=“module”,这类使用了模块的script是受限于同源策略的。
参考:
加载全部内容