Gulp自动化构建流程从入门到放弃再到真香的踩坑总结

采涵 前端 阅读 1,754
赞 24 收藏
二维码
手机扫码查看
反馈

gulp-sass编译失败,折腾了两天才搞定

最近重构一个老项目,想把以前手动合并的CSS改成用Gulp自动化处理。本来以为是个很简单的事情,结果被gulp-sass给坑惨了。项目里有个复杂的样式文件,用了大量嵌套和变量,一跑gulp任务就报错,而且错误信息还特别模糊。

Gulp自动化构建流程从入门到放弃再到真香的踩坑总结

最开始我以为是sass语法有问题,检查了好几遍都找不到原因。后来试了各种版本组合,node-sass、dart-sass、gulp-sass各种搭配都试了一遍,问题依然存在。

各种尝试都没用

这里我踩了好几个坑:

  • 先升级node版本,以为是环境问题
  • 重新安装gulp和gulp-sass,清空npm cache
  • 换用webpack的sass-loader,结果更麻烦
  • 手动写了一个简单的sass编译脚本,还是不行

折腾了两天,每次都是同样的错误:TypeError: this.getOptions is not a function。Google了一圈发现很多人都遇到这个问题,但解决方案五花八门,很多都不适用。

终于找到根因

后来仔细看了下package.json才发现问题所在。我的gulp版本是4.x,而gulp-sass的版本太新了,新版的gulp-sass内部依赖了webpack相关的模块,在gulp环境下会有兼容性问题。

还有一个问题是我的sass文件里用了一些高级特性,比如函数嵌套、复杂的@if判断,这些在老版本的sass编译器里处理起来会有问题。

最终解决方案

经过反复测试,最终确定了这个配置,亲测有效:

const gulp = require('gulp');
const sass = require('gulp-sass')(require('sass'));
const sourcemaps = require('gulp-sourcemaps');
const autoprefixer = require('gulp-autoprefixer');
const cleanCSS = require('gulp-clean-css');

// sass编译配置
gulp.task('sass', function() {
    return gulp.src('./src/scss/**/*.scss')
        .pipe(sourcemaps.init())
        .pipe(sass({
            outputStyle: 'expanded',
            includePaths: ['./node_modules']
        }).on('error', sass.logError))
        .pipe(autoprefixer({
            cascade: false,
            grid: true
        }))
        .pipe(cleanCSS({
            level: 2
        }))
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest('./dist/css'));
});

// 监听文件变化
gulp.task('watch', function() {
    gulp.watch('./src/scss/**/*.scss', gulp.series('sass'));
});

gulp.task('default', gulp.parallel('sass', 'watch'));

关键改动在这两行:

const sass = require('gulp-sass')(require('sass'));

以前的老写法是这样的:

const sass = require('gulp-sass');

新版的gulp-sass需要显式传入sass编译器,这样就不会有依赖冲突的问题了。

package.json依赖配置

对应的package.json配置也很重要:

{
  "devDependencies": {
    "gulp": "^4.0.2",
    "gulp-sass": "^5.1.0", 
    "sass": "^1.54.0",
    "gulp-autoprefixer": "^8.0.0",
    "gulp-clean-css": "^4.3.0",
    "gulp-sourcemaps": "^3.0.0"
  }
}

这里要注意sass的版本不能太新,不然和gulp-sass的兼容性会有问题。我测试下来1.54.0这个版本比较稳定。

错误处理很重要

还有一个坑就是错误处理。之前的配置如果sass编译出错,整个gulp任务就停了,而且看不到具体的错误位置。现在加上了错误监听:

.on('error', sass.logError)

这样即使编译出错,也能看到具体哪个文件哪一行有问题,排查起来方便多了。

性能优化考虑

项目比较大,编译速度也是个问题。我加了几个优化:

  • sourcemaps只在开发环境启用
  • 使用gulp-cache缓存未变化的文件
  • 并行执行多个编译任务

完整的优化版本:

const gulp = require('gulp');
const sass = require('gulp-sass')(require('sass'));
const sourcemaps = require('gulp-sourcemaps');
const autoprefixer = require('gulp-autoprefixer');
const cleanCSS = require('gulp-clean-css');
const cache = require('gulp-cache');

const isDev = process.env.NODE_ENV !== 'production';

gulp.task('sass', function() {
    return gulp.src('./src/scss/**/*.scss')
        .pipe(isDev ? sourcemaps.init() : gulp.util.noop())
        .pipe(cache(sass({
            outputStyle: isDev ? 'expanded' : 'compressed',
            includePaths: ['./node_modules']
        }).on('error', sass.logError)))
        .pipe(autoprefixer({
            cascade: false,
            grid: true
        }))
        .pipe(isDev ? gulp.util.noop() : cleanCSS({
            level: 2
        }))
        .pipe(isDev ? sourcemaps.write('.') : gulp.dest('./dist/css'))
        .pipe(gulp.dest('./dist/css'));
});

运行命令配置

最后在package.json里加几个常用的命令:

{
  "scripts": {
    "dev": "NODE_ENV=development gulp",
    "build": "NODE_ENV=production gulp sass",
    "watch": "NODE_ENV=development gulp watch"
  }
}

改完之后总算能正常编译了,虽然偶尔还会有一些小警告,但不影响正常使用。这次踩坑让我对gulp的sass处理有了更深的认识,以后遇到类似问题就知道怎么快速定位了。

以上是我踩坑后的总结,如果你也遇到了类似的问题,希望能帮到你。如果有更好的方案欢迎评论区交流。

本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。
发表评论

暂无评论