为什么我们开发 San 项目时要用 CLI?
导读:本文是 San CLI 的使用和原理的第一篇,主要介绍 San CLI 的初衷和使用,下一篇介绍具体的实现原理。
一、什么是 CLI
CLI,是命令行界面(command-line interface )的英文缩写,命令行界面是在图形用户界面得到普及之前使用最为广泛的用户界面。
我们就不看图形用户界面和命令行界面的定义了,直接举两个例子直观些。
这是图形用户界面:
这是命令行界面:
虽然命令行界面没有图形用户界面使用广泛,但后者并不能取代前者,原因这里列举一些:
远程操作。如果我们要远程操作一台服务器,而且不用命令行界面,那么,我们就得先来个远程桌面连接,这显然比较麻烦,或者,我们可以跑到那台服务器面前给它装个显示器,当然,服务器不能离我们太远。
自动化。如果要用图形化界面执行一些自动化流程,那就得用按键精灵来录制操作
计算资源。图形化界面需要的计算资源远比命令行界面需要的计算资源多。
所以,有时我们还是需要 CLI 的。
我们了解了 CLI 后,那 San CLI 又是什么?
顾名思义,San CLI 是 San 的 CLI 。简单来说,它是一个内置 Webpack 的命令行工具,当我们在开发 San 项目时,它能帮助我们省时省力。具体它是怎么帮助我们省时省力的,文章后边会讲到。
二、为什么要做 CLI
1. 「生产工具提升生产力」
CLI 是前端开发的生产工具,提升 CLI 的体验可以直接提升我们的生产力,这是我们的第一需求。
San CLI 从项目的创建、开发、调试、上线研发全流程入手,分别提供对应的解决方案,提升研发体验和开发效率。
除此之外,CLI 作为开发过程中接触最多的工具,我们的目标是以它为基础,做一套前端工程化集成解决方案,将项目和团队的最佳实践融入到 CLI 中,同时统一并且标准化项目,以便只需要升级 CLI 就可以实现解决方案在项目之间的迁移。
举例说明:假如我们团队通过实践证明某一个方案可行,那么我们可以封装到 CLI 的某个命令中,或者发布对应的插件,通过改变打包参数来让项目支持这种解决方案,比如 PWA、modern mode 等。
2. 「I have a dream!」
而我们更宏大的目标是:把 San CLI 做成一套可定制的前端工程化集成解决方案,让大家可以忘了 Webpack,直接通过执行 San CLI 提供的命令行命令来开发。
「Yes,We Can!」
三、San CLI 有什么功能
接下来,我们将从开发一个新项目的全流程,即项目的创建、本地开发、调试、打包上线这 4 个环节,来介绍 San CLI 的功能。
1. 创建:通过脚手架标准化项目
首先是项目的创建。我们在命令行里执行 san init xxx
,就会创建一个名为 xxx 的文件夹,然后在里边初始化一个 san 项目。
为了方便我们之后开发,在初始化的过程中,命令行会询问我们一些问题,我们对这些问题的回答将决定最终初始化出来的项目是什么样子的。
我们来看看初始化的实际过程。
可以看到,有一个警告,这个警告是因为我们在执行初始化项目命令时没有指定脚手架模板,于是 San CLI 使用默认的脚手架模板来初始化。默认的脚手架模板就可以满足大多数情况,所以无视这个警告就行。如果我们遇到了需要另外指定脚手架模板的情况,比如我们想用我们自定义的脚手架模板,可以移步 San CLI 官方文档查看该怎么做,这里我们只介绍最常用的部分。
现在我们来看下命令行问我们的这些问题分别都是什么意思。
项目名称:这个名称会用于 package.json 里的 name 字段的值,以及 README.md,默认使用项目所在文件夹的名称作为项目名称,在这里也就是 xxx。
项目描述:用于 package.json 里的 description 字段的值。
作者:用于 package.json 里的 author 字段的值,以及初始化时生成的文件的头部注释。
选择模板引擎:有 2 个可选项,一个是图中的 “Smarty”,另一个是 “纯 HTML”,也就是不用模板引擎。如果我们不了解模板引擎或者不知道该选什么,那就选 “纯 HTML”。
是否安装 ESLint:ESlint 的作用是检查编码规范。
选择 ESLint 配置:如果我们上一步同意了安装 ESLint,才会有这一步。这一步有 3 个可选项,
@ecomfe/eslint-config
、Standard
、Airbnb
,选我们喜欢的就行,百度内部一般是用 @ecomfe/eslint-config。是否安装 ESLint 的 lint-staged:如果我们之前选择了安装 ESLint,才会有这一步。如果安装,那么,之后我们在开发中执行 git commit 的时候,会对改动的文件进行编码规范检查,检查不通过就无法完成 git commit。出于对高质量的代码的追求,建议安装。有的人可能会担心有的情况确实不需要检查代码规范怎么办,比如把远古时期的代码从一个库迁移到另一个库,很简单,只需要给 git commit 命令加上
--no-verify
就可以跳过检查了。安装 demo 示例:如果我们对用 san 开发不熟悉,建议安装,这样我们开发时就可以参照 demo 了。
选择示例代码类型:如果我们上一步同意了安装 demo 示例,才会有这一步。这一步有 2 个可选项,“san-store” 和 “normal”。如果我们不知道自己是否需要用
san-store
,那就不用。选择 CSS 预处理器:有 3 个可选项,
less
、Sass
、stylus
,选我们喜欢的。是否安装依赖,这里可装可不装,这里不装的话之后可以自己装。
最终初始化出来的项目看上去是下面这样的:
Hands up:现在我们团队项目中的组件每次创建目录结构也是类似的,所以可以做成脚手架然后使用`san init`来安装
2. 开发:local server、mock
创建完项目,就到了开发阶段。在开发阶段,需要调试页面,那我们可以在命令行里项目目录执行 san serve
。
执行完之后,命令行会输出一个 URL 和一个二维码,如下图所示:
访问这个 URL 或者扫描这个二维码,就可以看到我们正在开发中的页面了,如下图所示:
我们修改代码后,页面会实时地响应我们的修改,非常方便。
Hands up:对于 smarty 我们提供了`hulk-mock-server`来做 local server,另外它也集成了接口 mock 功能,可以对接类似 YAPI 之类的 API 管理平台。
3. 部署:生产环境打包和远程部署
开发完成后,如果需要部署到其它的机器上,比如部署到 QA 的机器好让 QA 测试,这时就要用到生产环境的打包。
生产打包也很简单,在命令行里项目目录执行 san build
就行。
执行完之后,我们可以在命令行里看到打包结果的信息,包括产出的文件所在路径、文件大小等,如下图所示:
打包好了就该部署了,San CLI 当然也支持了,我们通过执行 san build --remote <remote-name>
就可以将生产环境的编译产出直接远程部署到目标机器。
不过在执行这个命令前,需要进行相应的环境配置以及参数配置,详见 San CLI 官方文档:https://ecomfe.github.io/san-cli/#/deployment。
4. 其他功能
1)查看 Webpack 内置信息
有时我们可能对打包的结果不满意,那就可以通过在命令行里项目目录执行 san inspect
来查看 Webpack 所有的内置信息了,如下图所示:
如果只想打印部分内置信息,也是可以的,只需要在执行命令时加上想要查看的内置信息对应的参数即可,比如加上 --rules
或 --rule postcss
。
2)图形用户界面
虽然我们名字叫命令行界面(CLI),但是我们也提供了图形用户界面以方便不同习惯的开发者。
只要在命令行执行 san ui
就可以打开 San CLI 的图形用户界面了,如下图所示:
该图形用户界面不只是把在命令行里也能做到的功能图形化了,它还提供了命令行不具备的功能,比如管理项目、阅读新闻等,值得一试,后续我们会有专门介绍该图形用户界面(即 San CLI UI)的文章,敬请期待。
四、怎么自己定制功能
虽然 San CLI 本身的功能已经覆盖了绝大多数的用 San 开发时的场景,但是如果我们想要定制化的功能,也没问题!
我们可以通过编写插件来扩展 San CLI 的功能,自定义解决方案。
针对 CLI 的使用场景,我们将 San CLI 的插件设计成了两类:
Command 插件:命令行插件,用于添加自定义命令,添加完之后我们就可以执行
san your_command_name
这样的自定义命令;Service 插件:当我们想要定制的功能需要用到内置 Webpack 配置 或
san.config.js
里的配置时,就选择开发 Service 插件而不是 Command 插件。
接下来我们以实际的例子分别看下具体怎么自定义 Command 插件和 Service 插件,通过简单例子,理解下两种插件的不同用途。
1. Command 插件
我们打算给 San CLI 扩展一个 hello 的命令,效果是当我们执行 san hello --name 百度
后,命令行会输出 百度,你好呀!
。
首先在项目根目录创建一个名为 san-command-hello.js
文件,内容如下:
exports.command ='hello';exports.builder ={ name:{ type:'string'}};exports.desc ='热情地向给定对象打招呼';exports.handler= argv =>{ console.log(`${argv.name},你好呀!`);};
exports.command
:定义命令的名字,这里我们给定义为了hello
;exports.builder
:定义命令接受的参数和参数类型,这里我们定义命令接受字符串类型的name
参数;exports.desc
:定义命令的描述,即我们在命令行输入san hello --help
后的输出,这里我们给定义为了热情地向给定打招呼对象
;exports.handler
:定义输入命令后的处理器函数,这里我们通过处理器函数的argv
参数拿到了命令接受的name
参数,然后用它拼接了一个字符串,最后输出这个字符串。
然后在项目的 package.json
文件中添加如下配置:
至此,就大功告成了,来看看执行效果:
嗯,令人满意。
另外,我们还可以把我们自定义的命令作为 npm 包发布出去,在这个例子中就是发布 san-command-hello.js
文件,并且遵循 san-cli-command-<whatever-you-like>
的命名方式,比如 san-cli-command-hello
,那么,我们就可以在其它项目中直接通过安装这个 npm 包来引入这个自定义命令了。
2. Service 插件
我们看完了怎么自定义 Command 插件,接下来就来看怎么自定义 Service 插件。
我们打算自定义一个 Service 插件用于获取网站的入口文件。
首先还是在项目根目录,创建一个名为 san-cli-plugin-get-entry.js
文件,内容如下:
Service 插件的 apply 函数接受三个参数:
api
:是 PluginAPI 实例,会提供一些 API,详见 San CLI 官方文档;projectOptions
:是san.config.js
里的处理后的项目配置;options
:是项目引入插件时传入的参数。
然后在项目的 san.config.js
文件中添加如下配置:
plugins
是一个 Service 插件数组,里面的每一个 Service 插件又是一个数组,数组第一项是插件的路径,数组第二项是传入插件的参数。
关于 Service 插件的执行时机:当 Service 实例化之时,会依次将 Service 插件进行注册执行。那 Service 什么时候实例化?我们可以简单认为当我们输入`san init`、`san build`等命令时 Service 会实例化。
至此,又大功告成了,也来看看执行效果:
可以看到,现在执行 san build
比之前执行多了两行输出,这两行输出就是我们自定义的 Service 插件产生的效果。
嗯,再次令人满意。
当然,和 Command 插件一样,我们也可以把我们自定义的 Service 插件作为 npm 包发布出去,为了方便他人找到我们的优秀 Service 插件,建议按照 san-cli-plugin-*
来命名。当引入一个 npm 包形式的 Service 插件时,只需把原来的插件路径 './san-cli-plugin-get-entry.js'
换成 require('san-cli-plugin-*')
即可。
五、最后
感谢你阅读到了这里,以上便是《为什么我们开发 San 项目时要用 CLI?》的全部内容。
San CLI 除了以上介绍的的功能外,还有其它许多功能,比如打包分析、性能分析、自定义项目脚手架、Markdown 建站等等,不一而足,墙裂推荐你体验体验!
我们下期《 San CLI 的实现原理》再见!
原文链接:https://mp.weixin.qq.com/s/R9hE5wdCkDQTZEKwQ4DiFQ
百度架构师
百度官方技术公众号上线啦!
技术干货 · 行业资讯 · 线上沙龙 · 行业大会
招聘信息 · 内推信息 · 技术书籍 · 百度周边
欢迎各位同学关注!
评论