You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Gulp中BrowserSync任务仅工作一次即卡住,如何修复?

Gulp + BrowserSync 二次修改后进程卡住问题解决

问题描述

使用Gulp搭建前端构建流程,已配置CSS/JS编译任务及文件监听,首次修改JS/SCSS文件时热重载正常,但第二次修改后整个进程卡住。

终端输出

λ gulp
[14:28:47] Using gulpfile ~\OneDrive\Desktop\gulp\GulpLearning\gulpfile.js
[14:28:47] Starting 'default'...
[14:28:47] Starting 'style'...
[14:28:47] Starting 'js'...
[14:28:47] Starting 'browserSyncTask'...
[14:28:47] Starting 'watch'...
[Browsersync] 2 files changed (style.min.css.map, style.min.css)
[14:28:47] Finished 'style' after 223 ms
[Browsersync] 2 files changed (index.min.js.map, index.min.js)
[Browsersync] Reloading Browsers... (buffered 2 events)
[Browsersync] Access URLs:
 -------------------------------------
       Local: http://localhost:3000
    External: http://192.168.56.1:3000
 -------------------------------------
          UI: http://localhost:3001
 UI External: http://localhost:3001
 -------------------------------------
[Browsersync] Serving files from: ./

原代码

// Require packages (from package json)
const gulp = require( 'gulp' );
const rename = require( 'gulp-rename' );
const sass = require('gulp-sass')(require('sass'));
const autoprefixer = require('gulp-autoprefixer');
const sourcemaps = require('gulp-sourcemaps');
const browserify = require('browserify');
const babelify = require('babelify');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');
const uglify = require('gulp-uglify');
const browserSync = require('browser-sync').create();

// CONSTS
const styleSRC = 'src/scss/style.scss';
const styleDIST = './dist/css/';
const styleWATCH = 'src/scss/**/*.scss';

const jsSRC = 'index.js';
const jsFolder = 'src/js/';
const jsDIST = './dist/js/';
const jsWATCH = 'src/js/**/*.js';
const jsFiles = [jsSRC];

/**
 * Gulp task for compile,compress, 
 * create source map and add autoprefixes 
 * for styles.
 * @returns 
 */
function style() {
    return gulp.src( styleSRC )
        .pipe( sourcemaps.init() )
        .pipe( sass({
            errorLogToConsole: true, 
            outputStyle: 'compressed',
        }) )
        .on( 'error', console.error.bind( console ) )
        .pipe( autoprefixer({ 
            overrideBrowserslist: ['last 2 versions', '> 1%'], 
            cascade: false
        }) )
        .pipe( rename( { suffix: ".min" } ) )
        .pipe( sourcemaps.write( './' ) )
        .pipe( gulp.dest( styleDIST ) )
        .pipe( browserSync.stream() );
}
exports.style = style;

/**
 * Gulp task for compile Javascripts
 * @returns 
 */
function js( ){
        return jsFiles.map(function ( entry ){
            // 1. browserify
            return browserify({
                entries: [jsFolder + entry],
            })
            // 2. transform babelify [env] (env is set up in package.json)
            .transform( babelify, {presets: ['@babel/preset-env']} )
            // 3. bundle
            .bundle()
            // 4. source
            .pipe( source( entry ) )
            // 5. rename .min
            .pipe( rename( { extname: ".min.js" } ) )
            // 6. buffer
            .pipe( buffer() )
            // 7. sourcemap
            .pipe( sourcemaps.init({ loadMaps:true }) )
            // 8. uglify
            .pipe( uglify() )
            // 9. write sourcemaps
            .pipe( sourcemaps.write( './' ) )
            // 10. dist
            .pipe( gulp.dest( jsDIST ) )
            .pipe( browserSync.stream() );
        })
}
exports.js = js;

/**
 * Task which start server and 
 * apply hot-reload for changes in FE
 * @returns 
 */
function browserSyncTask(){
    return browserSync.init({
        
        // This works only for localhost if we need specific URL we need specify further
         server: {
           baseDir: "./",
         },
         injectChanges: false // Disable the injectChanges option
    });
}
exports.browserSync = browserSyncTask;

// Watch function for catch changes in files 
function watch(){
    gulp.watch( styleWATCH, style );
    gulp.watch( jsWATCH, js);
}

// Gulp default task for default command in console. ( gulp )
gulp.task('default', gulp.parallel([
    style, 
    js,
    browserSyncTask,
    watch,
]));

问题分析

  1. JS任务返回值错误:js任务通过jsFiles.map返回了一个流数组,但Gulp任务要求返回单个流、Promise或回调函数。返回数组会导致Gulp无法正确跟踪任务完成状态,首次执行可能因异步时序侥幸成功,第二次修改时任务状态混乱引发进程卡住。
  2. BrowserSync初始化返回问题:browserSync.init是异步启动服务器的方法,不需要返回值。返回它会让Gulp认为任务一直处于未完成状态,干扰后续任务触发逻辑。
  3. injectChanges配置不当:设置为false会强制整页刷新而非注入变更,虽非核心问题,但可能加重任务阻塞风险。

解决方案

1. 安装merge-stream合并多流

首先安装merge-stream,用于将多个流合并为单个流:

npm install merge-stream --save-dev

2. 修改JS任务

引入merge-stream,合并流后返回:

const merge = require('merge-stream'); // 新增引入

function js() {
  const streams = jsFiles.map(function (entry) {
    return browserify({
        entries: [jsFolder + entry],
      })
      .transform(babelify, { presets: ['@babel/preset-env'] })
      .bundle()
      .pipe(source(entry))
      .pipe(rename({ extname: ".min.js" }))
      .pipe(buffer())
      .pipe(sourcemaps.init({ loadMaps: true }))
      .pipe(uglify())
      .pipe(sourcemaps.write('./'))
      .pipe(gulp.dest(jsDIST))
      .pipe(browserSync.stream());
  });
  return merge(streams); // 合并流后返回
}

3. 调整BrowserSync任务

移除return,让Gulp正确识别任务完成:

function browserSyncTask() {
  browserSync.init({
    server: {
      baseDir: "./",
    },
    injectChanges: true // 开启注入式刷新,优化体验
  });
}

4. 优化watch任务(可选)

给watch任务加上gulp.series,确保任务触发后正确通知Gulp:

function watch() {
  gulp.watch(styleWATCH, gulp.series(style));
  gulp.watch(jsWATCH, gulp.series(js));
}

5. 修正default任务的parallel参数

gulp.parallel不需要传入数组,直接传任务函数即可:

gulp.task('default', gulp.parallel(style, js, browserSyncTask, watch));

修改后的完整代码

// Require packages (from package json)
const gulp = require( 'gulp' );
const rename = require( 'gulp-rename' );
const sass = require('gulp-sass')(require('sass'));
const autoprefixer = require('gulp-autoprefixer');
const sourcemaps = require('gulp-sourcemaps');
const browserify = require('browserify');
const babelify = require('babelify');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');
const uglify = require('gulp-uglify');
const browserSync = require('browser-sync').create();
const merge = require('merge-stream'); // 新增

// CONSTS
const styleSRC = 'src/scss/style.scss';
const styleDIST = './dist/css/';
const styleWATCH = 'src/scss/**/*.scss';

const jsSRC = 'index.js';
const jsFolder = 'src/js/';
const jsDIST = './dist/js/';
const jsWATCH = 'src/js/**/*.js';
const jsFiles = [jsSRC];

function style() {
    return gulp.src( styleSRC )
        .pipe( sourcemaps.init() )
        .pipe( sass({
            errorLogToConsole: true, 
            outputStyle: 'compressed',
        }) )
        .on( 'error', console.error.bind( console ) )
        .pipe( autoprefixer({ 
            overrideBrowserslist: ['last 2 versions', '> 1%'], 
            cascade: false
        }) )
        .pipe( rename( { suffix: ".min" } ) )
        .pipe( sourcemaps.write( './' ) )
        .pipe( gulp.dest( styleDIST ) )
        .pipe( browserSync.stream() );
}
exports.style = style;

function js() {
  const streams = jsFiles.map(function (entry) {
    return browserify({
        entries: [jsFolder + entry],
      })
      .transform(babelify, { presets: ['@babel/preset-env'] })
      .bundle()
      .pipe(source(entry))
      .pipe(rename({ extname: ".min.js" }))
      .pipe(buffer())
      .pipe(sourcemaps.init({ loadMaps: true }))
      .pipe(uglify())
      .pipe(sourcemaps.write('./'))
      .pipe(gulp.dest(jsDIST))
      .pipe(browserSync.stream());
  });
  return merge(streams);
}
exports.js = js;

function browserSyncTask() {
  browserSync.init({
    server: {
      baseDir: "./",
    },
    injectChanges: true
  });
}
exports.browserSync = browserSyncTask;

function watch() {
  gulp.watch(styleWATCH, gulp.series(style));
  gulp.watch(jsWATCH, gulp.series(js));
}

gulp.task('default', gulp.parallel(style, js, browserSyncTask, watch));

验证

执行gulp命令后,多次修改JS/SCSS文件,进程不会再卡住,热重载功能正常工作。

内容的提问来源于stack exchange,提问作者Young L.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 05:37:59