手工搭建前端vite项目

初始化项目

mkdir front-end
cd front-end
pnpm init

安装Vite

pnpm install --save-dev vite
# @vitejs/plugin-vue,Vite看懂 .vue文件
pnpm add -D @vitejs/plugin-vue

创建index.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>front-end</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

创建CSS文件:src/assets/base.css、src/assets/main.css(暂时为空)

/* ==============================
   1. 全局样式重置(最核心)
============================== */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box; /* 让宽高计算更合理 */
}

/* ==============================
   2. HTML & Body 基础设置
============================== */
html,
body {
  height: 100%;
  font-family: "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
  font-size: 14px;
  color: #333;
  background-color: #fff;
  -webkit-font-smoothing: antialiased; /* 字体平滑 */
}

/* ==============================
   3. 列表样式清除
============================== */
ul,
ol {
  list-style: none;
}

/* ==============================
   4. 链接样式
============================== */
a {
  text-decoration: none;
  color: inherit;
}

a:hover {
  text-decoration: none;
}

/* ==============================
   5. 图片默认样式
============================== */
img {
  max-width: 100%;
  vertical-align: middle;
  border: none;
}

/* ==============================
   6. 表单元素统一
============================== */
input,
button,
textarea,
select {
  font-family: inherit;
  outline: none;
  border: none;
}

button {
  cursor: pointer;
  background: none;
}

/* ==============================
   7. 清除浮动(常用工具类)
============================== */
.clearfix::after {
  content: "";
  display: block;
  clear: both;
  visibility: hidden;
  height: 0;
}

/* ==============================
   8. 通用布局类(可选)
============================== */
.container {
  width: 1200px;
  margin: 0 auto;
}

.flex {
  display: flex;
}

.flex-center {
  display: flex;
  align-items: center;
  justify-content: center;
}
@import "./base.css";

创建入口文件:‌src/main.js

import './assets/css/main.css'

document.querySelector("body").innerHTML="<h1>hello world~</h1>"

Vite核心配置文件:vite.config.js

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'

export default defineConfig({
  // Vite插件数组:  Vue支持
  plugins: [vue()],
  // 开发服务器配置
  server: {
    open: true,       // ✅ 启动自动打开浏览器
    port: 5173,       // 自定义端口
    host: '0.0.0.0'   // 局域网手机可访问
  },
  resolve: {
    alias: {
      // @ 直接等价 src文件夹
      '@': path.resolve(__dirname, './src')
    }
  }
})

修改package的scripts

"scripts": {
  "dev": "vite --open",
  "build": "vite build",
  "preview": "vite preview --open"
},

启动:pnpm dev

搭建vite+vue+element-plus

安装vue+element-plus:

pnpm add vue
# UI组件库本体
pnpm add element-plus
# 可选:图标库
pnpm add @element-plus/icons-vue

Vue根组件src/App.vue

<template>
  <div>
    <el-button type="primary">主按钮</el-button>
    <el-input placeholder="请输入" v-model="val"></el-input>
    <Search /> <!--图标组件-->
  </div>
</template>
<script setup>
let val = ''
</script>

创建文件修改:‌src/main.js

import { createApp } from 'vue'
import App from './App.vue'
// 引入ElementPlus和全局样式
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
// 图标全局挂载(可选)
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import './assets/css/main.css'

const app = createApp(App)
// 全局注册ElementPlus
app.use(ElementPlus)
// 全局注册图标
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component)
}
app.mount('#app')

启动:pnpm dev

搭建Vite + Vue3 + TypeScript + Element Plus

初始化项目

mkdir vite-vue-ts
cd vite-vue-ts
pnpm init

安装Vite + TypeScript + Vue

pnpm add -D vite @vitejs/plugin-vue
pnpm add -D typescript vue-tsc @types/node
pnpm add vue
pnpm add element-plus
pnpm add @element-plus/icons-vue

Vite核心配置文件vite.config.ts

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'

export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src')
    }
  },
  server: {
    open: true,
    port: 3000,
    host: true
  }
})

TypeScript核心配置文件:tsconfig.json

{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "lib": ["ESNext", "DOM", "DOM.Iterable"],
    "moduleResolution": "bundler",
    "skipLibCheck": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "paths": {
      "@/*": ["./src/*"] // 加了 ./ 变成相对路径
    },
    "types": ["vite/client"]
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

Node.js环境的TypeScript配置文件:tsconfig.node.json

{
  "compilerOptions": {
    "composite": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "allowSyntheticDefaultImports": true
  },
  "include": ["vite.config.ts"]
}

TypeScript类型声明文件:src/env.d.ts(在开发阶段为TypeScript提供类型智能提示和类型检查)

declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}

Vue根组件:src/App.vue

<template>
  <div>
    <el-button type="primary">Hello Vue3 + TS + Element Plus {{ msg }}</el-button>
  </div>
</template>

<script setup lang="ts">
const msg: string = 'Vue3 + TS'
</script>

 入口文件:‌src/main.ts

import { createApp } from 'vue'
import App from './App.vue'

// 样式顺序:base → UI → main
import './assets/css/base.css'
import 'element-plus/dist/index.css'
import './assets/css/main.css'

import ElementPlus from 'element-plus'

const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')

创建index.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>vite-vue-ts</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

修改package.json脚本

"scripts": {
  "dev": "vite",
  "build": "vue-tsc --noEmit && vite build",
  "preview": "vite preview"
}

启动项目: pnpm dev

编译项目:pnpm build

集成ESLint 10

安装 ESLint 10 + Flat依赖: pnpm add -D eslint@10 vite-plugin-eslint eslint-plugin-vue typescript-eslint globals

ESLint10配置文件:eslint.config.js(与旧版本配置文件不同)

import globals from 'globals'
import vue from 'eslint-plugin-vue'
import tseslint from 'typescript-eslint'

export default tseslint.config(
  // 忽略 node_modules 和 dist 文件夹
  { ignores: ['node_modules/', 'dist/'] },

  // TS 推荐规则
  ...tseslint.configs.recommended,

  // Vue3 推荐规则 + 解析器配置
  ...vue.configs['flat/recommended'],
  {
    files: ['**/*.vue'],
    languageOptions: {
      parserOptions: {
        parser: tseslint.parser,
        ecmaVersion: 'latest',
        sourceType: 'module'
      }
    }
  },

  // 全局环境配置
  {
    languageOptions: {
      globals: {
        ...globals.browser,
        ...globals.es2021,
        ...globals.node
      }
    }
  },

  // 宽松规则配置
  {
    rules: {
      'vue/multi-word-component-names': 'off',
      '@typescript-eslint/no-unused-vars': 'warn',
      '@typescript-eslint/no-unused-expressions': 'warn',
      '@typescript-eslint/no-explicit-any': 'off',
      '@typescript-eslint/no-empty-object-type': 'off',
      'no-console': 'off'
    }
  }
)

Vite配置文件:vite.config.ts

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import eslintPlugin from 'vite-plugin-eslint'

export default defineConfig({
  plugins: [
    vue(),  
    // eslintPlugin({
    //   // 适配 ESLint 10 flat config
    //   useEslintrc: false,
    //   configType: 'flat'
    // })
    eslintPlugin()
  ],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src')
    }
  },
  server: {
    open: true,
    port: 3000,
    host: true
  }
})

修改package.json脚本

"lint": "eslint .",
"lint:fix": "eslint . --fix"

[lint = eslint . ]  扫描所有文件,列出错误 / 警告,不修改代码。
[lint:fix = eslint . --fix]  扫描 → 自动修复可修复问题 → 把改完的内容写回文件 → 剩下修不了的再打印出来ESLint。

更多推荐