Gulp 入门

记录一些Gulp相关的入门知识

Posted by ddxg on September 23, 2019

Gulp 入门

介绍

直奔官网吧

看了一遍官网还是半脸懵逼呀!很多都不理解,不知道为什么要这样写,不知道配置的具体用意。多练多看文档才是硬道理呀。

下面实现一个跟 webpack入门练习 类似结构的入门练习项目

打包的是一个简单的 H5 页面,主要有js打包、图片打包、css打包和html打包。js需要处理 ES6语法 和 模块化。

具体的gulp任务如下:

img

处理 js

  • 因为要处理模块的导入导出,需要使用到 browserify
  • 处理 ES6 等高级语法的话就使用跟 browserify 配套的 babelify
  • 压缩代码的话使用 gulp-uglify

browserify

browserify是javascript编译工具,可以通过预编译方式,将后端的node模块加入javascript中,进而可在前端浏览器上执行。

browserify 的文档内容还是很多的,我都没怎么看,主要是看不太懂。

我想说的是这个 browserify.transform(tr, opts={}) 方法,有一个 opts.global 的参数,全局转换,官方的意思是不太推荐设置为true的,具体为什么我也还没有搞懂。

babelify

browserify只做模块化处理,没有转 ES6+ -> ES5 的功能,babellifybabelbrowserify 提供的,用于 webpack 和 browserify 等构建工具中的

在这里 babellify 需要跟 browserify 结合使用达到 模块化处理 和 ES6+ -> ES5 转化。

安装:

npm install --save-dev babelify @babel/core

先看代码:

const { src, dest } = require('gulp');
const uglify = require('gulp-uglify');
// 处理模块化的插件,实际是node系,获取的文件将是普通Node Stream
const browserify = require("browserify");
// 转成gulp系的二进制stream流
const buffer = require('vinyl-buffer');
// 转成gulp系的stream流
const stream = require('vinyl-source-stream');
const babelify = require('babelify');

function buildJs(cb) {
    return browserify('src/js/index.js')
        .transform(babelify.configure({
            "presets": [
                "@babel/preset-env"
            ],
            "plugins": [
                // 使用 @babel/plugin-transform-runtime
                [
                    "@babel/plugin-transform-runtime", 
                    {
                        // options配置see:https://babeljs.io/docs/en/babel-plugin-transform-runtime
                        "corejs": 2,
                        helpers: false
                    }
                ]
            ]
        }))
        // 生成了Node Stream中的Readable Stream,而Readable Stream有管道方法pipe()
        .bundle()
        // 监听错误
        .on('error', function (error) {
            console.log(error.toString())
        })
        // node系只有content,添加名字转成gulp系可操作的流
        .pipe(stream('index.js'))
        // 转成二进制的流(二进制方式整体传输)buffer
        .pipe(buffer())
        // 压缩处理,gulp-uglify只支持Buffer类型的Vinyl File Object
        .pipe(uglify())
        // 输出
        .pipe(dest('dist/js/'))
}

我是觉得这里有几个转化流的概念很难理解,可能我对 Node.js 中流的概念还不太理解,也基本没有使用 Node.js 的原因。

这里要介绍一篇博客,专门讲了这方面的知识,我的注释很多都是参考它的,探究Gulp的Stream

处理图片

图片处理的话基本上就是压缩图片了,图片装base64的操作放在css中处理。

使用的是 gulp-imagemin 插件,这个插件默认提供了缩小PNG、JPEG、GIF和SVG图像的功能,如果想要深度压缩图片的话,文档中有 插件连接 的连接,点击就可以查看可以使用的插件了。我这里就是用默认的插件吧,正常图片的话UI给到开发这边的时候就应该是压缩好了的,我也习惯性的会使用这个网站 TinyPNG 进行图片压缩。

安装:

npm install --save-dev gulp-imagemin
function buildImg(cb) {
    console.log('处理img');
    return src('src/img/*.{jpg,png,gif,svg}')
    .pipe(imagemin([
        imagemin.gifsicle({interlaced: true}),
        imagemin.jpegtran({progressive: true}),
        imagemin.optipng({optimizationLevel: 5}),
        imagemin.svgo({
            plugins: [
                {removeViewBox: true},
                {cleanupIDs: false}
            ]
        })
    ]))
    .pipe(dest('dist/img/'));
}

文档中有各种图片类型参数的配置,可以去查看文档。

压缩图片操作比较费时,可以使用 gulp-cache 缓存插件,只压缩改变的图片。

function buildImg(cb) {
    console.log('处理img');
    return src('src/img/*.{jpg,png,gif,svg}')
    .pipe(cache(
        imagemin([
            imagemin.gifsicle({interlaced: true}),
            imagemin.jpegtran({progressive: true}),
            imagemin.optipng({optimizationLevel: 5}),
            imagemin.svgo({
                plugins: [
                    {removeViewBox: true},
                    {cleanupIDs: false}
                ]
            })
        ]), {
            name: 'gulp-img'
        }))
    .pipe(dest('dist/img/'));
}

加了缓存之后编译确实更快了 img

别忘了添加一个清理缓存的任务:

function clearImgCache(cb) {
  cache.clearAll();
  cb();
}

处理 css

处理css还是比较固定的

  • 处理 stylus sass 等css预处理器
  • 添加兼容前缀
  • 有需要的话还要处理样式中的图片文件,转成base64形式
  • 压缩css

需要安装的依赖:

npm install --save-dev gulp-stylus gulp-autoprefixer gulp-clean-css

如果需要将css中的图片使用base64方式替换的话,需要使用 gulp-base64 插件。

npm install gulp-base64 --save-dev

我是习惯将小于 2k 的图片放在源码目录里面,打包css的时候将这些小文件都使用base64方式替换。大于 2k 的图片就直接使用 cdn 连接形式。这样可以减少图片的请求量,也可以控制css文件不会太大。

function buildCss(cb) {
    console.log('处理Css');
    
    return src('src/stylus/index.styl')
    .pipe(stylus({
        'include css': true
    }))
    .pipe(autoprefixer())
    .pipe(base64({
        baseDir: 'dist/img',
        extensions: ['svg', 'png', 'jpg', 'gif'],
        exclude:    [/file\.xxx\.cn/], // 排除 cdn 的图片
        maxImageSize: 2 * 1024, // bytes,为了确保css文件按不过大,小于2k的图片才转换
        deleteAfterEncoding: false,
        debug: true
    }))
    .pipe(clean())
    .pipe(dest('dist/css/'));
}

处理html

我这里想做的是一个单页H5,css 、 js 和 小图标 都内联在 html 文件中,发布的时候就只发一个 html 文件就行了。

使用 gulp-inline-source 插件 将css和js 内联进html页面。可以内联 <script> <link> <img>,在需要内联的标签上需要加上 inline 属性。文档中有配置相关的连接。

安装:

npm install gulp-inline-source --save-dev
function buildHtml(cb) {
    console.log('处理html');
    
    return src('src/html/index.html')
    .pipe(inlinesource())
    .pipe(dest('dist/html/'));
}

参考