目录结构
根据 Vite 官网多页面应用模式介绍:
├── package.json
├── vite.config.js
├── index.html
├── main.js
└── nested
├── index.html
└── nested.js
这样的目录结构显然不能让人满意。
于是参考网上的做了一番改造,项目最终目录结构大致如下:
├── .husky
├── build
├── node_modules
└── src
├── apis
├── assets
├── components
└── pages
└── signin
├── App.vue
├── index.html
└── main.ts
└── about
├── App.vue
├── index.html
└── main.ts
└── router
├── types
├── utils
├── App.vue
├── index.html
├── main.ts
├── style.css
└── vite-nv.d.ts
└── .commitlintrc.json
├── .edtorconfig
├── .env
├── .env.development
├── .env.production
├── .env.testing
├── .eslintignore
├── .eslintrc
├── .eslintrc-auto-import.json
├── .gitignore
├── .prettierignore
├── .prettier
├── auto-import.d.ts
├── components.d.ts
├── package.json
├── pnpm-lock.yaml
├── README.md
├── stats.html
├── tailwind.config.js
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.js
打包配置
vite.config.ts 配置,主要配置 build.rollupOptions:
rollupOptions: {
input: {
entry: resolve(__dirname, 'src/index.html'),
signin: resolve(__dirname, 'src/pages/signin/index.html'),
about: resolve(__dirname, 'src/pages/about/index.html'),
},
output: {
assetFileNames: 'assets/[name]-[hash].[ext]', // 静态资源
chunkFileNames: 'js/[name]-[hash].js', // 代码分割中产生的 chunk
entryFileNames: 'js/[name]-[hash].js', // 指定 chunks 的入口文件
compact: true,
manualChunks: (id: string) => {
if (id.includes('node_modules')) {
return id
.toString()
.split('node_modules/')[1]
.split('/')[0]
.toString() // 拆分多个 vendors
}
},
},
},
input 是配置打包的入口文件,不过在生成打包的 HTML 资源文件时,使用文件已解析的路径 ID。
output 是配置生成文件的文件名格式,以及分割代码相关配置。
其中 rollup 的相关配置参考:rollupjs.org/configurati…
打包原理
在设置了以上的目录文件之后,还要修改相应的内容。
src/index.html 是最外层的主页,src/pages/signin/index 是子页面入口。相当于每一个页面都可以实例化 Vue。
- index.html:页面的主 HTML 文件,引入 main.ts。定义 Vue 实例挂载的 DOM 元素。
- main.ts:页面的入口文件,由 index.html 引入。实例化 Vue 并将其挂载到 index.html DOM 中。
- App.vue:主组件文件,通常作为其他组件的父组件。
因为每一个页面都相当于一个 Vue 项目,所以又分别可以引入 Router、Vuex 等,这样它们又有自己的路由系统和全局状态管理。如果只是简单的一个页面,没有路由跳转,就不需要 Router 了,App.vue 可以作为页面组件。
打包结果
打包生成的结构如:
打包后的页面地址:/index.html
子页面地址:/pages/signin/index.html
注意
很多文章都说 base 要设置为 '/',但是如果打包文件不在服务器根目录,应该设置为:'./'。这和网上很多关于打包后白屏问题的原因一样,路径不对。
更新 2023年11月15日19:28:46
更新几点做了又忘了,或者值得说明的:
- 在 Vite 文档的开始就说明了在开发期间 Vite 是一个服务器,
index.html是项目的入口文件,默认位于根目录下,而不是在 /src 下。 - Vite 有“根目录”的概念,即服务文件的位置,在配置文件
vite.config.js中可以通过 root 进行配置。 - 我们可以设置根目录,比如:
root: './src/' - 当使用多页面时,文档所说的:
如果你指定了另一个根目录,请记住,在解析输入路径时,
__dirname的值将仍然是 vite.config.js 文件所在的目录。因此,你需要把对应入口文件的root的路径添加到resolve的参数中。
指的是如果指定了根目录,路径也需要相对最外层(vite.config.js 文件所在的目录)
input: {
entry: resolve(__dirname, 'src/index.html'),
signin: resolve(__dirname, 'src/pages/signin/index.html'),
},
区别于:
input: {
main: resolve(__dirname, 'index.html'),
nested: resolve(__dirname, 'nested/index.html'),
},
vite.config.js 是在最外层,找不到 index.html,而应该找 src/index.html
- 这样设置多页面:
input: {
entry: resolve(__dirname, 'src/index.html'),
signin: resolve(__dirname, 'src/pages/signin/index.html'),
},
目录结构:
└── src
└── pages
└── signin
├── App.vue
├── index.html
└── main.ts
打包出来的路径:build/pages/signin/index.html
访问地址:/pages/signin/index.html
如果想要直接访问地址怎么设置?/invite/index.html
input: {
entry: resolve(__dirname, 'src/index.html'),
signin: resolve(__dirname, 'src/signin.html'),
},
目录结构:
└── src
└── pages
└── signin
├── App.vue
└── main.ts
├── index.html
├── signin.html
├── App.vue
├── main.ts
├── style.css
这样就可以直接访问:/invite.html 打包出来的路径:build/invite.html
这样地址中就不会带上 pages 这样的路径。缺点是所有的页面都要放在 /src/ 下,比较分散,好在 index.html 都是入口文件而已,几乎没有内容。
- 所以 Vite 的多页面设置还是很灵活的,除了上面说的每个页面都是一个 Vue 实例,有自己的路由等等,而且每一个页面又可以多页面,比如 /pages/signin/ 下面不只有 index.html,还可以有其他页面。总之是很自由,可以结合具体项目改造。
更新 2023年11月24日16:28:09 关于根目录关于配置
最近在搞一个奇葩的小问题,APP 调用系统自带的分享功能(反正我不知道是什么,又看不到代码),分享链接。然后分享时,iOS 上会显示连接的预览:图标、标题、简介。安卓上没有那部分。
标题应该就是 HTML 的 title,描述显示的是主域名,图标显示了一个指南针的 icon,类似 iOS 浏览器那个吧。问题是产品要求这个图标要显示业务的图,而且确定可以做到。
问了 APP,确定不是他们要做的,问了之前的开发,也说不知道怎么处理。我的直觉告诉我应该是网页 favicon 相关的东西。favicon 这玩意真的是 10 年都不弄它了。搜了一下怎么添加,用 png, 去转换 ico 图,怎么都不能在浏览器 Tab 上显示出来,如果这个都做不到,也不用去 APP 分享试了。后来新建了 Vite 的项目,用它的 svg,也显示不出来,这就奇怪了。
反复看官网中的静态资源处理-public 目录:
目录默认是
<root>/public,但可以通过publicDir选项 来配置。
该值可以是文件系统的绝对路径,也可以是相对于项目根目录的相对路径。
项目根目录(
index.html文件所在的位置)。可以是一个绝对路径,或者一个相对于该配置文件本身的相对路径。
注意 Vite 同时会解析项目根目录下的 配置文件(即
vite.config.js),因此如果根目录被改变了,你需要将配置文件移动到新的根目录下。
突然想到我的多页面配置,更改了根目录,root: './src/', base: './',。试着将 /public 移动到 /src/public,然后 favicon 就显示出来了。
但是我一直对 因此如果根目录被改变了,你需要将配置文件移动到新的根目录下 不能理解,因为目前我的配置文件仍然在最外层而不是设置的根目录 ./src/ 下。
然后顺利的,favicon 被打包进根目录之后,就能在 APP 分享预览中显示了~
另外分享个小知识,favicon 并不需要 link 写在页面中,只要网站根目录有,就能读取到。
更新 2024年5月17日18:08:25 无法读取环境变量
Vite 中应用环境变量的步骤:
.env.developement:
VITE_API_BASE_URL=http://localhost:8000
在代码中读取:import.meta.env.VITE_API_BASE_URL
就这么简单,可是却是 undefined。看文档看文章都只是这样而已啊,实在看不出来问题。
打印:import.meta.env,正常的默认字段,没有新设置的变量
由于项目是 Vite 多页面应用,怀疑是多页面相关的问题。
最后又回到了 root 根目录的问题上,由于我已经设置 root: './src/', 所以将环境文件放到 src 下就好了。
.env 文件: 文档第一句话:
它默认是 root,既然 root 已经改了,所以 envDir 也改变了。
环境目录也是可以设置的:
envDir: resolve(__dirname),
这样环境文件就可以放到 vite.config.ts 同层级。