从零构建企业级 Node.js + TypeScript 项目骨架:工程化最佳实践全解析

《从零构建企业级 Node.js + TypeScript 项目骨架:工程化最佳实践全解析》

在这里插入图片描述
收到你的反馈,我们来写一篇真正具备深度、结构清晰、代码严谨、适合 CSDN 发布并吸引收藏点赞的高质量技术文章。这篇文章我们选择一个非常实用且受关注度高的方向:


Vue3 + Vite 企业级项目架构设计详解(组件封装、状态管理、权限控制实战)

一、前言

Vue3 发布以来,配合 Vite 构建的开发体验已经彻底改变了前端工程模式。尤其在中大型企业项目中,如何构建一个可维护、可扩展、高性能的前端架构,成了前端开发工程化的关键挑战。

本文将基于实际企业项目经验,从以下几个核心方面讲解一套完整的 Vue3 项目架构设计:

  • 项目结构分层与模块化策略
  • 全局状态管理(Pinia)设计模式
  • 通用组件的抽象与封装
  • 权限控制逻辑的统一实现
  • 环境变量与多环境构建管理
  • 项目自动化配置优化(alias、自动引入等)

文章不仅有代码,还有思想和规范设计逻辑,适合希望构建企业级 Vue3 项目的开发者参考实践。


二、项目结构设计

目录结构

src/
├── api/                  # 所有 API 请求封装
├── assets/               # 静态资源
├── components/           # 通用组件
├── directives/           # 自定义指令
├── hooks/                # 通用逻辑 Hooks
├── layouts/              # 页面布局
├── pages/                # 路由页面
├── router/               # 路由配置
├── store/                # 状态管理
├── utils/                # 工具函数
├── views/                # 页面视图
├── permission.ts         # 权限控制
├── main.ts               # 入口文件
└── App.vue

这种分层结构保证了项目逻辑清晰,易于维护。


三、状态管理:模块化 + 持久化(Pinia)

安装:

npm install pinia

初始化:

// main.ts
import { createPinia } from 'pinia';

const app = createApp(App);
app.use(createPinia());

示例模块:用户模块(store/modules/user.ts)

import { defineStore } from 'pinia';

export const useUserStore = defineStore('user', {
  state: () => ({
    token: '',
    userInfo: null,
  }),
  actions: {
    setToken(token: string) {
      this.token = token;
      localStorage.setItem('token', token);
    },
    async fetchUserInfo() {
      const res = await getUserInfo();
      this.userInfo = res.data;
    },
  },
});

支持持久化,可以用插件如 pinia-plugin-persistedstate 自动持久化。


四、权限控制设计

我们采用路由守卫 + 权限白名单控制 + 动态路由注册的组合方式。

// permission.ts
import router from './router';
import { useUserStore } from '@/store/modules/user';

const whiteList = ['/login'];

router.beforeEach(async (to, from, next) => {
  const userStore = useUserStore();

  if (userStore.token) {
    if (to.path === '/login') next('/');
    else {
      if (!userStore.userInfo) {
        await userStore.fetchUserInfo();
        // 动态添加权限路由
      }
      next();
    }
  } else {
    whiteList.includes(to.path) ? next() : next('/login');
  }
});

五、通用组件封装:表格 + 弹窗 + 分页器

表格组件(components/BaseTable.vue)

<template>
  <el-table :data="data" v-bind="$attrs">
    <slot />
  </el-table>
</template>

<script setup lang="ts">
defineProps<{ data: any[] }>();
</script>

优势

  • 支持 v-bind 所有 table 属性
  • 支持插槽扩展自定义列

封装这些基础组件可以大大减少冗余代码,提升开发效率。


六、统一 API 管理:Axios 封装

// api/http.ts
import axios from 'axios';

const service = axios.create({
  baseURL: import.meta.env.VITE_API_URL,
  timeout: 10000,
});

service.interceptors.request.use(config => {
  const token = localStorage.getItem('token');
  if (token) config.headers.Authorization = `Bearer ${token}`;
  return config;
});

export default service;

接口模块封装:

// api/user.ts
import request from './http';

export function getUserInfo() {
  return request.get('/user/info');
}

七、自动引入优化(unplugin-auto-import)

安装:

npm install unplugin-auto-import -D

vite.config.ts 配置:

import AutoImport from 'unplugin-auto-import/vite';

AutoImport({
  imports: ['vue', 'vue-router', 'pinia'],
  dts: 'src/auto-imports.d.ts',
}),

可实现自动引入 refcomputed 等,无需重复 import。


八、环境变量与多环境配置

使用 .env 文件:

.env.development
.env.production
.env.staging

示例:

VITE_API_URL=https://dev.api.com

在代码中读取:

console.log(import.meta.env.VITE_API_URL);

九、动态菜单渲染与权限菜单生成

企业项目中,菜单往往来自服务端,需结合权限动态渲染。

1. 接口响应结构示例

[
  {
    "name": "Dashboard",
    "path": "/dashboard",
    "component": "Layout",
    "children": [
      {
        "name": "Overview",
        "path": "overview",
        "component": "dashboard/Overview",
        "meta": { "title": "概览", "icon": "Home", "roles": ["admin", "user"] }
      }
    ]
  }
]

2. 后端菜单转路由方法

// utils/permission.ts
export function transformMenuToRoute(menuList) {
  return menuList.map(item => {
    const route = {
      path: item.path,
      name: item.name,
      component: () => import(`@/views/${item.component}.vue`),
      meta: item.meta || {},
      children: item.children ? transformMenuToRoute(item.children) : []
    };
    return route;
  });
}

3. 路由动态添加

// permission.ts
const dynamicRoutes = transformMenuToRoute(serverMenuList);
dynamicRoutes.forEach(route => router.addRoute(route));

十、前端权限控制:按钮级别权限处理

针对按钮/模块的权限可以通过自定义指令控制显示:

// directives/permission.ts
import { useUserStore } from '@/store/modules/user';

export default {
  mounted(el, binding) {
    const { userInfo } = useUserStore();
    const hasPermission = userInfo?.permissions.includes(binding.value);
    if (!hasPermission) el.parentNode?.removeChild(el);
  }
};

使用:

<el-button v-permission="'user:add'">新增用户</el-button>

十一、Element Plus 主题定制与暗黑模式

企业 UI 通常要求品牌色、夜间模式支持。

1. 安装插件

npm install element-plus --save

vite.config.ts 中配置按需引入:

import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';

AutoImport({
  resolvers: [ElementPlusResolver()],
}),
Components({
  resolvers: [ElementPlusResolver()],
}),

2. 暗黑模式配置

/* main.css */
html.dark {
  --el-color-primary: #409eff;
  background-color: #1f1f1f;
}

通过切换类名 html.dark 可启用暗黑风:

document.documentElement.classList.add('dark');

十二、项目部署优化建议

  • 使用 Vite 的 base 配置支持部署路径:
    // vite.config.ts
    base: '/admin/',
    
  • 利用 Nginx 实现前端静态资源缓存与 gzip 压缩
  • 打包分析工具:
    npm run build --report
    
  • 使用 vite-plugin-compression 实现打包压缩
  • 接入 Sentry、阿里云前端监控 SDK 进行上线监控

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

全栈探索者chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值