本讲是M1里程碑的第一块砖。跑完你会看到浏览器里出现「Hello ShopX」热更新生效目录结构清楚。这是后续前端学习的地基。建议先点赞 收藏 关注配环境时随时回查。一、为什么用Vite而不是Vue CLI很多 Vue 教程还在教vue-cli init那是2018年的工具。Vite是2026年的标准选择原因有四个。1. 启动速度Vue CLI用webpack打包第一次启动要30-60秒依赖越多越慢。Vite用esbuild预构建依赖冷启动稳定在1秒以内无论项目多大。2. HMR速度改一行代码浏览器毫秒级看到变化。Vue CLI的HMR改大文件要3-5秒Vite是50ms量级——慢的HMR让人失去即改即看的节奏。3. 官方推荐Vue团队已正式公告Vue CLI进入维护模式不再新增大功能。Vite是官方推荐的下一代工具。4. 生态更广Vite同时支持Vue3 / React / Svelte / Solid / Vanilla JS。一个项目里要混合技术栈也方便。 唯一注意点Vite对Node版本有要求。我们装的是Node22完全满足。二、创建工程进入项目目录沿用第 3 讲的特性分支cd~/workspace/shopxgitswitch developgitpullgitswitch-cfeature/lecture-004-frontend-scaffold在项目根目录用 pnpm 创建前端工程pnpmcreate vite frontend--templatevue-ts--template vue-ts是关键指定Vue 3 TypeScript模板。frontend是目录名本专栏用monorepo布局前端代码都放这里。命令会问几个交互问题按回车确认默认即可。几秒后目录frontend/出现。进入并安装依赖cdfrontendpnpminstallpnpm install会按package.json装齐所有依赖。装完后目录里有node_modules/、pnpm-lock.yaml。启动 dev serverpnpmdev终端输出VITE v7.x.x ready in xxx ms ➜ Local: http://127.0.0.1:5173/ ➜ press h enter to show help打开浏览器访问http://127.0.0.1:5173/看到 Vite Vue 3的欢迎页。✅ 你的前端工程跑起来了。这是M1里程碑的第一块砖。三、目录约定Vite 默认生成一个最小可运行结构但本专栏会做扩展。完整目录约定如下frontend/ ├── public/ # 静态资源不进打包原样输出 ├── src/ │ ├── api/ # 接口请求层 │ ├── assets/ # 资源图片、字体、SVG │ ├── components/ # 公共组件 │ │ └── HelloShopX.vue # 第一个组件 │ ├── composables/ # 组合式函数useXxx │ ├── layouts/ # 布局组件 │ ├── router/ # 路由 │ ├── stores/ # Pinia stores │ ├── styles/ # 全局样式 │ │ ├── reset.css # 浏览器样式重置 │ │ └── variables.css # CSS 变量颜色、间距 │ ├── types/ # TS 类型定义 │ │ └── goods.ts # 商品类型 │ ├── utils/ # 工具函数 │ │ └── format.ts # 格式化函数 │ ├── views/ # 页面组件 │ │ └── HomeView.vue │ ├── App.vue # 根组件 │ ├── main.ts # 入口文件 │ └── env.d.ts # Vite环境变量类型 ├── eslint.config.js # ESLint配置ESLint9 flat config ├── .prettierrc.json # Prettier配置 ├── index.html # HTML 入口 ├── package.json ├── pnpm-lock.yaml ├── tsconfig.json ├── tsconfig.app.json ├── tsconfig.node.json ├── vite.config.ts └── README.md几个目录的提前说明api/讲Axios统一封装时建——目前空着composables/讲组合式API时建router/讲Vue Router时建stores/讲Pinia时建layouts/讲Element Plus布局时建现在只建components/views/assets/这三个其他目录等讲到时再建。命令一次性建好空目录mkdir-psrc/{api,assets,components,composables,layouts,router,stores,styles,types,utils,views}touchsrc/{api,composables,layouts,router,stores,types,utils}/.gitkeep.gitkeep是空目录占位文件——Git不跟踪空目录但有了这个文件目录就跟着仓库走。四、script setup语法糖Vite创建的App.vue默认就是script setup写法。这是Vue 3推荐的写法比Options API简洁50%以上。一个最小示例script setup langts import { ref, computed } from vue const count ref(0) const double computed(() count.value * 2) function increment() { count.value } /script template div classcounter pcount is {{ count }}/p pdouble is {{ double }}/p button clickincrementclick/button /div /template style scoped .counter { padding: 20px; text-align: center; } /style三件你需要知道的事第一langts启用TypeScript。没有它script里写TS代码会报错。第二ref和reactive是响应式API。ref(0)返回一个响应式引用模板里直接{{ count }}就能取到值Vue自动解包脚本里要count.value取值。后面会专门讲响应式原理。第三style scoped限定样式只作用于当前组件。.counter不会泄漏到其他组件的.counter上。这是模块化CSS的基础。与Options API对比老式Vue 2写法script export default { data() { return { count: 0 } }, computed: { double() { return this.count * 2 } }, methods: { increment() { this.count } } } /script新写法同等功能script setup import { ref, computed } from vue const count ref(0) const double computed(() count.value * 2) function increment() { count.value } /scriptref/computed移到顶部、变量直接定义、方法直接写函数——样板代码减少一半。五、TypeScript配置要点Vite三文件结构最新版的Vite的vue-ts将 TypeScript 配置拆分为三个文件这是 TypeScript 项目引用Project References 功能的体现。Vite 团队采用这种结构主要是为了将前端代码运行在浏览器中和 Vite 配置文件运行在 Node.js 中的 TypeScript 配置分离实现更清晰、更精确的类型检查。三个文件的分工文件作用负责范围tsconfig.json根配置通过references引用另外两个文件项目管理入口tsconfig.app.json你需要重点修改的文件src/下所有应用代码tsconfig.node.json构建工具配置vite.config.ts等 Node 环境文件tsconfig.json默认内容{files:[],references:[{path:./tsconfig.node.json},{path:./tsconfig.app.json}]}tsconfig.app.json核心修改文件{compilerOptions:{tsBuildInfoFile:./node_modules/.tmp/tsconfig.app.tsbuildinfo,target:ES2022,useDefineForClassFields:true,module:ESNext,lib:[ES2022,DOM,DOM.Iterable],skipLibCheck:true,/* Bundler mode */moduleResolution:Bundler,allowImportingTsExtensions:true,isolatedModules:true,moduleDetection:force,noEmit:true,jsx:preserve,/* Linting */strict:true,noUnusedLocals:true,noUnusedParameters:true,noFallthroughCasesInSwitch:true,paths:{/*:[./src/*]}},include:[src/**/*.ts,src/**/*.tsx,src/**/*.vue]}几个关键项解释strict: true—— 启用所有严格类型检查。这是 TS 最大的价值所在不要关noUnusedLocals/noUnusedParameters—— 没用到的变量/参数直接报错养成干净习惯paths: { /*: [./src/*] }—— 路径别名需要同时在tsconfig.json根文件和tsconfig.app.json中配置见第六节moduleResolution: Bundler—— Vite 推荐的解析模式比Node更适合打包工具noEmit: true—— 只做类型检查不输出编译产物实际打包交给 ViteisolatedModules: true—— 强制每个文件都能独立编译Vite esbuild 需要tsconfig.node.json保持默认即可tsconfig.node.json专门用于vite.config.ts的编译规则模板默认生成的内容已经可用一般不需要修改{compilerOptions:{tsBuildInfoFile:./node_modules/.tmp/tsconfig.node.tsbuildinfo,target:ES2023,lib:[ES2023],module:ESNext,skipLibCheck:true,moduleResolution:Bundler,allowImportingTsExtensions:true,isolatedModules:true,moduleDetection:force,noEmit:true,strict:true,types:[node]},include:[vite.config.ts]}这个文件告诉TS「编译vite.config.ts时把types设为[node]而不是[vite/client]」。env.d.ts声明Vite全局类型/// reference typesvite/client /interfaceImportMetaEnv{readonlyVITE_API_BASE_URL:string}interfaceImportMeta{readonlyenv:ImportMetaEnv}VITE_前缀的环境变量才能被客户端代码访问import.meta.env.VITE_API_BASE_URL。六、路径别名写import Hello from /components/Hello.vue比写import Hello from ../../components/Hello.vue优雅太多。配置分两步两个文件必须同时改缺一个TS会红。步骤 1Vite 配置编辑vite.config.tsimport{defineConfig}fromviteimportvuefromvitejs/plugin-vueimport{fileURLToPath,URL}fromnode:urlexportdefaultdefineConfig({plugins:[vue()],resolve:{alias:{:fileURLToPath(newURL(./src,import.meta.url)),},},server:{port:5173,host:127.0.0.1,proxy:{/api:{target:http://127.0.0.1:8000,changeOrigin:true,},},},})步骤 2TS 配置tsconfig.json中添加compilerOptions{files:[],references:[{path:./tsconfig.app.json},{path:./tsconfig.node.json}],compilerOptions:{paths:{/*:[./src/*]}}}验证别名生效!-- src/views/HomeView.vue -- script setup langts import HelloShopX from /components/HelloShopX.vue /script template HelloShopX / /template如果两个文件都改对了HelloShopX组件能正常引入TS 不会报错。几个常见疑问为什么三处都要配Vite需要vite.config.ts的alias来做实际解析tsconfig.json根文件让IDE识别路径tsconfig.app.json让vue-tsc类型检查通过。缺任何一处都可能出现“编辑器不报错但构建失败”或反之的情况。为什么fileURLToPath(new URL(./src, import.meta.url))因为Vite是ESM写法普通字符串路径在ESM下会报错。fileURLToPath把 URL 转成绝对路径。VSCode不识别重启TS服务CtrlShiftP→ “TypeScript: Restart TS Server”。七、devServer.proxy 代理后面会让后端跑在http://127.0.0.1:8000前端在5173。浏览器有同源策略前端直接fetch 8000端口会被CORS拦截。通过Vite代理前端代码写/api/xxx时Vite在开发服务器里反向代理到后端绕过浏览器同源检查。server:{proxy:{/api:{target:http://127.0.0.1:8000,changeOrigin:true,},},}怎么用前端代码constresawaitfetch(/api/v1/health/)constdataawaitres.json()浏览器看到的是5173 → 5173没跨域问题。Vite在内部把请求转发到8000用户完全无感。完整CORS原理浏览器只在生产环境真正需要CORS头。后面会配django-cors-headers也会讲清整个CORS流程简单请求、预检请求、Cookie携带、自定义头。八、ESLint Prettier 落地Linter和Formatter是工程规范的左膀右臂。Linter抓代码错误Formatter保代码风格。本讲不展开讲它们的规则只把它们配好。⚠️2026 年重要变化ESLint9已全面转向flat configeslint.config.js旧的.eslintrc.cjs写法已不推荐。本讲按新写法配置。安装pnpmadd-Deslint eslint/js typescript-eslint eslint-plugin-vue\vue-eslint-parser prettier eslint-config-prettiereslint.config.jsimportjsfromeslint/jsimporttseslintfromtypescript-eslintimportpluginVuefromeslint-plugin-vueimportprettierfromeslint-config-prettierexportdefault[js.configs.recommended,...tseslint.configs.recommended,...pluginVue.configs[flat/recommended],prettier,{rules:{vue/multi-word-component-names:off,typescript-eslint/no-unused-vars:[error,{argsIgnorePattern:^_}],},},].prettierrc.json{semi:false,singleQuote:true,trailingComma:all,printWidth:100,tabWidth:2,arrowParens:always}package.json加lint脚本{scripts:{dev:vite,build:vue-tsc -b vite build,preview:vite preview,lint:eslint . --fix,format:prettier --write .}}vue-tsc -b说明-b是build mode它会按照tsconfig.json的references分别对tsconfig.app.json和tsconfig.node.json做类型检查。VSCode 工作区配置新建.vscode/settings.json共享配置可以进git{editor.formatOnSave:true,editor.defaultFormatter:esbenp.prettier-vscode,eslint.validate:[javascript,typescript,vue],editor.codeActionsOnSave:{source.fixAll.eslint:explicit}}装ESLint和Prettier - Code formatter两个VSCode扩展后保存文件时自动格式化 自动修lint错。九、「Hello ShopX」页面把App.vue改成我们要的页面script setup langts const year new Date().getFullYear() /script template div classhello div classbrandShopX/div h1Hello ShopX/h1 p classsubtitle从零到上线 · 全栈电商项目/p p classmuted© {{ year }} · 第 4 讲里程碑/p /div /template style scoped .hello { min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; background: linear-gradient(135deg, #0f1b2d 0%, #1a2a44 100%); color: #ffffff; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, PingFang SC, sans-serif; } .brand { font-size: 18px; letter-spacing: 6px; color: #ffb020; margin-bottom: 24px; } h1 { font-size: 64px; margin: 0 0 16px; font-weight: 500; } .subtitle { font-size: 18px; color: #cbd5e1; margin: 0 0 48px; } .muted { color: #8a93a6; font-size: 14px; } /style保存后浏览器无刷新自动更新HMR验证。✅ 这一刻可以提交了。按第3讲的提交规范本讲至少两个commitcd~/workspace/shopx# 第一个 commit前端工程初始化gitaddfrontend/package.json frontend/pnpm-lock.yaml frontend/index.html\frontend/vite.config.ts frontend/tsconfig.json frontend/tsconfig.node.jsongitcommit-mfeat(frontend): 第 004 讲 初始化 Vite Vue3 TS 工程# 第二个 commitHello ShopX 页面与配置gitaddfrontend/src frontend/eslint.config.js frontend/.prettierrc.json frontend/.vscodegitcommit-mfeat(frontend): 第 004 讲 Hello ShopX 页面与 ESLint/Prettier 配置# 推送特性分支gitpush-uorigin feature/lecture-004-frontend-scaffold十、本讲作业跑通pnpm dev把App.vue改成你自己的「Hello XXX」版本保存看HMR是否生效故意写一个TS错误在script setup里写const x: number abc看pnpm build是否报红在src/components/HelloShopX.vue建一个组件导出count数字prop在App.vue引入并传42建好路径别名写import ./foo→ 改成import /foo任意写个文件测试十一、常见报错速查表报错原因解决pnpm报command not found没装pnpmnpm install -g pnpm或corepack enableVite启动后Cannot find module vue/xxx依赖没装pnpm install/components/Foo.vueTS飘红「Cannot find module」tsconfig.paths没配同步 tsconfig的paths配置HMR不生效编辑的不是Vite监听的文件检查vite.config.server.watch配置保存后看终端日志vue-tsc报类型错误但pnpm dev能跑类型检查只在build阶段写pnpm build一次强制全量检查ESLint报Could not find config file还在用旧的.eslintrc改用eslint.config.jsflat configPrettier和ESLint打架ESLint默认格式化规则与Prettier冲突eslint.config.js里加prettier配置放最后端口5173被占上次pnpm dev没关lsof -ti:5173 | xargs kill -9macOS十二、术语自查报告✅ Vite不是「Vite.js」、不是 Webpack✅ Vue3组合式API不是「Vue3写法」、「新写法」✅script setup语法糖名称准确✅ TypeScript 5.x不是泛指TS✅ HMRHot Module Replacement写全称✅ esbuild是Vite预构建工具不是「Vite用webpack」✅ pnpm与npm区别写清节省磁盘、严格依赖、防幽灵依赖✅style scoped模块化CSS原理✅langts启用TypeScript的位置✅ ESLint 9 flat configeslint.config.js非旧版.eslintrc自查通过。无禁用词。最后前端第一块砖已经砌好如果你跟着跑出了Hello ShopX评论区打卡一句第004讲签到Hello ShopX已跑通点赞让更多正在学前端的看到收藏配ESLint、路径别名时随时回查关注追更不迷路我们第5讲见。