编译
工程化是一个编译和打包的过程。
首先,什么是编译?
(资料图)
举个例子,当我们需要执行一个java文件。
在前端工程化以前,作为一门解释型语言,JavaScript是不需要像Java这样经过编译这个过程,它可以在浏览器中直接运行。
那么,为什么现在不这么做了?
浏览器兼容性问题
开发人员编写的不再是纯粹的JavaScript
解释第一点:
事实上,JS的版本每年都在升级,tc39每年都会收集意见稿对JS标准做出一些改动,增加一些特性,删除一些特性,其中最著名的版本就是ES2015(ES6)。
但JS的迭代跟Java的迭代不同,这个过程并不由开发者决定。
在Java中,只要开发者不主动升级JDK,那么Java新版本的改动就不会影响到开发者的代码,代码的运行结果也始终不会脱离期望。
但在JS中,这个过程由浏览器厂商和用户决定,开发者并不能知道自己的代码会被作为什么版本的JS来执行。
假如,开发者为了方便开发,在自己的代码中使用了ES2022的新特性,但用户使用的是厂商在2020年发布的浏览器,那么,你费尽心血编写的代码,将不能得到所期望的结果。
而且,浏览器厂家并不是只有Google,浏览器内核也并不是只有blink,不同内核,甚至相同内核不同版本的浏览器对JavaScript的执行能力也不一致。
我们需要一个工具,来将兼容性不那么良好的高版本JS,编译成兼容性相对更加优秀的低版本JS。
这样的话,即可以在开发中使用新特性来简化开发,也能确保在低版本浏览器中能够被正确地执行。
它就是babel。
解释第二点:
所有的网页归根结底由HTML(结构)、CSS(样式)、JS(交互)组成。
但直接编写上述三种文件来满足现代网页的开发需求是难以实现的,主要问题在于:
现代网页结构异常复杂,动则成千上万个dom,难以拆分
样式表命名空间复杂,权限比重不清
操作dom的api并不是那么易于使用,且弱类型的JS难以维护
为了解决上述问题才有了React、Vue、Angluar、Svelet、Solid等前端框架。而这些框架为了解决上述问题提出了自己的代码格式:react的jsx、vue的sfc,它们是JS又不是JS。
为了解决JS弱类型难以维护的问题,Microsoft提出了TypeScript,同样的,.ts是JS又不是JS。
目录结构
为了在不同框架下保持统一,前端项目在目录结构上有一些不成文的约定
根目录下:
public目录,这个目录中的文件会保持原样输出到打包好的代码中
dist目录,打包好的代码默认输出到这个目录出,若不存在则构建工具会自动生成它
src目录,所有源代码(除index.html外),都应该存放在此目录中
src目录下:
assets目录,存放图片、字体、样式表等网页需要引用的静态资源。注意,资源虽然是静态的,但仍会在打包过程中被编译,构建工具会使用一段hash重命名这些资源,资源的路径也会被改变。
api目录,存放发送网络请求相关代码,比如封装axios,react-query部分的代码。
components目录:存放公共组件,多次被引用才算公共组件,只被一个位置引用的组件不应该出现在这里
hooks目录:存放公共hook。注意,hook对项目框架是有依赖的,并不能跨平台使用。
pages目录:存放网页代码,每个网页都应该是一个目录。
routes目录:存放路由表,及路由配置代码。
stores目录:存放全局状态机,比如pinia、redux相关代码。
types目录:存放.d.ts声明文件。
utils目录:存放公共函数,不同于公共hook。公共函数不对框架有依赖,这部分代码应当是跨平台的。
入口文件:整个应用程序的入口文件
根组件:框架的根节点
路径别名
在引入一个自定义模块,或是使用静态资源文件的时候,都会需要使用到路径。
引用资源时,相对路径不应当被滥用。如下:
使用路径别名,改变上面这种丑陋的引用方式。
有些构建工具默认配置了上述约定,而有些则需要手动配置。
配置路径别名(vite举例)
打包
正如前面提到的,所有的网页最终给到用户的一定是HTML、CSS、JS。
构建工具会将我们编写好的.ts、.tsx、.jsx、.vue、.scss、.less等文件编译成.js和.css。
需要注意:
有些打包工具会将有引用关系的模块直接编译为单个.js。这往往会造成编译出的.js过大,从而影响用户打开网页的速度。
对于体积较大的npm包,最好在打包时进行分包。
必要时可以打包生成gzip,用以提高网页的加载速度。(需要nginx开启支持)