Gulp自动化构建流程从入门到放弃再到真香的踩坑总结
gulp-sass编译失败,折腾了两天才搞定
最近重构一个老项目,想把以前手动合并的CSS改成用Gulp自动化处理。本来以为是个很简单的事情,结果被gulp-sass给坑惨了。项目里有个复杂的样式文件,用了大量嵌套和变量,一跑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处理有了更深的认识,以后遇到类似问题就知道怎么快速定位了。
以上是我踩坑后的总结,如果你也遇到了类似的问题,希望能帮到你。如果有更好的方案欢迎评论区交流。

暂无评论