从零搭建Vue3项目:深入理解前端工程化与脚手架底层原理
1. 从“零”开始为什么我们要绕开脚手架最近在面试和带新人的过程中我发现一个挺有意思的现象很多简历上写着“精通Vue3”的朋友当被问到“如果不使用create-vue或Vite模板你如何从零初始化一个Vue3项目”时往往会卡壳。他们的第一反应是“啊现在不都用脚手架吗自己搭多麻烦。”这恰恰点出了当前前端学习的一个普遍误区——对工具的过度依赖导致对底层构建逻辑的认知模糊。脚手架如create-vue、Vite无疑极大地提升了开发效率它像一份精心搭配好的“预制菜”开箱即用。但长期只吃“预制菜”你可能会失去挑选食材、掌握火候、甚至设计菜谱的能力。所以这次我们不依赖任何现成的项目框架或脚手架就用最原始的npm init从一个空文件夹开始一步步搭建一个“过得去”的Vue3前端项目。这个“过得去”的标准是具备现代前端开发的核心要素模块化、热更新、类型检查、代码规范、构建优化结构清晰便于后续维护和扩展。这不仅仅是一个搭建教程更是一次对前端工程化核心链条的深度梳理。你会彻底明白那些被脚手架隐藏起来的配置究竟在为什么服务。2. 项目初始化与最简依赖引入我们的起点是一个绝对空白的目录。打开终端执行以下命令mkdir vue3-from-scratch cd vue3-from-scratch npm init -y这会生成一个最基础的package.json文件。现在我们需要思考一个Vue3应用最核心的依赖是什么答案是vue本身。所以我们首先安装Vue3npm install vuenext注意这里我们特意使用next来确保安装的是Vue3的最新稳定版。安装后你的package.json的dependencies中会出现vue: ^3.x.x。只有Vue库是不够的。Vue3的模板如template中的内容需要被转换成浏览器能理解的渲染函数。在Vue生态中负责这项工作的核心工具是vue/compiler-sfc(Single File Component compiler)。它专门用于编译.vue单文件组件。因此我们需要将其安装为开发依赖npm install vue/compiler-sfc -D至此我们拥有了运行和编译Vue3代码的最基础能力。但如何让这些代码在浏览器中运行起来呢这就需要引入构建工具。3. 构建工具选型为什么是Vite在早期Webpack是绝对的主流但其复杂的配置和缓慢的启动/热更新速度在项目变大后成为痛点。我们选择Vite原因非常直接极致的开发体验基于原生ES模块ESMVite在开发环境下无需打包启动速度极快。热更新HMR也是按需进行几乎瞬间完成。对Vue的一等公民支持Vite由Vue作者尤雨溪创建对Vue单文件组件SFC的支持是原生且最优的。简洁的配置相比WebpackVite的配置更加直观和简洁更符合我们“从零理解”的目标。因此我们安装Vitenpm install vite -D同时为了让Vite能够正确识别和编译.vue文件我们还需要安装官方的Vue插件npm install vitejs/plugin-vue -D现在我们的核心开发依赖已经齐全。让我们创建项目的基础结构。4. 搭建项目骨架与基础配置首先创建必要的目录和入口文件vue3-from-scratch/ ├── public/ # 静态资源目录会被直接复制到构建输出目录 ├── src/ # 源代码目录 │ ├── App.vue # 应用根组件 │ └── main.js # 应用入口文件 ├── index.html # 页面入口HTML ├── package.json └── vite.config.js # Vite配置文件4.1 配置index.html这是应用的页面入口。关键点在于我们需要一个div idapp/div作为Vue应用的挂载点并通过script typemodule引入我们的入口JS文件。!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 titleVue3 From Scratch/title /head body div idapp/div script typemodule src/src/main.js/script /body /html4.2 编写src/main.js这是JavaScript的入口文件。在这里我们导入Vue和根组件并创建Vue应用实例。import { createApp } from vue import App from ./App.vue createApp(App).mount(#app)4.3 编写src/App.vue这是我们的第一个单文件组件采用Vue3的script setup语法这是目前最推荐、最简洁的组合式API写法。template div h1Hello, Vue3 From Scratch!/h1 p这是一个完全不依赖脚手架从零搭建的项目。/p /div /template script setup // 这里可以导入其他组件或逻辑 /script style scoped h1 { color: #42b983; } /style4.4 配置vite.config.js这是Vite的核心配置文件。我们需要引入vitejs/plugin-vue来让Vite处理.vue文件。import { defineConfig } from vite import vue from vitejs/plugin-vue // https://vitejs.dev/config/ export default defineConfig({ plugins: [vue()] })至此一个最最基础的Vue3项目骨架就完成了。在package.json的scripts中添加启动命令scripts: { dev: vite, build: vite build, preview: vite preview }运行npm run dev打开浏览器访问http://localhost:5173你应该能看到绿色的“Hello, Vue3 From Scratch!”字样。恭喜你已经成功迈出了第一步5. 工程化深化路由、状态管理与代码规范一个“过得去”的项目不能只是一个Hello World。接下来我们为其注入现代前端应用的灵魂路由和状态管理。5.1 集成Vue Router对于单页面应用SPA路由是必不可少的。我们安装Vue Router 4对应Vue3的版本npm install vue-router4在src目录下创建router/index.js文件来配置路由import { createRouter, createWebHistory } from vue-router // 定义路由组件这里先使用懒加载提升首屏性能 const Home () import(../views/Home.vue) const About () import(../views/About.vue) const routes [ { path: /, component: Home }, { path: /about, component: About } ] const router createRouter({ history: createWebHistory(), routes }) export default router然后在main.js中安装路由import { createApp } from vue import App from ./App.vue import router from ./router createApp(App).use(router).mount(#app)最后修改App.vue加入router-view来显示路由组件并添加导航template div nav router-link to/Home/router-link | router-link to/aboutAbout/router-link /nav router-view / /div /template别忘了创建对应的src/views/Home.vue和src/views/About.vue组件。5.2 集成Pinia进行状态管理对于复杂应用组件间的状态共享是个问题。Vuex 4虽然可用但Pinia是Vue官方推荐的新一代状态管理库API更简洁且完美支持TypeScript。我们选择Pinia。npm install pinia在src目录下创建stores目录并创建一个示例store例如src/stores/counter.jsimport { defineStore } from pinia export const useCounterStore defineStore(counter, { state: () ({ count: 0 }), actions: { increment() { this.count } }, getters: { doubleCount: (state) state.count * 2 } })在main.js中安装Piniaimport { createApp } from vue import { createPinia } from pinia import App from ./App.vue import router from ./router const app createApp(App) app.use(createPinia()) app.use(router) app.mount(#app)现在你就可以在任何组件中通过const counterStore useCounterStore()来使用这个store了。5.3 引入ESLint和Prettier统一代码风格团队协作和代码维护离不开统一的代码规范。ESLint负责检查代码质量问题Prettier负责代码格式化。首先安装相关依赖npm install eslint eslint-plugin-vue typescript-eslint/parser typescript-eslint/eslint-plugin prettier eslint-config-prettier eslint-plugin-prettier -D注意这里我们一并考虑了未来可能使用TypeScript的情况所以安装了typescript-eslint相关的包。如果确定只用JavaScript可以暂时不装。创建.eslintrc.js配置文件module.exports { root: true, env: { node: true, browser: true, es2021: true }, extends: [ eslint:recommended, plugin:vue/vue3-recommended, // 使用Vue3的推荐规则 plugin:prettier/recommended // 将Prettier规则集成进ESLint ], parserOptions: { ecmaVersion: latest, sourceType: module }, rules: { // 可以在这里覆盖或添加自定义规则 vue/multi-word-component-names: off // 允许单个单词的组件名如Home.vue } }创建.prettierrc配置文件{ semi: false, singleQuote: true, trailingComma: none, printWidth: 100, tabWidth: 2, endOfLine: auto }在package.json中添加lint和format脚本scripts: { dev: vite, build: vite build, preview: vite preview, lint: eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore, format: prettier --write . }现在运行npm run lint可以自动修复大部分代码风格问题npm run format可以用Prettier格式化所有文件。6. 开发体验与生产优化配置6.1 配置路径别名Alias在import模块时../../../这种相对路径非常难以维护。Vite允许我们配置路径别名。修改vite.config.jsimport { defineConfig } from vite import vue from vitejs/plugin-vue import path from path export default defineConfig({ plugins: [vue()], resolve: { alias: { : path.resolve(__dirname, ./src) // 将 指向 src 目录 } } })同时为了让ESLint和TypeScript如果使用能识别这个别名需要在项目根目录创建jsconfig.json对于JS项目或tsconfig.json对于TS项目。jsconfig.json示例{ compilerOptions: { baseUrl: ., paths: { /*: [src/*] } }, exclude: [node_modules, dist] }现在在代码中就可以使用import HelloWorld from /components/HelloWorld.vue这样的清晰路径了。6.2 环境变量管理不同环境开发、测试、生产需要不同的配置如API地址。Vite使用.env文件来管理环境变量。.env所有环境共享.env.development开发环境npm run dev时自动加载.env.production生产环境npm run build时自动加载创建一个.env.development文件VITE_API_BASE_URLhttp://localhost:3000/api重要Vite规定只有以VITE_开头的变量才会被暴露给客户端代码。这是出于安全考虑避免敏感信息泄露。在代码中可以通过import.meta.env.VITE_API_BASE_URL来访问这个变量。6.3 生产构建优化Vite的默认构建配置已经不错但我们还可以进行一些微调。分包策略ManualChunks将node_modules中的依赖打包成单独的chunk避免业务代码变更导致整个vendor缓存失效。资源内联/压缩对极小的资源如图标进行Base64内联减少HTTP请求。一个优化后的vite.config.js生产构建部分示例如下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) } }, build: { rollupOptions: { output: { manualChunks(id) { if (id.includes(node_modules)) { // 将vue相关的库拆分成一个chunk if (id.includes(vue)) { return vue-vendor } // 将其他的node_modules依赖拆分成一个chunk return vendor } } } }, // 启用/禁用 CSS 代码拆分 cssCodeSplit: true, // 构建后生成资源的目录 assetsDir: static, // 小于此阈值的资源将被内联为 base64 assetsInlineLimit: 4096 } })7. 样式方案、组件库与测试接入可选但推荐7.1 选择CSS预处理器虽然可以直接写CSS但Sass/Less等预处理器能提供变量、嵌套、混合等强大功能。以Sass为例npm install sass -D安装后就可以在.vue文件的style langscss中直接使用Sass语法了。你还可以在vite.config.js中配置全局的Sass变量文件。7.2 按需引入UI组件库对于一个需要快速开发的项目引入一个成熟的UI组件库如Element Plus、Ant Design Vue、Naive UI是明智的选择。但全量引入会显著增加打包体积。我们必须掌握按需引入。以Element Plus为例首先安装npm install element-plus然后我们需要安装用于自动按需导入的插件npm install -D unplugin-vue-components unplugin-auto-import修改vite.config.jsimport { defineConfig } from vite import vue from vitejs/plugin-vue import AutoImport from unplugin-auto-import/vite import Components from unplugin-vue-components/vite import { ElementPlusResolver } from unplugin-vue-components/resolvers export default defineConfig({ plugins: [ vue(), // 自动导入API如ref, reactive, onMounted等 AutoImport({ resolvers: [ElementPlusResolver()], }), // 自动导入UI组件 Components({ resolvers: [ElementPlusResolver()], }), ], })配置完成后你就可以在模板中直接使用el-button等Element Plus组件而无需在组件内手动import和app.use。插件会在构建时自动处理按需引入极大地提升了开发体验。7.3 集成单元测试VitestVite生态下首推的测试框架是Vitest它拥有和Vite相同的配置、转换器和解析器速度极快。安装Vitest和Vue测试工具npm install vitest vue/test-utils jsdom -D在package.json中添加测试脚本scripts: { test: vitest, coverage: vitest run --coverage }创建vitest.config.js其配置可以与vite.config.js大部分共享import { defineConfig } from vitest/config import vue from vitejs/plugin-vue export default defineConfig({ plugins: [vue()], test: { environment: jsdom, // 模拟浏览器环境 } })然后你就可以在src目录下创建__tests__文件夹来编写你的组件单元测试了。8. 部署上线与持续集成思路项目构建完成后会生成一个dist目录里面是静态文件HTML, JS, CSS, 图片等。部署的本质就是将这些文件放到一个HTTP服务器上。8.1 简单的静态服务器部署你可以使用任何静态文件服务器如Nginx、Apache或者云服务商的对象存储如阿里云OSS、腾讯云COS配合CDN。以Nginx为例一个最简单的配置如下server { listen 80; server_name your-domain.com; root /path/to/your/dist; index index.html; location / { try_files $uri $uri/ /index.html; # 支持Vue Router的history模式 } }关键点是try_files $uri $uri/ /index.html;它确保了在直接访问子路由如/about时Nginx会返回index.html然后由前端的Vue Router来处理路由而不是返回404。8.2 自动化部署与CI/CD对于团队项目手动上传dist文件夹是不可靠的。我们可以结合Git和CI/CD工具如GitHub Actions, GitLab CI, Jenkins实现自动化部署。一个简单的GitHub Actions工作流示例.github/workflows/deploy.ymlname: Deploy to Production on: push: branches: [ main ] jobs: build-and-deploy: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 - name: Setup Node.js uses: actions/setup-nodev3 with: node-version: 18 - name: Install Dependencies run: npm ci - name: Lint run: npm run lint - name: Build run: npm run build env: VITE_API_BASE_URL: ${{ secrets.PROD_API_URL }} - name: Deploy to Server via SSH uses: appleboy/ssh-actionv0.1.5 with: host: ${{ secrets.SERVER_HOST }} username: ${{ secrets.SERVER_USER }} key: ${{ secrets.SSH_PRIVATE_KEY }} script: | cd /path/to/your/project git pull origin main npm ci --onlyproduction npm run build # 这里可以加上重启Nginx或PM2的命令这个工作流会在代码推送到main分支时自动触发执行安装依赖、代码检查、构建并通过SSH连接到服务器进行部署。走完这一整套流程你已经不仅仅是从零搭建了一个Vue3项目而是亲手铺设了一条从本地开发、代码规范、测试到自动化部署的完整前端工程化流水线。这个过程可能会遇到各种报错和配置冲突但每一次解决问题的经历都会让你对“前端项目”这四个字有更深的理解。下次再看到脚手架生成的那一堆文件你就能清晰地知道每一行配置的意图这才是真正的“过得去”。

相关新闻

Python生成器与Yield原理及工程实践

Python生成器与Yield原理及工程实践

1. 生成器与Yield的本质解析1.1 生成器的运行机制生成器本质上是一个特殊的迭代器,但它的执行流程与传统函数截然不同。当调用生成器函数时,Python并不会立即执行函数体,而是返回一个生成器对象。这个对象保存了当前执行状态(包括…

2026/10/6 2:05:15 阅读更多 →
AI-Shoujo HF Patch:一站式模组整合解决方案与安装指南

AI-Shoujo HF Patch:一站式模组整合解决方案与安装指南

1. 项目概述:什么是AI-Shoujo HF Patch? 如果你玩过AI-Shoujo(或者它的姐妹作AI-Syoujyo、AI-Girl),大概率会遇到一个头疼的问题:游戏原版功能有限,社区里海量的角色卡(Character Ca…

2026/10/1 16:08:29 阅读更多 →
Unity虚拟摇杆插件Joystick Pack:5分钟集成移动端游戏输入控制

Unity虚拟摇杆插件Joystick Pack:5分钟集成移动端游戏输入控制

1. 项目概述与核心价值 在移动端游戏开发里,虚拟摇杆是玩家与游戏世界交互的基石。一个手感流畅、响应精准的摇杆,能直接决定一款动作或RPG手游的操作上限和玩家留存率。很多刚入行的朋友,包括我自己早期,都尝试过从零手写摇杆逻辑…

2026/10/9 19:23:57 阅读更多 →

最新新闻

牛客寒假算法集训营第一场题解:双指针、树形DP与字符串DP实战

牛客寒假算法集训营第一场题解:双指针、树形DP与字符串DP实战

牛客寒假算法基础集训营第一场这套题,我印象挺深。难度曲线并不是那种“签到题送到嘴边、压轴题劝退所有人”的极端分布,前几道确实送分,但从G题开始就进入双指针、树形DP、字符串DP这些正经考点,最后两道又考模型转化和临场取舍。…

2026/10/12 6:04:34 阅读更多 →
Codex额度总不够用?揪出4种隐蔽的无效消耗

Codex额度总不够用?揪出4种隐蔽的无效消耗

1. 额度告急的真相:先别急着升级套餐用Codex写代码的人,十个里有八个都经历过这种场景:正写到关键逻辑,突然弹出一行提示说额度用完了,只能干瞪眼等到下一个重置周期。第一反应往往是"是不是我的Plus套餐太少了&q…

2026/10/12 6:04:33 阅读更多 →
特征工程实战全流程:从原始数据到房价预测 R² 0.82 的进阶之路

特征工程实战全流程:从原始数据到房价预测 R² 0.82 的进阶之路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 6:04:33 阅读更多 →
claude-mem 记忆层实战:为 Claude 构建持久化记忆系统

claude-mem 记忆层实战:为 Claude 构建持久化记忆系统

1. 项目缘起与核心定位第一次看到 claude-mem 这个标题,我的直觉是:这应该是一个围绕 Claude 生态做“记忆层”的项目。事实也确实如此。它的核心目标很明确——给 Claude 这类大语言模型加上一层可持久化、可检索、可管理的记忆系统,让模型在…

2026/10/12 6:04:33 阅读更多 →
DeepSeek Harness局域网AI Agent平台Docker部署实战

DeepSeek Harness局域网AI Agent平台Docker部署实战

1. 为什么局域网里需要一个“能自己干活”的AI Agent平台最近两周,我帮三个不同背景的朋友搭过类似系统:一位做工业设备预测性维护的某公司工程师,想让大模型自动读取PLC日志并生成故障简报;一位高校实验室的某导师,希…

2026/10/12 6:04:33 阅读更多 →
有害气体控制洁净工程的底层逻辑:从过滤到吸附,从压差到监测

有害气体控制洁净工程的底层逻辑:从过滤到吸附,从压差到监测

空气里最危险的不是脏,而是失控:有害气体控制洁净工程的底层逻辑干了这么多年洁净工程,我越来越觉得“洁净”这个词会误导人。很多人一听到洁净室,想到的就是无尘、高等级过滤、白大褂和干干净净的地板,下意识把“颗粒…

2026/10/12 6:03:33 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →