0
点赞
收藏
分享

微信扫一扫

职场人必修课:高效沟通与自信表达慕ke分xiang

东林梁 2022-06-03 阅读 57

前端工程化

Part 1 工程化概述

1、工程化的定义和主要解决的问题

前端工程化通常是指遵循一定标准及规范,通过工具去提高效率,降低成本的一种手段。

技术往往是为了解决问题而存在的,前端工程化也不例外。我们在日常的前端开发中就经常面临诸多问题,比如想用ES6+新特性,但兼容有问题。还有当我们想要使用Less/Sass/PostCSS来增强CSS的编程性时运行环境不能直接支持。再有当我们想要使用模块化的方式来提高项目的可维护性时运行环境也不能直接支持。此外,还有项目部署上线前需要手动压缩代码及资源文件,部署过程需要手动上传代码到服务器等重复性较强的工作。并且在多人协作开发时,无法硬性统一大家的代码风格,从仓库中pull回来的代码质量也无法保证。之前都是在编码中可能出现的问题,但在开发具体功能时也会遇到部分功能开发时需要等待后端服务接口提前完成的问题。

总而言之大概分为以下几类:1、传统语言或语法的弊端。2、无法使用模块化/组件化。3、重复的机械式工作。4、代码风格统一、质量保证。5、依赖后端服务接口支持。6、整体依赖后端项目。

2、一个项目过程中工程化的表现

一切以提高效率、降低成本、质量保证为目的的手段都属于「工程化」。

在创建项目时使用脚手架工具自动创建项目结构,创建特定类型文件,完成基础项目结构搭建。

在编码时可以自动格式化代码,校验代码风格,编译/构建/打包。

在预览/测试时可以使用Web Server/Mock,Live Reloading/HMR体验热更新(编码完成后直接在浏览器中看到最新结果)及在后端没有完全完成时进行开发(Mock假接口)。还有Source Map可以在编译后还能定位到源代码所在位置。

在代码提交环节,可以使用Git Hooks工具来在代码提交前做项目整体的检查(项目质量以及代码风格)。且对于提交日志(git log)也可以做严格的格式限制,这对于我们日后需要回滚代码时具有很大的参考价值。另外还有Lint-staged以及持续集成等。

在部署环节中,工程化表现的地方就更多了,我们可以用一行命令去代替传统的ftp上传,甚至还可以实现代码提交后通过CI/CD的方式自动将代码部署到服务器。

3、工程化不等于工具

注意,工程化并不等于某个具体的工具。因为现阶段有部分工具的功能过于强大,例如webpack,导致有部分人认为工程化就是webpack,只要用了webpack就等于有了工程化,但实际并非如此。工程化的核心应该是对项目整体的一个规划或说架构,而工具在这个过程中只是用来帮我们去落地实现这种规划架构的手段。

我们可以在一些成熟的集成式的工程化方案中找到一些思路,比如:create-react-app,vue-cli,angular-cli,gatsby-cli等,很多人认为这些工具都是官方给出的脚手架,实际上,这些工具应该都属于特定类型的项目官方给出的集成式工程化方案。如vue-cli中不仅仅为我们创建了项目,更多的是约定了vue项目是什么样的结构。在此之上vue-cli还提供了一些工具让我们可以有热更新的开发服务以及自动编译vue单文件组件与其他一些模块文件还有代码风格的校验,这些实际上都是集成在vue-cli内部的service之中的。而这些东西其实都是工程化中的几个维度。所以说像这些工具我们可以称之为工程化的集成。

4、工程化与 Node.js

有人说Ajax给前端带来了新的生命力,而Node的出现对于前端无异于工业革命,可以说前端工程化是由Node强力驱动的。工程化是一个非常庞大的概念,并且还在不断发展,值得强调的是不管他如何发展,其始终都是为了解决问题而存在的。

接下来我们将在:1、脚手架工具开发。2、自动化构建系统。3、模块化打包。4、项目代码规范化。5、自动化部署。这五个方面去具体来看如何在这些维度落实前端工程化。

Part 2 脚手架工具

5、脚手架工具概要

脚手架可以简单理解为自动帮我们去创建项目基础文件的一个工具,可以说是前端工程化在项目创建时的表现。但他最本质的作用其实不仅仅是创建项目的基础结构,更为重要的是他还提供了项目规范以及约定。其中包括:1、相同的组织结构。2、相同的代码开发范式。3、相同的模块依赖。4、相同的工具配置。5、相同的基础代码。因有很多需要相同的规范与约定,所以就会出现我们在搭建新项目时有大量的重复工作要去做。脚手架工具就是用来解决这样一个问题的,我们可以通过脚手架工具去快速搭建特定类型的项目骨架,然后基于这个骨架去进行后续的开发工作。

例如Visual Studio与Eclipse这样大型的IDE,其创建项目的过程就是一个脚手架的工作流程。而在前端项目创建过程当中,由于前端技术选型比较多样,又没有一个统一的标准,故前端方向的脚手架一般不会集成在某个IDE中,都是以一个独立的工具存在,并且相对会复杂一些。但本质上,脚手架的目标都是一样的,都是为了解决创建项目过程中那些复杂的工作。

接下来,我们先会介绍常用的脚手架工具,并对通用的脚手架工具进行剖析,最后还会去开发一款脚手架工具。

6、常用的脚手架工具

目前有很多成熟的前端脚手架工具,但大多都是为了特定的项目类型服务的,例如在React项目中可以使用create-react-app,在vue.js项目中可以使用vue-cli,在angular项目中可以使用angular-cli。这些工具的实现方式都大同小异,无外乎都是根据我们提供的信息自动创建对应的项目基础结构以及相关配置。不过他们一般只适用于自身所服务的那个框架的项目。还有就是以Yeoman为代表的通用型脚手架工具,他们可以根据一套模板生成一个对应的项目结构,这种脚手架一般都很灵活,而且容易扩展。除了以上这些在创建项目时才会用到的脚手架工具,还有一类脚手架工具也非常有用,代表性工具就是Plop,他们用来在项目开发过程中创建一些特定类型的文件,例如我们要想在一个组件化的项目中创建一个新的组件,或在模块化的项目中创建一个新的模块,这些模块和组件一般是由特定的几个文件组成的,而且每个文件都有基本的代码结构,相对于我们手动一个个去创建,脚手架会提供更为便捷更为稳定的一种操作方式。在了解了这些工具过后,我们接下来会重点关注几个有代表性的工具。

7、Yeoman简介

现今,React.js与Vue.js还有angular大行其道,这些框架的官方都提供了更为集成的脚手架工具链,所以大家在谈论到脚手架时往往最先想到的都是像Vue-cli,Angular-cli这样的工具。而对于这类的工具,由于他太过针对某一个框架,而且在使用上也非常普及,在此就不作过多的介绍了。

这里我们着重去探讨Yeoman这种工具,因为Yeoman作为最老牌,最强大,最通用的脚手架工具,有更多值得我们借鉴与学习的地方。Yeoman官方的定义说他是一款“用于创造现代Web应用的脚手架工具(The web's scaffolding tool for modern webapps)”,不同于vue-cli这样的工具,Yeoman更像是一个脚手架运行平台,我们可以通过Yeoman搭配不同的Generator去创建任何类型的项目,也即我们可以通过创建自己的Generator从而去定制属于我们自己的前端脚手架。

而Yeoman的优点也同样是他的缺点,在很多基于框架开发的人眼中,由于Yeoman过于通用,不太专注,所以他们更愿意使用像vue-cli这样的脚手架。这也是像vue-cli这样的工具问什么现在这么成功的原因,但这并不妨碍我们去学习Yeoman,那接下来我们就快速去了解一下Yeoman的用法以及Generator的工作原理,为我们后面去开发自己的脚手架做出准备。

8、Yeoman 基础使用

Yeoman是一款基于Node.js开发的工具模块,使用Yeoman的第一步自然是通过npm在全局安装他。当然,使用npm去安装模块的前提是我们需要在机器上正常安装Node环境。注意后续我们会在使用npm时用一个叫做yarn的工具去取代他,yarn和npm在很多使用上是类似的,只不过他的体验可能会更好一些。

接下来我们会用yarn来安装yeoman,而yarn的全局安装命令是:​​yarn global add​​:

yarn global add yo
复制代码

yo就是yeoman的工具模块名。但在之前我们就介绍过,单有yo这个模块是不够的,因为yeoman是搭配特定的generator才能去使用,所以我们要使用yeoman去创建项目的话就必须要找到对应项目类型的generator。例如我们想要去生成一个node-module的项目,一个node的模块,我们就可以用一个叫generator-node的模块,而使用这个generator的方式也是先把他全局安装。

yarn global add generator-node
复制代码

安装这两款模块之后,我们就可以使用yarn去运行刚刚所安装的generator-node这个生成器,自动地去帮我们创建一个全新的node module。

yo node
复制代码

注意,运行特定的generator就是把包前面的generator-前缀给去掉。在创建过程中,yeoman还会提出一些问题,我们可以在命令行中通过命令行交互的方式把相关信息填写进去,而这些信息则会影响最终生成出来的项目结构。当所有选项都输入结束后,yeoman会在当前目录下创建一些基础文件,并帮我们在项目根目录下运行npm install去安装这个项目必要的一些依赖。在项目目录下,除了基本的文件外,内部的一些基础代码,包括一些基础配置都是帮我们提前配置好的,这也是脚手架工具的一个优势。

总结:1、在全局范围安装yo。2、安装对应的generator。3、通过yo运行generator(注意要先到想要创建项目的文件夹下再运行)。

9、Sub Generator

有时候我们并不需要创建完整的项目结构,可能只是在已有的项目基础之上去创建一些特定类型的文件,例如给已经存在的项目创建一个README,又或是在原有的项目之上去添加某些类型的配置文件,如ESLint或Babel配置文件。这些配置文件都有一些基础代码,如果我们手动去写的话很容易配错,而我们可以通过生成器自动帮我们去生成,来提高我们的效率。如果说我们需要这样的需求的话,可以使用Yeoman所提供的Sub Generator这样的特性来实现。具体而言就是通过在项目目录下运行一个特定的sub Generator命令去生成对应的文件。在此,我们就可以使用generator-node里所提供的子集生成器“cli”来帮我们生成一个cli应用所需要的一些文件,来让我们这个模块变为一个cli应用。

yo node:cli
复制代码

运行Sub Generator的方式就是在原有的Generator名字后面跟上":"和Sub Generator的名字。注意回车后他会提示我们是否要重写package.json这个文件,因为我们在添加cli支持的时候会添加一些新的模块和配置,这里我们选yes。完成之后会提示我们重写了package.json以及创建了一个cli.js的新文件。回到编辑器,在package.json中,我们会看到一个bin的配置以及新的dependencies,这些都是我们在新的cli应用中所需要的。除此之外我们在lib目录下的cli.js中也可以看到一些cli应用基础的代码结构,有了这些我们就可以将我们的模块作为一个全局的命令行模块去使用了。而本地的模块我们可以使用​​yarn link​​到全局范围,之后通过模块的名字去运行刚刚加进来的模块(注意在新加入配置文件后还需要输入​​yarn​​去安装相应的依赖,若还运行不了可以看看本节最下面的链接)。这个就是Generator的子集Generator的特性了,值得注意的是,并不是每一个generator都提供子集的生成器,所以我们在使用之前需要通过我们所使用的generator的官方文档来明确。例如在我们示例中的generator-node的官方文档(​​传送门​​)中就说明了这些相关的sub generator。

若yarn link后还运行不了相关命令请看:

​​记录Win上使用yarn link的那些坑​​

10、Yeoman 使用步骤总结

  1. 明确需求。
  2. 找到合适的Generator。(​​传送门​​)
  3. 全局范围安装找到的Generator。
  4. 通过Yo命令运行对应的Generator。
  5. 通过命令行交互填写选项。
  6. 生成所需要的项目结构。

另外还需要注意的是,一些生成器生成的项目中会依赖一些C++的模块,而这些模块需要在安装过程中下载一些二进制文件,但这些文件并不能通过npm镜像去加速,所以速度会相对慢一点,不过我们也可以通过配置对应的镜像去提高这些二进制文件的下载速度。下图是部分二进制文件的镜像配置:

职场人必修课:高效沟通与自信表达慕ke分xiang_python

11、自定义 Generator

通过前文对Yeoman的基本介绍,我们发现不同的Generator可以用来生成不同的项目,也即我们可以通过创造自己的Generator来帮我们去生成自定义的项目结构。而即便市面上已经有了各种各样的Generator我们还是有创造自己的Generator的必要,因为市面上的Generator都是通用的,而我们在实际开发中可能会出现一部分基础代码甚至是业务代码在相同类型项目时还是会重复,这时我们就可以把公共的部分都放在脚手架中去生成,让脚手架工具去发挥更大的价值。例如我们在创建Vue.js的项目的时候,官方默认的脚手架工具只会去创建一个最基础的项目骨架,这并不包含我们经常要用到的一些模块如Axios、vue-router或vuex,而我们就需要在每次项目创建完成之后手动去引入这些模块并去编写一些基础的使用代码。试想一下,如果我们把这些也放到脚手架之中,那就不存在我们刚刚说过的问题了。那么重点来了,自定义Generator该如何去实现呢,接下来我们就以自定义一个带有一定基础代码的Vue.js项目脚手架为目标来向大家介绍。具体内容请看下回分解。

12、创建Generator模块

在正式开始自定义Vue项目脚手架之前,先让我们来介绍一些基础的内容。创建Generator实际上就是创建一个npm模块,但Generator有特定结构,他需要在根目录下有一个generators的文件夹,然后在这个文件夹下再去存放一个app文件夹用于存放我们生成器对应的代码。如果我们需要提供多个的Sub generator则可以在app的同级目录再去添加一个新的生成器目录。例如我们添加一个component目录,此时我们的模块就有了一个叫做component的子生成器。

职场人必修课:高效沟通与自信表达慕ke分xiang_python_02

除了特定结构,还有一个与普通npm模块所不同的是,Yeoman的Generator的模块名称必须是​​generator-<name>​​这种格式,如果说我们在具体开发的时候没有去使用这样格式的名称,那么Yeoman在后续工作的时候就没办法找到我们所提供的生成器模块。

接下来我们按流程去做一个基本的演示。首先我们通过​​mkdir​​去创建一个叫​​generator-sample​​的文件夹作为生成器模块的目录,然后在这个生成器的目录下通过​​yarn init​​的方式去创建一个​​package.json​​。之后我们再运行​​yarn add yeoman-generator​​去安装一个​​yeoman-generator​​模块,这个模块提供了一个生成器基类,这个基类中提供了一些工具函数,让我们可以在创建生成器的时候更加便捷。安装完依赖之后,我们用vscode打开这个目录,然后在这个目录下按照项目结构要求去创建一个​​generators​​文件夹,并在这个文件夹下创建​​app​​文件夹,之后在​​app​​文件夹下创建一个​​index.js​​文件。而​​index.js​​文件会作为​​Generators​​的核心入口,他需要去导出一个继承自Yeoman Generator的类,Yeoman Generator在工作时会自动调用我们导出的类当中的一些生命周期方法,我们可以在这个文件中通过调用父类提供的一些工具方法去实现一些功能,比如文件写入。

// generators/app/index.js
// 我们先通过require的方式载入yeoman-generator
const Generator = require('yeoman-generator')
// 然后我们需要导出一个类,让这个类继承自Generator
module.exports = class extends Generator {
// 在这个类中我们定义一个writing方法
// 这个方法会在Yeoman工作时的生成文件阶段自动调用这个类中的writing方法
// 在这个方法中,我们可以通过文件读写的方式往我们生成的目录下写入文件
writing() {
// 这里我们通过父类中的fs模块去写入文件到我们的生成目录。
// 需要注意的是,这里的fs模块与我们在node中的fs不太一样,
// 这是一个高度封装的file system模块,相对原生的fs模块功能会更加强些。
// 这里的write方法有两个参数,一个是写入文件的绝对路径,另一个是写入文件的内容
this.fs.write(this.destinationPath('temp.txt'), Math.random().toString());
}
}


举报

相关推荐

0 条评论