Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gulp 中的任务规划和流程控制 #2

Open
sweeetcc opened this issue Oct 3, 2016 · 1 comment
Open

Gulp 中的任务规划和流程控制 #2

sweeetcc opened this issue Oct 3, 2016 · 1 comment
Assignees

Comments

@sweeetcc
Copy link
Owner

sweeetcc commented Oct 3, 2016

gulp-structure

## 理想中的 gulpfile

我理想中的 gulpfile 包含两部分:

  1. 任务列表,列表中包含具体的单个任务,单个任务保持明确,与其他任务解耦合,能够独立完成某个任务,同时不依赖也不影响其他任务的执行;
  2. 流程列表,流程列表中包含了任务的组合,流程可能包括:开发流程、测试流程、打包流程等。各个流程需要考虑到开发环境、任务属性等。

所以理想中的 gulpfile 规划是:

gulpfile

任务列表示例:

// Scripts
gulp.task( 'js', jsTask ); // 对应 tasks/js-task.js
// Style
gulp.task( 'css', cssTask ); // 对应 tasks/css-task.js
// HTML
gulp.task( 'html', htmlTask ); // 对应 tasks/html-task.js

// ...

gulp-tasks

流程列表示例:

// Develop
gulp.task( 'dev', ['clean'], () => {
    runSequence(['vendor', 'js', 'css', 'html', 'font', 'image', 'static'], 'serve', 'watch');
} );

// ...

gulp-flow

gulp 任务规划的原则

在重构和梳理 gulpfile 的过程中,我一直遵循以下原则:

  1. 解耦合 —— 任务独立,清晰明确,中间过程不做过多暴露;
  2. 流程化 —— 基于任务独立,最优化流程配置;
  3. 可配置 —— 将可配置的东西尽量抽离到配置文件中。

gulp 任务规划的目的

使用 gulp 管理前端任务已经很久了,很喜欢 gulp 的基于流的构建系统。之前的 gulpfile 一直工作比较稳定,在多条业务线数十个项目中也一直都是 copy & paste,所以有了很多冗余。另外,由于之前的 gulpfile 中有很多“嵌套”的任务,也就是任务间的时序和组合是通过在 'task' 后面传数组实现的,比如:

gulp.task('task2', ['task1'], function() {
    ...
});

以这样的方式来控制执行 task1 后再执行 task2。导致下图这种为了一个构建 'scripts' 的任务,产生了各种冗余任务: 'scripts:init:controllers', 'scripts:init:directives', 'scripts:init:filters', 'scripts:init:services', 'scripts:init'…… 任务。任务之间的依赖关系错综复杂,非常混乱。

old-tasks-organize

基于以上提到的原则,“解耦合”非常重要,'scripts' 的构建应该由单一的 'scripts' 任务来独立完成,不向外暴露冗余任务:

js-task

貌似任务本身有点长…… 但是确实做到了单一任务完成单一职责,没有暴露过多冗余任务。

需要提前明确的几个概念

一、两种模式:

这里的两种模式是指最常规的两种模式:开发模式和构建模式。

之所以说是最常规的模式,是因为除了这两种模式可能还会包含“测试模式”等其他模式。这里明确两种模式是为了更好的区分:开发&构建 这两个概念。

1. 开发(dev)需要什么?

  1. 开发需要便于调试:为此,需要加入 sourcemap ,需要源文件映射 & etc.;
  2. 开发需要提升体验:为此,需要有 livereload,实现文件监听和自动化编译 & etc.。

2. 构建(build)需要什么?

  1. 构建需要文件压缩:为此,需要加入 js 的 uglify,img 的 compress, css 的 minify & etc.;
  2. 构建需要加版本号:为此,需要针对静态资源文件做 hash 前缀,并替换原始路径 & etc.;
  3. 构建需要做模板缓存:(针对 Angular 项目)为此,需要使用 templateCache 做模板缓存。

3. 如何区分?

我在 gulpfile 中使用了一个全局变量来区分两种模式:

global.isBuildMode = false;

这个变量是如何起作用的呢?下面使用一个具体的任务 css task 来作说明:

css-task

二、 三种环境

三种环境包括: 本地开发环境、测试发布环境和线上发布环境。

关于三种环境的区别,需要提前做一个说明:

  1. 本地开发环境使用的是本地的 browserSync 做服务器,主要优点就是它的自动刷新做得很人性化,比如如果是样式更新可以直接 inject 生效,而不用刷新,所以会很快;而脚本更新这种需要刷新的动作,browserSync 会主动刷新页面;
  2. 测试发布环境和线上发布环境基本上主要流程一直,唯一的区别是线上的编译最终会使用 CDN 做静态文件托管,而测试环境最终构建完成的文件会在测试机上。

1. 如何区分环境?

(1). 从大的方面来讲,本地环境和另外两种环境使用任务名称作区分:

env-task-difference

(2). 从更加细致的方面讲,测试环境和生产环境的区分主要通过命令行传参数:

env-param

2. 环境变量会影响那些流程?

环境变量的作用不可小觑,它决定了以下方面:

  1. 本地开发的时候需要远程 api,远程 api 的调用通过给 browserSync 添加 node 中间件做代理,代理的地址由环境变量决定;
  2. 项目构建时,会根据环境变量决定静态文件最终是否替换成 CDN 地址 &.etc。

env-api

重构步骤

对于旧项目 gulpfile 的重构主要是以下四个步骤:

第一步:明确目录结构,写出基础配置

第二步:拆分单个任务,对任务进行配置,进行各种调试

第三步:组成流程,包括本地开发流程,线上打包流程等

第四步:针对流程通过变量控制等去调试各个任务在不同流程中的任务细节差异

重构心得:

第一点:解耦合很重要

gulp 任务解耦合可以使任务更明确、清晰,排查问题更为容易,同时也更容易维护。秉承“单一任务,单一职责”的原则,不仅可以使任务间的互相依赖减少,也隐藏了很多中间处理的流程,这样,我们能很容易的实现文件流的控制。解耦合也为流程化的实现奠定了基础。

第二点:流程化

流程化是指可以通过 gulp 任务的组合来实现包括本地开发、线上编译等各个流程。虽然我们把任务拆分的相对独立,但是仍然存在一定的时序问题,比如,本地开发模式下,我们需要让 css、js、image、font &etc. 任务执行后,再启动 watch、serve 任务,就需要控制时序,这里我用了一个插件 run-sequence。

@sweeetcc
Copy link
Owner Author

对于任务划分的粒度其实有很多可以讨论的地方,因为拆分梳理过程中发现把单一任务划分出来完成一整套职责,可能一定程度上增加了复杂性。

@sweeetcc sweeetcc self-assigned this Oct 18, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant