资讯详情

资讯详情

前端项目初始化全流程:技术选型、工程配置与协作规范指南

前端项目初始化说出来好像没什么技术含量但以前端开发这个岗位的日常来看真正拉开项目质量差距的往往就是从初始化这一脚开始的。项目初始化不只是执行一句脚手架命令它需要回答的问题其实很多代码放在哪个目录、用什么规范约束提交、依赖版本怎么锁定、测试和构建从哪一步开始介入。这些问题如果不在初始阶段拍板后面就会出现一人生病全家吃药的局面——有人习惯把接口封装散在任意页面里有人用组件文件又有人用逻辑拆分等到多人协作时光是文件位置就能吵上半天。所以这个系列的第一篇我打算把“项目初始化”这件事掰开揉碎讲清楚。它适合刚接触前端工程的新人也适合写过几个项目但一直靠手工维护、想系统梳理一遍流程的老手。不管你用的是React、Vue还是别的框架初始化的核心逻辑都是共通的。我们要做的不只是把页面跑起来而是搭出一套后续开发、调试、发布都能舒服运转的底子能在三个月后不返工、不重构的那种底子。1. 为什么项目初始化值得单独写一篇1.1 项目初始化到底在做什么很多人把项目初始化理解成“脚手架生成一下就完事”但一次完整的初始化至少包含四层工作。第一层是环境决策包括Node版本、包管理器、脚手架工具的选择第二层是工程配置包括TypeScript、构建工具、路径别名、环境变量等第三层是协作规范包括ESLint、Prettier、Git提交规范、分支约定第四层是基础代码的组装比如路由结构、状态管理、请求层、通用组件的初始形态。这四层一层都不能缺缺了哪一层后面都会以各种形式找补回来。空下来看这几个问题的布局听起来都不复杂但真正把它们落地到具体文件、具体命令、具体的钩子脚本里需要跨很多知识面。这一篇的价值就是把这些散落在日常经验里的环节串成一条完整的流程告诉你每一步在解决什么问题以及为什么这一步不能跳过。1.2 初始化阶段决定了项目后续的开发体验一个初始化粗糙的项目通常会在三个月后爆发这些症状新成员找不到某个工具函数应该放在哪里、ESLint报错没人敢改配置、依赖升级后无法回退、团队成员被不同的格式化风格反复折磨。而一套扎实的初始化流程能把这些坑提前填平。我见过一个真实的例子某项目从仓库克隆下来后新成员按照文档安装依赖结果一跑就报错。排查了半天发现package.json里的依赖版本写的是^1.2.3这种带脱字符的范围版本而当前包管理器解析出来的版本和当初开发时完全不一样。这就导致行为表现不一致。这就是初始化时没有锁定依赖版本、也没约定包管理器版本的隐患。反过来如果初始化时就引入锁文件机制并把包管理器版本也一并说明清楚这类问题根本不会出现。另外一个常见的现象是项目里混用了多种代码风格。有人说自己只写三目运算符有人写if判断有人喜欢在组件文件里直接写样式有人非要全部抽到独立样式文件。这些差异在初始化阶段如果通过工具统一掉后面就不需要靠人肉评审来纠正省下大把沟通成本。所以说初始化做得好的项目后面每个成员都是在固定的轨道上“添砖加瓦”初始化做得差的项目后面每一步都是先“清理废墟”。2. 技术选型先把地基打好2.1 脚手架为什么现在默认选Vite初始化项目的第一步是选脚手架。前几年提到前端工程化大家默认就是webpack全家桶后来出现了一些更便捷的一体化创建工具。到现在我的观点很直接新项目不用纠结优先考虑Vite。Vite的核心思路是开发环境下利用浏览器原生ES模块启动时不用预先打包冷启动速度和热更新速度都比传统方案快一个数量级。举个例子一个上百个页面规模的项目用传统方案冷启动可能要去倒杯水Vite往往一两秒就能给出响应。对于需要频繁验证效果的日常开发来说这个差异体感极其明显。生产构建阶段Vite默认基于Rollup完成打包产物体积和分包能力也在持续进步。我用一张表格大概对比一下Vite、webpack和传统一体化工具在新项目里的感受维度Vitewebpack传统一体化工具冷启动速度秒级依赖按需加载分钟级起步随项目膨胀变慢中等受底层工具限制热更新模块级、非常快项目大时会有明显延迟稳定性一般配置复杂度低零配置即可跑通高需要手动管理大量配置低到中生态兼容主流插件基本齐全插件最丰富但老插件多相对封闭适合场景新项目、中小型业务、快速原型遗留项目、复杂定制构建一体化简单场景表里没有提到的一个点是Vite也支持wrapper兼容很多旧插件所以即使项目里有一些历史包袱也不是完全不能迁移。只不过新项目初始化没必要背着这些包袱上路。如果你的团队还没用过Vite我建议先拿一个小型项目试水跑通之后再推广。2.2 TypeScript与框架的取舍语言层面我现在基本不做第二种选择直接用TypeScript。很多刚接触的人会担心TypeScript增加心智负担但在项目初始化阶段引入它长期收益远大于短期成本。类型系统相当于一份可执行的接口文档多人协作时能省下大量沟通成本。一个函数的参数是string还是number不需要点进源码逐行看编辑器里的类型提示已经告诉你答案。TypeScript的配置文件tsconfig.json值得在初始化阶段花十分钟过一遍。比如开启strict模式从一开始就避免隐式any泛滥比如配置路径别名让/指向src目录避免项目里出现大量../../这样的相对路径。路径别名在大型项目里对可维护性的提升非常明显改一个文件的位置不需要牵一发动全身地改路由和组件引用的相对路径。框架层面React和Vue各有拥趸这里不争哪家更好。关键是初始化时把项目定位想清楚管理后台、内容展示站点、移动端H5对应适合的方案并不相同。如果是移动端且需要同时覆盖小程序小型团队可以优先考虑跨端框架如果是传统中后台系统建议把状态管理和权限模型的设计放到初始化阶段一并考虑而不是等页面写了一半再补。2.3 包管理器pnpm还是npm包管理器看似小事实际影响非常大。npm是Node环境自带的默认选择兼容性最好但node_modules体积大、安装速度慢、幽灵依赖的问题让人头疼——你明明没有在package.json里声明某个依赖代码里却能直接引用到这就是因为某层依赖把它带出来了很容易造成环境之间不一致。pnpm用全局内容寻址存储加硬链接的方式不仅节省磁盘空间而且严格的项目隔离能避免不少隐性问题。现在的pnpm也基本兼容npm的生态。从经验来看新项目我更推荐直接用pnpm。如果团队对pnpm不熟npm也完全够用但要在初始化时约定好版本。npm 8以上的版本在性能和锁文件处理上还算稳定。包管理器版本不一致会导致锁文件格式不同这也是很多人踩过的一个坑。可以在package.json里加一个packageManager字段声明项目使用哪个包管理器及其版本再配合包管理器的corepack机制就能尽量避免成员各自用默认环境折腾出不同锁文件。对比一下常见包管理器特性npmpnpmyarn classic默认内置Node自带需单独安装/开启需单独安装安装速度一般快较快磁盘占用高低硬链接共享中等幽灵依赖存在默认隔离存在锁文件package-lockpnpm-lockyarn.lock3. 环境准备与项目搭建3.1 Node.js版本管理项目初始化第一个容易翻车的点是Node.js版本不匹配。不同项目对Node版本要求不同一台机器上经常需要同时维护多个Node版本。我建议用nvm这类版本管理工具允许随时切换全局Node版本也能通过.nvmrc文件让项目锁定Node版本。初始化的时候先执行一下node -v看看当前版本如果偏低或者跟团队不一致就先切换。Node版本到底选多高这得看脚手架和依赖库的支持情况。以Vite搭建的React项目为例常见做法是选18或20这个长期支持主线。长期支持版本稳定性更好开发环境和生产环境都建议保持一致。我见过有项目本地用Node 22服务器还停在Node 16结果某个语法或内置API在新旧版本里表现不一致只在一方报错排查半天才发现是版本差异。所以初始化时把Node版本写进README最好让CI里的构建环境也锁定到同一版本。这里有一个细节nvm的使用并不复杂但要注意在CI或Docker构建里也得同步指定Node版本不能只在本地装。3.2 用Vite创建项目当我需要开始一个新项目时最常执行的命令是pnpm create vite my-project --template react-ts这条命令会创建一个使用React和TypeScript的Vite项目。如果用的是Vue把模板参数换成vue-ts即可pnpm create vite my-project --template vue-ts执行过程中Vite会询问几个问题包括是否安装依赖、是否启动直接确认就好。生成后的项目自带基本的配置文件、入口文件和一个示例页面。很多人在这一步会直接把默认的示例代码删掉然后开始写业务。我建议先不要急着删先把目录结构和配置文件看一遍理解脚手架帮你做了哪些决策。Vite生成的配置都在vite.config.ts里里面通常已经预设了开发服务器的地址、代理和插件配置。如果项目里会用到路径别名比如指向src也需要在这个文件里配合TypeScript的paths一起配置。看着简单但漏配国内很常见结果代码里用/导入编辑器不报错运行或构建时却找不到模块。初始化阶段顺手配好能避免很多后续的魔改。3.3 基础依赖安装脚手架生成的项目依赖很少通常只有框架本身和开发构建相关的工具。真正跑一个业务应用还需要补齐路由、状态管理、样式方案等基础依赖。以React项目为例我通常会装这些pnpm add react-router-dom tanstack/react-query zustand路由负责页面跳转状态管理负责跨组件共享数据请求层负责和接口交互。这几个库之间并不是完全互斥比如React Query和请求函数对应Zustand负责全局状态两者可以共存。关键是这些决策要在初始化阶段统一不要等页面写了一半再引入不然每个人对“数据该放哪”的答案都不一样。样式方案也是同理是CSS Modules、Tailwind还是Sass建议早点决定。很多项目后期出现样式混乱都是因为初始化时没有统一方案各人写各人的。比如有人用纯CSS文件有人在组件标签里写style有人引入Tailwind的原子类最后维护起来异常痛苦。初始化阶段把方案写进文档团队照着一个方式来写才能保证后续样式可预期。4. 工程化配置让项目跑得更稳4.1 目录结构设计初始化阶段最值得花时间的是目录结构设计。一套好的目录结构要满足的核心原则是“可预期”任何人接手代码不用问别人就能找到要找的文件。我常用的目录是源码放在src目录下按功能模块而非按文件类型组织公共组件、页面、请求、工具函数各自独立。一个参考结构如下src/ api/ // 接口请求封装 assets/ // 静态资源 components/ // 公共组件 composables/ // 逻辑复用 layouts/ // 页面布局 pages/ // 页面级组件 router/ // 路由配置 store/ // 全局状态管理 styles/ // 全局样式 types/ // 类型定义 utils/ // 工具函数这个结构不是标准答案但它解决了几个关键问题新增页面知道放哪、公共代码不会散落得到处都是、类型定义集中管理。如果项目规模真的很小先只划分pages、components和utils三个目录也可以等规模成长了再做拆分。目录结构调整起来其实不难但项目大了之后调整成本会指数级上升所以初始化阶段值得把这些目录建好。另外目录命名要统一用单数还是复数、用驼峰还是短横线也要一开始约定。比如components还是componentuserInfo还是user-info。这类细节看着琐碎但影响到每个文件的导入路径和记忆成本。团队约定好之后尽量写进README或贡献指南。4.2 ESLint与Prettier没有代码规范的项目最终会变成代码风格的大杂烩。初始化时就引入ESLint和Prettier成本很低收益很高。ESLint负责检查代码质量和潜在错误Prettier负责统一格式。好用的做法是在ESLint里集成Prettier规则让代码保存时自动格式化。我举个例子团队里有人习惯双引号加末尾分号另一个人偏好单引号且不写分号两人改同一份文件的时候diff里面全是格式化噪音真正的业务改动反而看不清。引入统一格式化后这类问题彻底消失。ESLint还能查出一些真正的逻辑问题比如和混用、未使用的变量、不安全的条件赋值。Vite脚手架生成的模板里通常已经包含了ESLint配置。我们需要确保编辑器在保存时自动执行格式化并配置Prettier的规则比如单引号、不写分号、缩进宽度等。下面是一份比较基础的Prettier配置示例{ semi: false, singleQuote: true, printWidth: 100, trailingComma: es5 }ESLint里也可以配置一些项目级规则比如禁止在代码里出现console.log、强制显式返回类型、限制函数复杂度。不要一上来就加太多规则规则多了会让人反感且难以维护。初始化阶段先配置最核心的检查项后续团队有共识再增量添加。Prettier的哲学是“可争论的规则越少越好”初始化阶段把规则定下来后续就不要再频繁调整避免全仓库大范围diff。4.3 Git初始化与提交规范代码写得再规范协作流程不规范也白搭。初始化Git仓库时第一件事是写好.gitignore文件。Vite模板自带的.gitignore一般已经覆盖了node_modules和dist目录但还要注意忽略本地环境文件比如.env.local、日志文件、编辑器临时目录。这些文件一旦进了版本库处理起来很麻烦提前忽略是王道。提交规范方面我建议用husky配合lint-staged在提交前自动跑检查和格式化。husky能在Git提交或推送时触发钩子脚本lint-staged则只对暂存区的文件执行检查和格式化这样即使项目变大提交前检查的速度也不会明显拖慢。一个典型配置是pnpm add -D husky lint-staged然后在package.json里声明lint-staged的规则比如{ lint-staged: { *.{ts,tsx}: [eslint --fix, prettier --write] } }提交信息规范我也建议在初始化阶段约定。社区里常用的格式是feat、fix、docs、refactor等类型前缀配合commitlint来强制校验。这样生成的提交历史清晰、方便回溯也为后续自动生成变更日志留好了基础。如果你不想一开始就上commitlint至少可以在项目文档里约定commit格式让团队先养成习惯。提交信息写得好将来用命令回溯一行代码为什么被改节省的时间非常可观。5. 实操过程完整跑通初始化流程5.1 从零到一的操作清单我整理了一份比较顺手的操作清单照着做基本不会踩坑用nvm把Node切到指定版本确认node -v和npm -v都是预期结果用pnpm create vite命令创建项目选择React/Vue和TypeScript模板进入项目目录执行包管理器安装依赖补充路由、状态管理等基础依赖配置ESLint和Prettier统一编辑器设置调整目录结构建好src下常用文件夹初始化Git仓库并配置.gitignore启动开发服务器验证HMR和页面访问执行一次生产构建确认没有报错提交第一个commit。有人会觉得这些步骤太琐碎不就是一个项目吗。但实际操作中很多人就是在第五步之后开始放飞自我结果过几天就要推倒重来。初始化流程的完成标志不是“页面能显示”而是“后续加代码的路径是明确的”。所以第八步和第九步不能省略。先启动一次开发服务器确认HMR正常再跑一次构建确认生产构建没有报错最后提交一次commit确认Git钩子都生效。这些验证都通过才算真正完成初始化。5.2 启动开发服务器并验证执行开发命令很简单pnpm dev如果用的是Vite控制台会打印本地的访问地址。打开浏览器后把首页渲染、路由跳转、页面热更新都依次试一遍。热更新的标准是修改一个组件里的文字浏览器应该在不刷新的情况下自动变化。如果改了代码页面没反应八成是HMR配置或依赖监听问题。接着跑一次类型检查和构建pnpm build构建成功后会生成dist目录这就是要部署到服务器的产物。如果构建阶段就报错说明项目配置还没到位别等到上线前才发现。构建时也可以顺手看看产物提示比如chunk大小、依赖包体积。如果某个依赖特别大可以考虑后续做代码分割或异步加载。初始化的项目跑一次构建的价值就是确认整个链条是通的而不是等到业务开发了几千行代码之后再暴露问题。5.3 第一次提交的完整流程开发服务器验证通过后进入Git提交流程。先执行git init初始化仓库然后git add把所有文件加入暂存区再执行git status检查有没有不该提交的文件比如本地的.env.local、日志文件或者某个临时目录。如果全局没有配置过Git用户信息当前项目里要单独设置git config user.name your-name git config user.email your-emailexample.com如果配置了husky和commitlint第一次提交时它们会自动执行检查。可能遇到提交信息不合法、ESLint报错等情况这恰恰说明钩子生效了。第一次提交信息我通常写feat: project init。提交完成后用git log --oneline查看一下提交记录确认结构没问题再推送到远程仓库。这里要注意远程仓库如果已经有一些代码比如自动生成的README务必先git pull --rebase再push避免无意义的合并分支或覆盖别人的提交。6. 常见问题与排查技巧实录6.1 Node版本不匹配最常见的报错是类似“Unsupported engine”或者“requires node 18”这样的提示。遇到这种情况先确认当前Node版本node -v。如果版本偏低用nvm安装并切换如果版本过高也未必是好事某些老依赖在Node新版本下会有兼容问题。建议让项目的Node版本和CI环境保持一致并在README里写清楚最低版本要求。有人会问为什么不直接在package.json里固定Node版本实际上约定加工具才能生效比如在.nvmrc里写好版本号再用包管理器的引擎校验来兜底。初始化阶段就把这套联动配好后续基本不会再遇到“本地跑得动大家都在报错”的局面。6.2 依赖安装失败依赖安装失败的原因多种多样网络原因、镜像源问题、node_modules缓存损坏都可能导致。我常用的排查步骤是先删掉node_modules和锁文件重新安装再看报错信息是否指向某个具体包。如果反复不行考虑切换镜像源或检查代理配置。另一个容易忽略的点是包管理器版本不统一有人用pnpm 6有人用pnpm 9生成的锁文件格式不同协作时非常容易冲突。解决方法是统一包管理器并把版本信息写入package.json的packageManager字段。另外在Windows和macOS/Linux不同的环境里某些依赖的安装脚本行为也可能不一样。比如一些原生的二进制包在Windows上可能需要预编译版本否则尝试本地编译会报缺工具链。初始化阶段如果团队成员已经跨平台建议提前明确每个平台的额外依赖要求避免新成员一上来就卡在安装这一步。6.3 端口被占用启动开发服务器时提示端口被占用一般是之前的开发进程没有退出或者同时跑着另一个项目。Vite会默认递增端口所以换个端口也能继续开发。如果希望项目始终用固定端口可以在vite.config.ts里的server.port字段设置。排查时可以用系统命令查看端口占用进程确认没有残留后再重新启动。还有一个相关坑前端项目常用端口号和本地代理绑定。如果代理配置里写错了目标端口控制台不会直接报错但所有接口请求都会失败。初始化阶段如果项目需要对接后端服务最好把代理配置和约定端口一并写入vite.config.ts和团队文档减少每个人各自猜测的情况。6.4 husky钩子不生效装了husky后提交时钩子却没有执行大部分原因是只安装了依赖但没跑husky的初始化命令。现代版本的husky需要执行npx husky init来生成.husky目录和钩子脚本。如果项目是从某个模板拷贝的.husky目录没有被提交到Git新克隆的仓库自然没有钩子。验证钩子是否生效可以临时在文件里加一行故意不合规的代码再尝试提交一次看钩子是否拦截。如果拦截了说明配置正常如果没有就要检查husky的安装状态和Git的core.hooksPath设置。另外一个常见的误操作是直接把旧的钩子脚本复制进.husky但钩子脚本里找不到可执行命令比如npx在某些环境下的路径问题。初始化阶段把这些跑通一次后续成员就不会被这种问题反复折腾。6.5 热更新不生效热更新失效的体验非常难受。常见原因包括编辑器保存触发的是文件变更但已经被忽略项目目录在虚拟磁盘或共享目录中文件监听失效某些缓存问题导致状态残留。我的排查顺序是先看控制台有没有报错再试着重启开发服务器。如果重启之后恢复正常多半是监听问题。使用某些网络驱动器或同步盘同步代码的开发环境Vite的HMR常常不稳定这也是这类工具链的一个已知短板。项目初始化时尽量让代码库放在本地磁盘远程同步目录只做备份能省掉很多诡异问题。如果项目本身很大还可以调整Vite的server.watch配置比如关闭轮询的开销或者把node_modules排除在监听范围之外。初始化阶段不需要调这些优化但知道排查方向遇到问题时不至于一脸懵。7. 一些初始化过程中的经验补充写完主体流程再顺手补几个我踩过的坑都是文档里通常不写的东西。第一初始化的第一个commit一定要“干净”。意思是不管项目多小第一次提交前先确认没有大文件、没有密钥文件、没有本地临时文件。一旦密钥或大文件进了Git历史后面清理起来极其麻烦因为每次checkout都会把历史带出来。初始化那天就养成用git status的习惯比任何时候都重要。第二别急着引入一堆花哨的库。项目初始化阶段最容易冲动安装各种“看起来有用”的依赖结果很多用不上还白白增加体积和安全风险。我现在的习惯是“用到才装”。比如没做图表之前不装图表库没做拖拽之前不装拖拽库。基础依赖控制在最小必要范围内后续再按业务需求增量添加反而更清爽。第三把初始化决策记录下来。可以是在README里建一个“项目约定”章节也可以单独写一份工程规范文档。内容包括Node版本、包管理器、目录结构、命名规范、提交规范、样式方案。这些信息看着琐碎却是新成员接入项目的“接口说明书”。项目做久了文档比代码更稀缺初期随手记几句后面能少回答无数次重复问题。第四如果你所在团队有多个项目可以考虑把初始化流程沉淀成内部模板。当模板跑通一次之后新成员创建项目的时间能从半天压缩到十分钟。但模板本身也要定期维护不要一劳永逸。依赖升级、插件变更、团队规范调整都需要同步更新模板。把初始化当作一个持续维护的工程资产来对待收益和投入是完全成比例的。写到这里这一篇初始化流程算是踩出了一个相对顺滑的版本。我个人实际操作中的体会是前端项目初始化最重要的不是用多新的工具而是把决策都提前做完并写下来。哪怕某些工具组合不是最流行只要团队达成一致并且文档清楚项目推进起来都会踏实很多。如果你正准备开一个新前端项目照着这份流程先跑一遍大概率能少走很多弯路等跑完一遍再根据团队习惯调整目录和规则很快就会形成属于你自己的初始化标准。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →