Vue3 多页面实现

MuYan2024-03-16VueVue
├── env
|   ├── .env
|   └── .env.[name]
├── package.json
├── package.json
├── vite.config.js
└── src
    ├── router
    ├── views
    ├── views
    └── pages
        ├── index.html
        ├── App.html
        ├── main.ts
        └── page1
            ├── router
            ├── views
            ├── index.html
            ├── App.html
            └── main.ts
  • 以上结构将 主页面 跟其他 子页面 统一至 src/pages 文件下进行归类,主页面开发主要在 src 根目录下开发,子页面主要在 src/pages/[name] 下开发。

  • 公共的组件、方法就放置于 src 文件夹下(如 assetsutils 等),子页面的就放置对应子页面 src/pages/[name] 文件夹下,这样的归类可以减少多人开发的文件变更记录,让文件归属更加清晰

实现代码如下

  • vite.config 文件配置
// vite.config.ts
import { UserConfig, defineConfig } from "vite";
import { resolve } from "path";
import vue from "@vitejs/plugin-vue";
import { getInput } from "./build/rollup-options";

// https://vitejs.dev/config/
export default defineConfig((): UserConfig => {
  // 项目根目录(index.html 文件所在的位置)变更
  const rootPage = resolve(__dirname, "./src/pages/");
  // 打包后文件指定输出路径(相对于 项目根目录)变更
  const outDirDist = resolve(__dirname, "./dist");
  const input = getInput();
  return {
    root: rootPage,
    // 变更 .env 文件的目录
    envDir: resolve(__dirname, "./env"),
    plugins: [vue()],
    build: {
      outDir: outDirDist, // 输出路径
      assetsDir: "static", // 静态文件目录
      // 默认情况下 若 outDir 在 root 目录下, 则 Vite 会在构建时清空该目录。
      emptyOutDir: true,
      rollupOptions: {
        input,
        output: {
          // 更改静态文件 目录+文件名
          chunkFileNames: "static/js/[name]-[hash].js",
          entryFileNames: "static/js/[name]-[hash].js",
          assetFileNames: "static/[ext]/[name]-[hash].[ext]",
        },
      },
    },
    // 打包移除log、debug
    esbuild: {
      drop:
        process.env.NODE_ENV === "development" ? [] : ["console", "debugger"],
    },
    server: {
      host: "0.0.0.0",
      port: 8080,
      // 项目启动后,自动打开
      open: true,
      proxy: {
        "/api": {
          target: "http://127.0.0.1",
          changeOrigin: true,
          rewrite: (path: any) => path.replace(/^\/api/, ""),
        },
      },
    },
  };
});
  • rollup-options.ts 文件配置如下
import fs from "fs";
import { resolve, join, extname } from "path";

// 获取项目根目录
const ROOT_PATH = resolve(__dirname, "..");
// 获取项目页面文件夹
const PAGE_PATH = join(ROOT_PATH, "/src/pages");

type FileInfo = {
  fullPath: string,
  fileInfo: fs.Stats,
  file: string,
};

const readDirectory = (
  filePath: string,
  excludeFiles: string[] = []
): FileInfo[] => {
  const files: FileInfo[] = [];
  try {
    const items = fs.readdirSync(filePath);
    for (const item of items) {
      if (!excludeFiles.includes(item)) {
        const fullPath = resolve(filePath, item);
        const fileInfo = fs.statSync(fullPath);
        files.push({ fullPath, fileInfo, file: item });
      }
    }
  } catch (error) {
    console.error(`读取目录出错: ${filePath}`, error);
  }
  return files;
};

interface inputInfo {
  [key: string]: string;
}

const getInput = (): inputInfo => {
  const input: inputInfo = {
    index: resolve(PAGE_PATH, "index.html"),
  };

  const files = readDirectory(PAGE_PATH);

  for (const { fullPath, fileInfo, file } of files) {
    if (fileInfo.isDirectory()) {
      const innerFiles = readDirectory(fullPath);
      const htmlFile = innerFiles.find(({ file }) => extname(file) === ".html");
      if (htmlFile) {
        input[file] = htmlFile.fullPath;
      }
    }
  }

  // 子页面打包时,获取子页面的页面 name,该 name 需要与实际子页面文件夹 name 一致,如无子页面单独打包需求可以去除该代码,保留也无影响
  const pageIndex = process.argv.findIndex((item) => item === "--page");
  if (pageIndex !== -1) {
    const pageName = process.argv[pageIndex + 1] || undefined;
    if (pageName && input[pageName]) {
      return {
        [pageName]: input[pageName],
      };
    }
  }
  return input;
};

export { getInput };

子页面的一些配置

子页面单独启动

  • 配置下 package.json 文件即可
// package.json
{
  "scripts": {
    "dev": "vite",
    "dev:page1": "vite serve src/pages/page1/ --config ./vite.config.ts"
  }
}

子页面单独打包

  • 打包命令配置
// package.json
{
  "scripts": {
    "build:page1": "vue-tsc && vite build -- --page page1"
  }
}

多页面全局 css 变量引入

  • 这里以引入 scss 变量文件为例,例如我要引入 src/styles/variables.scss 这个 scss 变量文件
export default defineConfig({
  resolve: {
    // 配置下文件系统路径的别名,如果使用了ts 还需要进行 tsconfig.json 文件的配置
    alias: {
      "@": `${resolve(__dirname, "src")}`,
    },
  },
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `@use "@/styles/variables.scss" as *;`,
      },
    },
  },
});
  • tsconfig.json 文件的别名配置
// tsconfig.json
{
  "compilerOptions": {
    "paths": {
      "@/*": ["src/*"]
    }
  }
}

子页面共享全局 stores 配置

  • 默认已进行stores配置,而后在子项目的 mian.ts 配置如下参数
import { createApp } from "vue";
import App from "./App.vue";
import pinia from "@/stores";

const app = createApp(App);
app.use(pinia);
上次更新 2026/6/23 11:49:15
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.8