gulp

Gulp是一个前端自动化构建工具,它的配置的编写非常简单易用而且支持大量插件,能够轻松的自动化完成前端构建任务。目前最新版本是Gulp4,这篇笔记我们以该版本为例介绍Gulp的使用。

官网:https://gulpjs.com

Gulp和Webpack的区别

Gulp和Webpack这两个工具的初衷是完全不同的。Gulp是一个基于流程(task)的构建工具,通过我们指定的若干task完成一个预期的工程构建;而webpack是一个打包(Bundle)工具,它通常用来将一些源码和资源打包,本身并没有什么流程的概念。

至于为什么各种前端框架的脚手架都不需要Gulp,因为它们都是纯前端SPA框架,项目构建比较简洁,也谈不上什么task,而且这个过程完全不需要开发者干预。Webpack丰富的插件也能方便的实现代码合并混淆压缩、ES6转义、各种Loader打包加载资源、HMR等功能,Gulp的功能点完全用不上。而如果是我们自己一步步写起来的项目,尤其是那种多页面、前后端不分离的大型项目,又有代码合并混淆压缩的需求,Webpack当然是办不到的,我们自然而然的会想到找一个“构建脚本”去干这件事,这时候就是Gulp出场的时候,甚至可能Gulp + Webpack的形式出场。

安装Gulp

实际开发中,我们通常在工程中局部安装Gulp工具。

npm install gulp --save-dev

安装完Gulp后,我们还需要在项目根目录创建一个配置文件gulpfile.js,构建流程需要在这个配置文件中配置。

配置构建流程

下面是一个gulpfile.js的例子,它没有实际意义,仅仅是演示如何定义Gulp构建流程。

const {series} = require('gulp');

function clean(cb) {
    console.log('clean执行了');
    cb();
}

function build(cb) {
    console.log('build执行了');
    cb();
}

exports.build = build;
exports.default = series(clean, build);

能够被gulp命令调用的构建流程需要定义为一个函数并通过exports暴露,上面代码中我们暴露了build而没有暴露clean,因此可以使用命令gulp build,而调用gulp clean则会报错。除此之外,exports.default定义的是默认的构建流程,即直接执行gulp命令不附带参数时的动作。

顺序和并行构建流程

series表示一个顺序执行的构建流程序列,它可以用来连接多个构建流程。之前代码中,如果执行命令gulp,那么cleanbuild会依次顺序执行。除了series,还有一个parallel()用来连接并行的构建流程。

exports.build = series(
  clean,
  parallel(
    cssTranspile,
    series(jsTranspile, jsBundle)
  ),
  parallel(cssMinify, jsMinify),
  publish
);

如果有多个复杂的构建流程需要连接,在exports的赋值语句中连接它们是推荐的写法。

src()和dest()

构建过程其实就是读文件->处理文件->写文件src()用来指定读取哪些文件,dest()用来指定输出到哪里。

下面是一个将ES6文件用Babel转译为ES5的例子。

const {src, dest} = require('gulp');
const babel = require('gulp-babel');

function build() {
    return src('src/*.js')
        .pipe(babel({
            presets: ['@babel/env']
        }))
        .pipe(dest('dist/'));
}

exports.build = build;

Gulp配置的一个构建流程中,每一个小步骤都要用pipe()连接起来。

使用插件

上面其实已经用到了我们非常熟悉的babel插件,Gulp支持大量的高质量插件,我们可以在Gulp官网搜索其它插件。

https://gulpjs.com/plugins/

在这些插件的npm仓库中,一般都会注明其用法。

触发自动构建

前端开发本来没有编译构建这些繁琐的步骤,现在引入了Gulp,虽然可以用上各种现代化、工程化的特性了,但是如果每次修改一点代码就手动运行一次命令去构建代码就太麻烦了,gulp支持监测文件系统中的文件修改触发自动构建。

exports.default = function () {
    watch('src/', build);
};

注:代码中的build流程沿用之前的Babel转义功能。

Gulp使用实例

这里我们为一个SpringBoot应用编写一个Gulp构建流程,后端应用出于业务复杂性和开发效率等多种因素考虑,并未使用现代化的框架和前后端分离模式开发而是使用Thymeleaf模板,这里我们需要用Gulp处理JavaScript和Less代码。我们打算使用watch去实时构建,而不是在Maven或Gradle中调用Gulp。

gulpfile.js

const {src, dest, parallel, watch} = require('gulp');
const babel = require('gulp-babel');
const uglify = require('gulp-uglify');
const rename = require('gulp-rename');
const less = require('gulp-less');
const minifyCss = require('gulp-minify-css');

function buildLess() {
    return src('static/src/*.less')
        .pipe(less())
        .pipe(minifyCss())
        .pipe(dest('static/dist/'));
}

function buildJs() {
    return src('static/src/*.js')
        .pipe(babel({
            presets: ['@babel/env']
        }))
        .pipe(uglify())
        .pipe(rename({extname: '.min.js'}))
        .pipe(dest('static/dist/'));
}

exports.default = function () {
    watch('static/src/', parallel(buildJs, buildLess));
};

上面代码中,我们定义了两个并行的task,分别用来编译jsless

<link th:href="@{/dist/style.css}" type="text/css" rel="stylesheet" />
<script th:src="@{/dist/app1.min.js}"></script>
<script th:src="@{/dist/app2.min.js}"></script>

在模板中,我们直接引入生成的.min.js文件。

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-devtools</artifactId>
</dependency>

为了在gulp实时构建后,SpringBoot能够热部署,我们引入了devtools的起步依赖。

这样,我们的目的就基本实现了。当然,其中的不完美之处还有很多,比如:

  1. 应该加一个clean任务,buildclean应单独暴露出来
  2. 没有在模板引用CSS、JavaScript文件时加上版本号,版本迭代升级时,用户浏览器的缓存可能造成干扰
  3. 不支持ES6的import语法,这里其实我们应该再引入webpack进行打包配合Gulp的构建任务

看来要做到尽善尽美还是很复杂的,不过这里仅仅是演示gulp的使用,这里就不多说了。从上面例子我们可以发现,gulp作为一个前端构建工具确实是个神器。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap