🔥本文或许可以帮你快速了解前端工程和工程化
当我准备开始写这篇文章的时候,我突然觉得有些迷茫~
通常来讲,我会确定一个主题,然后会让AI给我一个可能的提纲,而我来根据自己的理解,收集,参考一些依据,做一些论证小实验,从而来完成一篇相对负责任的文章,可是这一次我有点犹豫了,因为就这一个主题下,AI给我的提纲和我想说的出入有点大,或者说AI太八股了,而我想说的是一些能够快速解释前端工程化的杂谈。
这是 AI 给我的提纲:
这提纲没什么不好的,全面,但是偏正式,偏八股。
而我想说的可能更适合于从实践的角度快速理解前端工程并非想解释前端工程化,因为我觉得只有你知道前端工程的概念,你才能明白工程化。
以下我会从实际工作中的视角代入前端工程,做一个简单的全览。
here we go!
⚠️ 不过在开始之前也需要了解一些前端工程化的八股概念 (偷个懒直接交给gpt):
前端工程化的定义:
前端工程化是一种思想,它利用软件工程的技术和方法来规范前端的开发流程,提高效率,保证质量,它包括了开发、测试、部署等所有的步骤。前端工程化的重要性:
随着Web技术的发展,前端的复杂性也在不断提高,前端工程化可以帮助我们更好地管理这种复杂性,提高开发效率,减少错误。模块化:
是将复杂的程序分解为互相独立的模块,每个模块只负责一部分功能,模块之间通过接口通信。这样可以提高代码的可维护性和可复用性。组件化:
是在模块化的基础上,将UI分解为可复用的组件,每个组件包含了它的视图和逻辑。这样可以提高UI的一致性和开发效率。工程化:
是将软件工程的方法应用到前端开发中,包括版本管理、测试、构建、部署等。这样可以提高质量和效率,减少错误。自动化:
是使用工具自动执行重复的任务,如构建、测试、部署等。这样可以减少人为错误,提高效率。
⚠️ 阅读本文之后,你会有以下收获:
前端工程在项目中是什么
前端工程在前端工作流中是什么
前端工程原来就这~
正文开始👉
⚠️ 特别提示:以下内容旨在帮助快速理解相对局部、相对微观的前端工程化,更多的是前端工程的东西,并不会全面且细致的去阐述前端工程化,若需八股,还是得多看看面经~
当你入职后拿到一个repo坑位后,什么是前端工程?📌
一般来说我们入职后会先熟悉团队的各种开发规范,工作流,通常最初你大概率会负责一个repo坑,也不排除多个或者monorepo的情况,但总体是一样的,下面我们用一个基础的monorepo举例:
正常来讲你的前端工程都是基于git做版本管理,基于node和npm做工程管理,而webpack,vite,rollup等其实是基于node的上层工程管理框架,当然也有一些基于rust的工程管理库,比如Rspack,当然了,这几个主要是负责前端工程的打包构建等方面。
我是怎么看的,任何一个Application都是一堆代码和资源组成,这些代码和资源分散在各个文件或文件夹里,而前端工程就是它们和管理的总和。
简单来说就是你看到的repo所有都是前端工程,这是一句废话,但是请听我慢慢解释:
husky:(githook工程管理)
基于三方库husky的githook管理功能目录node_modules:(npm包工程管理)
npm包安装目录,及环境变量bin目录packages:(代码及资源目录)
代码和资源scripts:(当前仓库脚本管理)
一些前端工程需要写一些脚本帮助管理,比如build,release时的一些脚本.cz-config.js:(git.commit工程管理)
基于三方库cz-customizable的prompt交互式commit自定义配置文件.eslintrc.cjs:(代码规范管理)
基于三方库eslint的代码规范配置文件.gitignore:(git.tracing管理)
基于git的,git文件跟踪管理配置文件.lintstagedrc.json:(git.worktree工程管理)
基于三方库lintstaged的git工作区的管理配置文件.prettierignore:(代码风格工程管理)
基于三方库prettier的工作区的管理配置文件.prettierrc.js:(代码风格工程管理)
基于三方库prettier的管理配置文件commitlint.config.js:(git.commit风格工程管理)
基于三方库commitlint的管理配置文件,用于规范git提交docker-compose.yml:(docker部署工程管理)
基于docker和docker-compose的部署配置文件nginx.conf:(nginx部署工程管理)
基于nginx的部署配置文件package.json:(npm项目工程管理)
基于node和npm的项目配置文件pnpm-lock.yaml:(pnpm项目依赖版本工程管理)
基于pnpm的依赖版本管理文件pnpm-workspace.yaml:(项目工作区工程管理)
基于pnpm的monorepo管理配置文件prometheus.yml:(普罗米修斯监控工程管理)
基于三方软件Prometheus的监控配置文件README.md:(项目说明)
基于markdown的项目说明文件tsconfig.js:(ts及tsc工程管理)
基于tsc的ts工程管理配置文件
或许你会奇怪为什么没有webpack
或者vite
或者其他框架的配置文件,其实是有的,只不过在packages
目录下具体的子项目里, 不过我想要说的是,不论是webpack
还是vite
,这些开发及构建工具都是基于node
的能力开发的上层框架,而你也可以不用这些, 直接用node
提供的能力来开发及构建自己的项目,当然工作中没人会这么做,因为他们提供了强大,便捷,全面的功能。
这就是你拿到的前端项目,这就是前端工程。
当你在 development 环境开发时,什么是前端工程?📌
试想一下当你进入开发阶段了,你会干嘛?我想大多数情况下是这样的(注意:这里并不会深入的探讨每一个步骤的具体实现,而是粗略介绍):
npm install
- npm会在node_modules下去安装在npmjs.org官方源(具体源需要根据你的npmrc配置或者你本地npm config配置)搜索到的你的package.json里声明的所有依赖。
- 并会生成对应的lock文件,方便统一所有开发人员的依赖版本。
npm run dev
- npm会找到对应的pacakge.script的dev命令,执行命令,这时取决于你的package.json中dev的配置,比如:
cross-env API_ENV=development NODE_ENV=development webpack serve --config webpack/webpack.dev.ts
,这段命令是用cross-env定义了2个node的环境变量,并根据指定webpack目录下的配置文件,来webpack serve启动。
- npm会找到对应的pacakge.script的dev命令,执行命令,这时取决于你的package.json中dev的配置,比如:
编码
- 编码时,vscode中你的eslint,prettier插件会根据你的eslint和prettier的配置文件来检查你的代码规范和代码风格,基于AST。
- 一般来说你用的编辑器中,比如vscode,有LSP(Language Server Protocol)服务,为你提供顺畅的编码体验,比如:自动完成,跳转定义,查找引用等。
保存 -> 更新
- 一般来说,你修改完代码之后(注意如果修改的是对应的启动配置文件,需要重新npm run),webpack和vite都会进行编译,并更新代码,也就是热替换简称HMR(Hot Module Replace),而这也是基于node的能力实现的,这里以webpack为例,通常来说开发环境下会启用一个Websocket来进行通信,如有更新,相对应的文件hash会改变,并且告诉浏览器加载新的文件,从而达到热替换的效果。
- 这里也可以提一句前端常用的devServer配置,也就是绕过浏览器的同源策略的常用方案,proxy代理,其背后也是通过node实现,比如通过httpProxyMiddleware这类中间件来转发你的请求,一旦你配置了devServer或者proxy那么,webpack就会拦截你代码里的请求,转发到目标服务器,以达到绕过浏览器同源策略的效果。
跑测试用例
- 一般来说前端单元测试,如果是工具函数的测试用例,就相对简单一些,导入方法,调用,看执行结果是否符合预期即可,也是运行在node。
- 我们会在开发环境做的稍微复杂一点的单元测试应该来说是组件、页面的功能测试,他会用到一些无头浏览器(headless browser),也是基于node这个JavaScript运行时的,比如:谷歌的Puppeteer,只是它并不会显示UI,但是你仍然可以请求html页面,click某个按钮,检测页面是否有正常显示,或判断某个input元素上是否出现了某个class。
提交代码
如果你项目配置了husky,并成功安装了githook,那么会根据你配置的githook来做相应的操作,比如下图配置了2个钩子,一个是在执行git commit之前触发,一个是在git commit时触发。
分别有以下代码:
pre-commit:
commit-msg:
pre-commit的代码,会在你git commit之前触发这一段bash命令,在git commit之前会执行npx lint-staged,npx是npm的一个包运行器,我们这里用npx来执行lint-staged,会调用三方库lint-staged,它默认会先读取你的执行目录下的.lintstagedrc这种配置文件,会根据配置文件里的代码,在你的git暂存区进行相应的操作,通常来讲你的.lintstagedrc文件里面是如下代码:
javascript{ "*.{js,jsx,ts,tsx,vue}": ["prettier --write", "eslint --fix"] }
通常被用来做代码规范的检查,以及代码风格的转换,当然你完全可以随意做其他操作~。
commit-msg的代码,会调用三方库commitlint,它默认会根据执行目录下的commitlint.config.js之类的配置文件的具体配置,来对你的commit的message进行检查。
不难看出以上步骤,几乎都是基于node这个runtime来执行,基本上可以说是前端工程离不开node。但现在有一种用rust来构建前端工程体系的趋势,比如Bun,SWC,Rspack,Oxlint等。
当你集成到 test 环境测试时,什么是前端工程?(TLDR)📌
- 这一段其实已经不仅仅是前端工程了,被包括在了CICD或者DevOps的工程里面了,但是和开发环境是同理的,但更复杂,因为涉及一些诸如远程仓库管理,脚本,镜像管理,集成测试,构建优化的东西,还有一些其他技术,比如
Github Action
,或者是Gitlab Hook
这些,有机会再填这个坑吧。
当你集成到 production 部署时,什么是前端工程?(TLDR)📌
- 部署里面有很多前端工程,通常是和构建息息相关的,我们可以倒回去讲讲 Webpack 对于构建这一块的处理,比如为什么资源是用的 Content Hash 来命名?其实就和部署有莫大关系。另外除了以上之外,有个比较大的区别就是通常来说是根据具体情况具体分析的工程配置了,需要基于一些判断和结论,根据采集的数据来做相应的工程处理,当然你得先有数据监控,埋点,数据清洗,数据分析,服务监控,资源监控等很多监控手段。这里甚至涉及到很多系统设计,系统架构的知识,所以,还是有机会再来填这个坑吧。
😊okk~ 关于局部且微观的前端工程化就水到这里啦~ 未完待续~