主要场景
有时候需要登录页、推广页等独立页面和业务 SPA 页分离的情况。尤其是在登录页中使用我觉得是不错的方案。
它可以直接和带有 vue-router、vuex、pinia 的 SPA 应用解耦,避免在登录页调用了一些 SPA 页面初始化行为。
原理
原理上其实也很简单,就是通过 Vite 的多入口、多出口来实现产出多个独立的 HTML 文件。
全程实现
创建登录页
就用最新的 vue3 脚手架为例,先创建项目:
shell
npm create vue@latest
然后在根目录创建 login.html
,其实就是复制了一份。不过如果是真实项目中可以把 index.html
中注入的各种 JS 和 CSS 清除掉。
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>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/login.js"></script>
</body>
</html>
然后在 /src
目录下创建登录页的入口文件 login.js
和具体渲染 login.vue
.
js
import { createApp } from "vue";
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
import Login from "./Login.vue";
const app = createApp(Login);
// 去掉 pinia、vue-router 等不需要的库
app.use(ElementPlus);
app.mount("#app");
一个简单的 .vue
文件
html
<template>
<div>
<el-input v-model="username" placeholder="请输入账号"></el-input>
<el-input
v-model="password"
type="password"
placeholder="请输入密码"
></el-input>
<el-button type="primary" @click="login">登录</el-button>
</div>
</template>
<script setup>
import { ref } from "vue";
const username = ref("");
const password = ref("");
function login() {
window.location.href = "/"; // 登录进入 SPA 页面
}
</script>
<style scoped></style>
以上就实现了一个简单的登录页了,其中登录和登出就靠着 window.location.href
来实现
js
function login() {
window.location.href = "/";
}
function logout() {
window.location.href = "/login.html";
}
另外,其实也可以在进入登录页的时候清空域名下的用户信息、实现真正的前后端登出。
js
// login.vue
onMounted(() => {
apiLogout()
})
Vite 配置
以上就实现了独立登录页功能,但是在执行 yarn build
的时候发现打包并没有把 login.html
包含进去。所以需要修改下 vite 的配置。
vite 的配置是基于 rollup 的,所以除了 vite 官网外,也可以参考 rollup 打包相关的配置。
js
// vite.config.js
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import { resolve } from 'node:path'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
vueJsx(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
build: {
rollupOptions: {
input: {
index: resolve(__dirname, './index.html'),
login: resolve(__dirname, './login.html'),
},
},
},
})
在加上了 build.rollupOptions.input
后再执行 yarn build
就可以在 dist
目录下看到 login.html
了。
login.html 路径的隐藏
这个可以让代理服务器的同学加个 Nginx 代理。
bash
server
{
listen 80;
...
location /login {
proxy_pass http://localhost:7001/login.html;
}
}
如此就可以通过 https://domain.com/login
来访问登录页啦~
最后
其实原理并不难,记录下此文主要是提供一种思路。面对一些独立性较强的页面的时候不用拘泥于 SPA 中的路由功能,是可以利用 vite 或者 webpack 做多页应用的。
另外,我也遇到过一开始是接入的公司公共 SSO 页,后面要自行开发登录页的情况。也适合用这种多页应用的模式。