grunt serve:并发:服务器因警告而中止

Posted

技术标签:

【中文标题】grunt serve:并发:服务器因警告而中止【英文标题】:grunt serve: concurrent:server aborts due to warnings 【发布时间】:2014-08-14 10:45:08 【问题描述】:

我的项目突然停止使用 grunt。不幸的是,我有一段时间没有将我的更改提交到 git 中,所以我不知道有什么不同。

当我运行 grunt server --verbose 时,我得到以下输出(... 以上的所有内容都以 OK 传递):

...
Running "wiredep" task

Running "wiredep:app" (wiredep) task
Verifying property wiredep.app exists in config...OK
Files: app/index.html
Verifying property wiredep.app.src exists in config...OK

Running "wiredep:sass" (wiredep) task
Verifying property wiredep.sass exists in config...OK
Files: app/styles/analyzer.scss, app/styles/colors.scss, app/styles/login.scss, app/styles/main.scss, app/styles/shared.scss, app/styles/styles.scss, app/styles/tagsinput.scss
Verifying property wiredep.sass.src exists in config...OK

Running "concurrent:server" (concurrent) task
Verifying property concurrent.server exists in config...OK
Files: [no src] -> server
Options: limit=2
    Warning:  Use --force to continue.

        Aborted due to warnings.


Execution Time (2014-06-24 08:34:05 UTC)
loading tasks        8ms  0%
serve                2ms  0%
clean:server        10ms  0%
wiredep:app        242ms  ▇▇▇▇▇▇▇ 4%
wiredep:sass        17ms  0%
concurrent:server   5.3s  ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 95%
Total 5.6s

所以,当尝试执行任务concurrent:server 时,grunt 中止。在这个任务中,compass:server 任务被执行(见下面的Gruntfile.js)。所以,它一定与指南针有关,但我不确定Files: [no src] -> server这行是否可以为问题提供更多提示。

这是我的Gruntfile.js

// Generated on 2014-06-16 using generator-angular 0.9.0-1
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/,*/*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) 

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Configurable paths for the application
  var appConfig = 
    app: require('./bower.json').appPath || 'app',
    dist: 'dist'
  ;

  // Define the configuration for all the tasks
  grunt.initConfig(

    // Project settings
    yeoman: appConfig,

    // Watches files for changes and runs tasks based on the changed files
    watch: 
      bower: 
        files: ['bower.json'],
        tasks: ['wiredep']
      ,
      js: 
        files: ['<%= yeoman.app %>/scripts/,*/*.js'],
        tasks: [],
        options: 
          livereload: '<%= connect.options.livereload %>'
        
      ,
      jsTest: 
        files: ['test/spec/,*/*.js'],
        tasks: ['newer:jshint:test', 'newer:jshint:all', 'karma']
      ,
      compass: 
        files: ['<%= yeoman.app %>/styles/,*/*.scss,sass'],
        tasks: ['compass:server', 'autoprefixer'],
        options: 
            spawn: false,
        
      ,
      gruntfile: 
        files: ['Gruntfile.js']
      ,
      livereload: 
        options: 
          livereload: '<%= connect.options.livereload %>'
        ,
        files: [
          '<%= yeoman.app %>/,*/*.html',
          '<%= yeoman.app %>/scripts/directives/**/*.html',
          '.tmp/styles/,*/*.css',
          '<%= yeoman.app %>/images/,*/*.png,jpg,jpeg,gif,webp,svg'
        ]
      
    ,

    // The actual grunt server settings
    connect: 
      options: 
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35729
      ,
      livereload: 
        options: 
          open: false,
          middleware: function (connect) 
            return [
              connect.static('.tmp'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];
          
        
      ,
      test: 
        options: 
          port: 9001,
          middleware: function (connect) 
            return [
              connect.static('.tmp'),
              connect.static('test'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];
          
        
      ,
      dist: 
        options: 
          open: false,
          base: '<%= yeoman.dist %>'
        
      
    ,

    // Make sure code styles are up to par and there are no obvious mistakes
    jshint: 
      options: 
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      ,
      all: 
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/,*/*.js'
        ]
      ,
      test: 
        options: 
          jshintrc: 'test/.jshintrc'
        ,
        src: ['test/spec/,*/*.js']
      
    ,

    // Empties folders to start fresh
    clean: 
      dist: 
        files: [
          dot: true,
          src: [
            '.tmp',
            '<%= yeoman.dist %>/,*/*',
            '!<%= yeoman.dist %>/.git*'
          ]
        ]
      ,
      server: '.tmp'
    ,

    // Add vendor prefixed styles
    autoprefixer: 
      options: 
        browsers: ['last 1 version']
      ,
      dist: 
        files: [
          expand: true,
          cwd: '.tmp/styles/',
          src: ',*/*.css',
          dest: '.tmp/styles/'
        ]
      
    ,

    // Automatically inject Bower components into the app
    wiredep: 
      app: 
        src: ['<%= yeoman.app %>/index.html'],
        ignorePath: new RegExp('^<%= yeoman.app %>/|../')
      ,
      sass: 
        src: ['<%= yeoman.app %>/styles/,*/*.scss,sass'],
        ignorePath: /(\.\.\/)1,2bower_components\//
      
    ,

    // Compiles Sass to CSS and generates necessary files if requested
    compass: 
      options: 
        sassDir: '<%= yeoman.app %>/styles',
        cssDir: '.tmp/styles',
        generatedImagesDir: '.tmp/images/generated',
        imagesDir: '<%= yeoman.app %>/images',
        javascriptsDir: '<%= yeoman.app %>/scripts',
        fontsDir: '<%= yeoman.app %>/styles/fonts',
        importPath: './bower_components',
        httpImagesPath: '/images',
        httpGeneratedImagesPath: '/images/generated',
        httpFontsPath: '/styles/fonts',
        relativeAssets: false,
        assetCacheBuster: false,
        raw: 'Sass::Script::Number.precision = 10\n'
      ,
      dist: 
        options: 
          generatedImagesDir: '<%= yeoman.dist %>/images/generated'
        
      ,
      server: 
        options: 
          debugInfo: true
        
      
    ,

    // Renames files for browser caching purposes
    filerev: 
      dist: 
        src: [
          '<%= yeoman.dist %>/scripts/,*/*.js',
          '<%= yeoman.dist %>/styles/,*/*.css',
          '<%= yeoman.dist %>/images/,*/*.png,jpg,jpeg,gif,webp,svg',
          '<%= yeoman.dist %>/styles/fonts/*'
        ]
      
    ,

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: 
      html: '<%= yeoman.app %>/index.html',
      options: 
        dest: '<%= yeoman.dist %>',
        flow: 
          html: 
            steps: 
              js: ['concat', 'uglifyjs'],
              css: ['cssmin']
            ,
            post: 
          
        
      
    ,

    // Performs rewrites based on filerev and the useminPrepare configuration
    usemin: 
      html: ['<%= yeoman.dist %>/,*/*.html'],
      css: ['<%= yeoman.dist %>/styles/,*/*.css'],
      options: 
        assetsDirs: ['<%= yeoman.dist %>','<%= yeoman.dist %>/images']
      
    ,

    // The following *-min tasks will produce minified files in the dist folder
    // By default, your `index.html`'s <!-- Usemin block --> will take care of
    // minification. These next options are pre-configured if you do not wish
    // to use the Usemin blocks.
    // cssmin: 
    //   dist: 
    //     files: 
    //       '<%= yeoman.dist %>/styles/main.css': [
    //         '.tmp/styles/,*/*.css'
    //       ]
    //     
    //   
    // ,
    // uglify: 
    //   dist: 
    //     files: 
    //       '<%= yeoman.dist %>/scripts/scripts.js': [
    //         '<%= yeoman.dist %>/scripts/scripts.js'
    //       ]
    //     
    //   
    // ,
    // concat: 
    //   dist: 
    // ,

    imagemin: 
      dist: 
        files: [
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: ',*/*.png,jpg,jpeg,gif',
          dest: '<%= yeoman.dist %>/images'
        ]
      
    ,

    svgmin: 
      dist: 
        files: [
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: ',*/*.svg',
          dest: '<%= yeoman.dist %>/images'
        ]
      
    ,

    htmlmin: 
      dist: 
        options: 
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true,
          removeOptionalTags: true
        ,
        files: [
          expand: true,
          cwd: '<%= yeoman.dist %>',
          src: ['*.html', 'views/,*/*.html'],
          dest: '<%= yeoman.dist %>'
        ]
      
    ,

    // ngmin tries to make the code safe for minification automatically by
    // using the Angular long form for dependency injection. It doesn't work on
    // things like resolve or inject so those have to be done manually.
    ngmin: 
      dist: 
        files: [
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: '*.js',
          dest: '.tmp/concat/scripts'
        ]
      
    ,

    // Replace Google CDN references
    cdnify: 
      dist: 
        html: ['<%= yeoman.dist %>/*.html']
      
    ,

    // Copies remaining files to places other tasks can use
    copy: 
      dist: 
        files: [
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.dist %>',
          src: [
            '*.ico,png,txt',
            '.htaccess',
            '*.html',
            'views/,*/*.html',
            'images/,*/*.webp',
            'fonts/*'
          ]
        , 
          expand: true,
          cwd: '.tmp/images',
          dest: '<%= yeoman.dist %>/images',
          src: ['generated/*']
        , 
          expand: true,
          cwd: '.',
          src: 'bower_components/bootstrap-sass-official/vendor/assets/fonts/bootstrap/*',
          dest: '<%= yeoman.dist %>'
        ]
      ,
      styles: 
        expand: true,
        cwd: '<%= yeoman.app %>/styles',
        dest: '.tmp/styles/',
        src: ',*/*.css'
      
    ,

    // Run some tasks in parallel to speed up the build process
    concurrent: 
      server: [
        'compass:server'
      ],
      test: [
        'compass'
      ],
      dist: [
        'compass:dist',
        'imagemin',
        'svgmin'
      ]
    ,

    // Test settings
    karma: 
      unit: 
        configFile: 'test/karma.conf.js',
        singleRun: false
      
    
  );


  grunt.loadNpmTasks('grunt-sass');

  grunt.registerTask('serve', 'Compile then start a connect web server', function (target) 
    if (target === 'dist') 
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    
    grunt.task.run([
      'clean:server',
      'wiredep',
      'concurrent:server',
      'autoprefixer',
      'connect:livereload',
      'watch'
    ]);
  );

  grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) 
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run(['serve:' + target]);
  );

  grunt.registerTask('test', [
    'clean:server',
    'autoprefixer',
    'connect:test',
    'karma'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'wiredep',
    'useminPrepare',
    'concurrent:dist',
    'autoprefixer',
    'concat',
    'ngmin',
    'copy:dist',
    'cdnify',
    'cssmin',
    'uglify',
    'filerev',
    'usemin',
    'htmlmin'
  ]);

  grunt.registerTask('default', [
    'newer:jshint',
    'test',
    'build'
  ]);
;

我使用 yo 角度生成器生成了项目。这是我的环境:

node -v: v0.10.25 ruby -v: ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin13.0] yo -v: 1.1.2

gem list:

* 本地宝石 *

大十进制 (1.2.4) 捆绑器(1.6.2) 捆绑器卸载 (1.0.2) 矮胖的_png (1.3.1) 指南针 (0.12.6) 可执行挂钩 (1.3.1) fssm (0.2.10) 宝石包装器 (1.2.4) io 控制台 (0.4.2) json (1.8.1) 迷你测试(4.7.5) 心理 (2.0.5) 耙子 (10.1.0) rdoc (4.1.0) rubygems 捆绑器 (1.4.3) 转速 (1.11.3.9) 萨斯(3.3.8,3.2.19) 测试单元 (2.1.2.0)

grunt --verison: grunt-cli v0.1.13, grunt v0.4.5

Mac OS X 10.9

这是我的package.json


  "name": "project1",
  "version": "0.0.0",
  "dependencies": ,
  "devDependencies": 
    "grunt": "^0.4.1",
    "grunt-autoprefixer": "^0.7.3",
    "grunt-concurrent": "^0.5.0",
    "grunt-contrib-clean": "^0.5.0",
    "grunt-contrib-coffee": "^0.10.1",
    "grunt-contrib-compass": "~0.8.0",
    "grunt-contrib-concat": "^0.4.0",
    "grunt-contrib-connect": "^0.7.1",
    "grunt-contrib-copy": "^0.5.0",
    "grunt-contrib-cssmin": "^0.9.0",
    "grunt-contrib-htmlmin": "^0.3.0",
    "grunt-contrib-imagemin": "^0.7.0",
    "grunt-contrib-jshint": "^0.10.0",
    "grunt-contrib-uglify": "^0.4.0",
    "grunt-contrib-watch": "^0.6.1",
    "grunt-filerev": "^0.2.1",
    "grunt-google-cdn": "^0.4.0",
    "grunt-newer": "^0.7.0",
    "grunt-ngmin": "^0.0.3",
    "grunt-svgmin": "^0.4.0",
    "grunt-usemin": "^2.1.1",
    "grunt-wiredep": "^1.7.0",
    "jshint-stylish": "^0.2.0",
    "load-grunt-tasks": "^0.4.0",
    "time-grunt": "^0.3.1",
    "coffee-script": "~1.7.1",
    "grunt-karma": "~0.8.3",
    "karma-phantomjs-launcher": "~0.1.4",
    "karma": "~0.12.16",
    "karma-jasmine": "~0.1.5",
    "karma-coffee-preprocessor": "~0.2.1",
    "karma-chrome-launcher": "~0.1.4",
    "karma-script-launcher": "~0.1.0",
    "karma-firefox-launcher": "~0.1.3",
    "karma-safari-launcher": "~0.1.1",
    "karma-ng-html2js-preprocessor": "~0.1.0",
    "karma-junit-reporter": "~0.2.2",
    "grunt-ng-constant": "~0.5.0",
    "grunt-bowercopy": "~1.0.1",
    "karma-coverage": "~0.2.4",
    "grunt-protractor-runner": "~1.0.0",
    "karma-jasmine-given": "~0.1.1",
    "grunt-sass": "~0.13.1"
  ,
  "engines": 
    "node": ">=0.10.0"
  ,
  "scripts": 
    "test": "grunt test"
  

这是我的bower.json


  "name": "project1",
  "version": "0.0.0",
  "dependencies": 
    "angular": "1.3.0-beta.11",
    "json3": "~3.3.1",
    "es5-shim": "~3.1.0",
    "jquery": "~1.11.1",
    "bootstrap-sass-official": "~3.1.1",
    "bootstrap": "~3.1.1",
    "angular-resource": "1.3.0-beta.11",
    "angular-cookies": "1.3.0-beta.11",
    "angular-sanitize": "1.3.0-beta.11",
    "angular-animate": "1.3.0-beta.11",
    "angular-touch": "1.3.0-beta.11",
    "angular-route": "1.3.0-beta.11",
    "font-awesome": "~4.1",
    "underscore": "~1.6.0"
  ,
  "devDependencies": 
    "angular-mocks": "1.3.0-beta.11",
    "angular-scenario": "1.3.0-beta.11"
  ,
  "appPath": "app"

【问题讨论】:

【参考方案1】:

实际上,我的 SCSS 没有语法错误,这是因为我全局安装了 compass (npm -g),而它需要作为 Ruby gem 安装:

gem install compass

【讨论】:

【参考方案2】:

我不是专家,但我发现一旦本地服务器运行,它将允许 scss 或其他任何内容中出现 lint 错误,然后一旦您停止服务器并尝试重新启动,它将给出此错误,直到您修复 scss 错误。您可以使用 grunt check 然后解决它们并重试。 9/10 这就是我的服务器无法重启的原因。

【讨论】:

【参考方案3】:

它是在 SCSS 文件中导入的。试试

grunt serve --force

这可能会强制构建过程继续,即使您的 SCSS 无法编译。最终结果是您将启动 grunt 服务器,它会告诉您构建过程失败的确切位置。

【讨论】:

【参考方案4】:

愚蠢的我!

对于遇到相同问题的任何人:

我的 SCSS 文件中有一些导入错误。在 grunt 的实时重新加载期间,它会告诉您有问题。但是在grunt serve 的启动过程中,它只是中断并且什么也没告诉你。因此,请检查您的 SCSS 文件的导入和语法。

【讨论】:

我也有同样的问题。我在一台机器上工作,而在另一台机器上失败(由于警告)。有什么建议吗? 要隔离问题,请检查您是否有一些 SCSS 问题。注释掉每一个 SCSS 并启动你的服务器。如果服务器没有启动,则应该与 SCSS 语法无关。如果它确实启动了,请逐步在每个 SCSS 语句中进行注释。现在您的文件上会出现正确的错误/警告,您可以修复它。 它与 sass gem 版本有关。我们在 3.4.0 版本中遇到了编译问题,而 3.3.14 则没有。 运行grunt compass查看编译失败的地方。 我升级了我的 grunt-concurrent 1.0.0->2.1.1,现在错误在 grunt server-start 上传播。

以上是关于grunt serve:并发:服务器因警告而中止的主要内容,如果未能解决你的问题,请参考以下文章

警告:connect.static 不是函数使用 --force 继续

Azure 媒体服务 - 视频播放因损坏而中止... (0x20400003)

上下文因超时而取消但计算未中止?

kmeans pyspark org.apache.spark.SparkException:作业因阶段失败而中止

如何在 WebStorm 中调试从 grunt serve 开始的 Angular 网站?

测试执行因源自 Hammerhead 的请求管道的问题而随机中止(Testcafe e2e 测试)