gulp 的基本运用及使用过程中遇到的坑

作者: tww844475003 分类: 前端开发 发布时间: 2021-08-04 21:26

JavaScript 和 Gulpfile

Gulp 允许你使用现有 JavaScript 知识来书写 gulpfile 文件,或者利用你所掌握的 gulpfile 经验来书写普通的 JavaScript 代码。根目录 gulpfile.js 的作用,在运行 gulp 命令时会被自动加载。

  • 坑一(也是很多初学 node.js 项目经常犯的错误)

npm init 初始化项目时,name 的填写,不少同学为了方便记忆,喜欢直接就用模块名。如 gulp、react、vue,这样就会出现问题,比如 gulp 这个就是 gulp 项目的内部关键字,package.json name 定义了这个名称,这个项目就无法正常安装 gulp 模块了。

npm ERR! code ENOSELF
npm ERR! Refusing to install package with name “gulp” under a package
npm ERR! also called “gulp”. Did you name your project the same
npm ERR! as the dependency you’re installing?
npm ERR!
npm ERR! For more information, see:
npm ERR! https://docs.npmjs.com/cli/install#limitations-of-npms-install-algorithm

npm ERR! A complete log of this run can be found in:

  • 坑二 (gulp 新版本,老的语法不兼容)

很多初接触的同学,在学习 gulp 过程中,喜欢在百度上搜索一些 gulp 入门教程来学着做,包括笔者自己。这经常会遇到一些问题,明明按照资料一步一步完成,还是出现意想不到的问题。其中有不少问题产生原因就是因为网上资料上用的是旧版本,而学习的同学安装的是高版本。由于版本升级问题,就极有可能造成某些语法的变化,不兼容问题道理。下面我们来一起实践一个简单的示例:

// 复制文件
const gulp = require('gulp');
const paths = {
  html: './*.html'
}

gulp.task('copyHtml', async function() {
  await gulp.src(paths.html)
    .pipe(gulp.dest('dist/'))
})

gulp.task('default', ['copyHtml'])

这个代码在 gulp3 上没有任何问题,如果同学安装的是最新版 gulp4 的话就会报错了。

{ AssertionError [ERR_ASSERTION]: Task function must be specified
at Gulp.set as _setTask
at Gulp.task (D:\node\gulp\node_modules\undertaker\lib\task.js:13:8)
at Object. (D:\node\gulp\gulpfile.js:12:6)
at Module._compile (internal/modules/cjs/loader.js:701:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
at Module.load (internal/modules/cjs/loader.js:600:32)
at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
at Function.Module._load (internal/modules/cjs/loader.js:531:3)
at Module.require (internal/modules/cjs/loader.js:637:17)
at require (internal/modules/cjs/helpers.js:22:18)
generatedMessage: false,
name: ‘AssertionError [ERR_ASSERTION]’,
code: ‘ERR_ASSERTION’,
actual: false,
expected: true,
operator: ‘==’ }

那如何解决这个问题了,gulp4 提供了更好的方法

  • gulp.series 用于串行(顺序)执行
  • gulp.parallel 用于并行执行

串行

// 复制文件
const gulp = require('gulp');
const paths = {
  html: './*.html'
}

gulp.task('copyHtml', async function() {
  await gulp.src(paths.html)
    .pipe(gulp.dest('dist/'))
})


gulp.task('default', gulp.series('copyHtml'))

并行

// 复制文件
const gulp = require('gulp');
const paths = {
  html: './*.html',
  css: './*.css'
}

gulp.task('copyHtml', async function() {
  await gulp.src(paths.html)
    .pipe(gulp.dest('dist/'))
})

gulp.task('copyCss', async function() {
  await gulp.src(paths.css)
    .pipe(gulp.dest('dist/'))
})

gulp.task('default', gulp.parallel('copyHtml', 'copyCss'))

接着我们用 gulp 构建一个适用前端切图的项目(支持 Less、es6 语法、js混肴、css压缩、实时预览刷新页面)

const gulp = require('gulp');
const less = require('gulp-less');
const cleanCss = require('gulp-clean-css');
const connect = require('gulp-connect');
const htmlbeautify = require('gulp-html-beautify');
const clean = require('gulp-clean');
const fileInclude = require('gulp-file-include');

const paths = {
  html: './html/**/*.html',
  css: './html/css/**/*.css',
  img: './html/images/**',
  js: './html/js/**',
  less: './html/less/**/*.less'
}

// 清理目标文件夹/文件
gulp.task('clean', async function() {
  await gulp.src('dist')
    .pipe(clean({
      force: true
    }))
});

// 格式化 html
gulp.task('htmlbeautify', async function() {
  await gulp.src('dist/**/*.html')
    .pipe(htmlbeautify({
      indent_size: 2,
      indent_char: ' '
    }))
    .pipe(gulp.dest('dist/'))
});

// 复制html
gulp.task('copyHtml', async function() {
  await gulp.src(paths.html)
    .pipe(fileInclude({
      prefix: '@@',
      basepath: '@file'
    }))
    .pipe(gulp.dest('dist/'))
    .pipe(connect.reload());
});

// 复制css
gulp.task('copyCss', async function() {
  await gulp.src(paths.css)
    .pipe(gulp.dest('dist/css/'))
    .pipe(connect.reload());
});

// 复制img
gulp.task('copyImg', async function() {
  await gulp.src(paths.img)
    .pipe(gulp.dest('dist/images/'))
    .pipe(connect.reload());
});

// 复制js
gulp.task('copyJs', async function() {
  await gulp.src(paths.js)
    .pipe(gulp.dest('dist/js/'))
    .pipe(connect.reload());
});

// less css 预处理
gulp.task('less', async function() {
  await gulp.src(paths.less)
    .pipe(less())
    .pipe(cleanCss())
    .pipe(gulp.dest('dist/css/'))
    .pipe(connect.reload());
});

// connect任务
gulp.task('connect', async function () {
  await connect.server({
    root: 'dist',
    livereload: true
  });
});

// watch任务
gulp.task('watch', async function () {
  await gulp.watch(paths.html, gulp.series('copyHtml'));
  await gulp.watch(paths.css, gulp.series('copyCss'));
  await gulp.watch(paths.img, gulp.series('copyImg'));
  await gulp.watch(paths.js, gulp.series('copyJs'));
  await gulp.watch(paths.less, gulp.series('less'));
});

gulp.task('copy', gulp.parallel('copyHtml', 'copyCss', 'copyImg', 'copyJs'));
gulp.task('default', gulp.series('copy', 'less', 'connect', 'watch'));

js 支持 es6 语法待更新 ……

下面我来一起接着完成上次未完成的工作,项目接入 babel 转换 es6 新特性语法。

安装依赖:

npm install --save-dev gulp-babel @babel/core @babel/preset-env webpack-stream

gulp 新建 babel 任务

const gulp = require('gulp');
const less = require('gulp-less');
const cleanCss = require('gulp-clean-css');
const connect = require('gulp-connect');
const htmlbeautify = require('gulp-html-beautify');
const clean = require('gulp-clean');
const fileInclude = require('gulp-file-include');
const babel = require('gulp-babel');
const webpack = require('webpack-stream');

const paths = {
  html: './html/**/*.html',
  css: './html/css/**/*.css',
  img: './html/images/**',
  js: './html/js/**',
  less: './html/less/**/*.less',
  es6: './html/es6/main.js'
}

// 清理目标文件夹/文件
gulp.task('clean', function() {
  return gulp.src('dist')
    .pipe(clean({
      force: true
    }))
});

// 格式化 html
gulp.task('htmlbeautify', function() {
  return gulp.src('dist/**/*.html')
    .pipe(htmlbeautify({
      indent_size: 2,
      indent_char: ' '
    }))
    .pipe(gulp.dest('dist/'))
});

// 复制html
gulp.task('copyHtml', function() {
  return gulp.src(paths.html)
    .pipe(fileInclude({
      prefix: '@@',
      basepath: '@file'
    }))
    .pipe(gulp.dest('dist/'))
    .pipe(connect.reload());
});

// 复制css
gulp.task('copyCss', function() {
  return gulp.src(paths.css)
    .pipe(gulp.dest('dist/css/'))
    .pipe(connect.reload());
});

// 复制img
gulp.task('copyImg', function() {
  return gulp.src(paths.img)
    .pipe(gulp.dest('dist/images/'))
    .pipe(connect.reload());
});

// 复制js
gulp.task('copyJs', function() {
  return gulp.src(paths.js)
    .pipe(gulp.dest('dist/js/'))
    .pipe(connect.reload());
});

// less css 预处理
gulp.task('less', function() {
  return gulp.src(paths.less)
    .pipe(less())
    .pipe(cleanCss())
    .pipe(gulp.dest('dist/css/'))
    .pipe(connect.reload());
});

// babel
gulp.task('babel', function() {
  return gulp.src(paths.es6)
    .pipe(babel({
      presets: ['@babel/preset-env']
    }))
    .pipe(webpack({
      output: {
        filename: 'main.js'
      }
    }))
    .pipe(gulp.dest('dist/js/'))
    .pipe(connect.reload());
})

// connect任务
gulp.task('connect', function () {
  return connect.server({
    root: 'dist',
    livereload: true
  });
});

// watch任务
gulp.task('watch', function () {
  gulp.watch(paths.html, gulp.series('copyHtml'));
  gulp.watch(paths.css, gulp.series('copyCss'));
  gulp.watch(paths.img, gulp.series('copyImg'));
  gulp.watch(paths.js, gulp.series('copyJs'));
  gulp.watch(paths.less, gulp.series('less'));
  gulp.watch(paths.es6, gulp.series('babel'));
});

gulp.task('copy', gulp.parallel('copyHtml', 'copyCss', 'copyImg', 'copyJs'));
gulp.task('default', gulp.series('copy', 'babel', 'less', 'connect', 'watch'));

更为详细的分解请移步,这里笔者就直接上源码了。

前端开发那点事
微信公众号搜索“前端开发那点事”

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注