node.js - 如何在 grunt.js 上绑定(bind)服务器和客户端?

标签 node.js gruntjs grunt-express

我是平均堆栈开发的新手。

我有一个项目,需要添加一个通过 grunt 编译的用户界面。

我的服务器从命令node server开始,gruntfile编译我的所有客户端。但我需要我的 grunt 启动服务器并编译所有 View 。 我添加了grunt-express,将其添加到任务中,但是当我进行gruntserve时,它上面没有服务器端。它停留在端口 3000。

如何在 grunt 编译上实现两侧?

Gruntfile.js

"use strict";
var LIVERELOAD_PORT, lrSnippet, mountFolder;

LIVERELOAD_PORT = 35728;

lrSnippet = require("connect-livereload")({
  port: LIVERELOAD_PORT
});

mountFolder = function(connect, dir) {
  return connect["static"](require("path").resolve(dir));
};

module.exports = function(grunt) {
  var yeomanConfig;
  require("load-grunt-tasks")(grunt);
  require("time-grunt")(grunt);
  yeomanConfig = {
    app: "client",
    dist: "dist",
    docs: "documentation"
  };
  try {
    yeomanConfig.app = require("./bower.json").appPath || yeomanConfig.app;
  } catch (_error) {}
  grunt.initConfig({
    yeoman: yeomanConfig,
    serverJS: ["Gruntfile.js", "server.js", "config/**/*.js", "app/**/*.js"],
    watch: {
      express: {
        files: [
          "app/**/*.js",
          "config/{,*/}*.js",
          "server.js",
          "Gruntfile.js"
        ],
        tasks: "express:dev",
        options: {
          nospawn: true
        }
      },
      compass: {
        files: ["<%= yeoman.app %>/styles/**/*.{scss,sass}"],
        tasks: ["compass:server"]
      },
      less: {
        files: ["<%= yeoman.app %>/styles-less/**/*.less"],
        tasks: ["less:server"]
      },
      jade: {
        files: ["<%= yeoman.docs %>/jade/*.jade"],
        tasks: ["jade:docs"]
      },
      livereload: {
        options: {
          livereload: LIVERELOAD_PORT
        },
        files: [
          "<%= yeoman.app %>/index.html",
          "<%= yeoman.app %>/app/**/*.html",
          "<%= yeoman.app %>/app/**/*.js",
          "<%= yeoman.app %>/styles/**/*.scss",
          "<%= yeoman.app %>/styles-less/**/*.less",
          ".tmp/styles/**/*.css",
          "<%= yeoman.app %>/images/**/*.{png,jpg,jpeg,gif,webp,svg}",
          "<%= yeoman.docs %>/jade/*.jade"
        ]
      }
    },
    express: {
      server: {
        options : {
          port: 3000,
          script: 'server.js'
        }
      }
    },
    connect: {
      options: {
        port: 5000,
        hostname: "localhost"
      },
      livereload: {
        options: {
          middleware: function(connect) {
            return [lrSnippet, mountFolder(connect, ".tmp"), mountFolder(connect, yeomanConfig.app)];
          }
        }
      },
      docs: {
        options: {
          middleware: function(connect) {
            return [lrSnippet, mountFolder(connect, yeomanConfig.docs)];
          }
        }
      },
      test: {
        options: {
          middleware: function(connect) {
            return [mountFolder(connect, ".tmp"), mountFolder(connect, "test")];
          }
        }
      },
      dist: {
        options: {
          middleware: function(connect) {
            return [mountFolder(connect, yeomanConfig.dist)];
          }
        }
      }
    },
    open: {
      server: {
        url: "http://localhost:<%= connect.options.port %>"
      }
    },
    clean: {
      dist: {
        files: [
          {
            dot: true,
            src: [".tmp", "<%= yeoman.dist %>/*", "!<%= yeoman.dist %>/.git*"]
          }
        ]
      },
      all: [".tmp", ".sass-cache", "readme.md", "client/bower_components", "documentation/jade", "documentation/config.codekit", "landing/jade", "landing/config.codekit", "node_modules", ".git"],
      server: ".tmp"
    },
    jshint: {
      options: {
        jshintrc: ".jshintrc"
      },
      all: ["Gruntfile.js", "<%= yeoman.app %>/scripts/**/*.js"]
    },
    injector: {
      options: {
        relative: true
      },
      local_dependencies: {
        files: {
          "<%= yeoman.app %>/index.html": [
            "<%= yeoman.app %>/app/**/*.module.js",
            "<%= yeoman.app %>/app/**/*.js",
            "!" + "<%= yeoman.app %>/**/*.spec.js"
          ]
        }
      },
    },
    jade: {
      docs: {
        options: {
          pretty: true
        },
        files: {
          "<%= yeoman.docs %>/index.html": ["<%= yeoman.docs %>/jade/index.jade"]
        }
      }
    },
    compass: {
      options: {
        sassDir: "<%= yeoman.app %>/styles",
        cssDir: ".tmp/styles",
        generatedImagesDir: ".tmp/styles/ui/images/",
        imagesDir: "<%= yeoman.app %>/styles/ui/images/",
        javascriptsDir: "<%= yeoman.app %>/scripts",
        fontsDir: "<%= yeoman.app %>/fonts",
        importPath: "<%= yeoman.app %>/bower_components",
        httpImagesPath: "styles/ui/images/",
        httpGeneratedImagesPath: "styles/ui/images/",
        httpFontsPath: "fonts",
        relativeAssets: true
      },
      dist: {
        options: {
          outputStyle: 'compressed',
          debugInfo: false,
          noLineComments: true
        }
      },
      server: {
        options: {
          debugInfo: true
        }
      },
      forvalidation: {
        options: {
          debugInfo: false,
          noLineComments: false
        }
      }
    },
    less: {
      server: {
        options: {
          strictMath: true,
          dumpLineNumbers: true,
          sourceMap: true,
          sourceMapRootpath: "",
          outputSourceFiles: true
        },
        files: [
          {
            expand: true,
            cwd: "<%= yeoman.app %>/styles-less",
            src: "main.less",
            dest: ".tmp/styles",
            ext: ".css"
          }
        ]
      },
      dist: {
        options: {
          cleancss: true,
          report: 'min'
        },
        files: [
          {
            expand: true,
            cwd: "<%= yeoman.app %>/styles-less",
            src: "main.less",
            dest: ".tmp/styles",
            ext: ".css"
          }
        ]
      }
    },
    useminPrepare: {
      html: "<%= yeoman.app %>/index.html",
      options: {
        dest: "<%= yeoman.dist %>",
        flow: {
          steps: {
            js: ["concat"],
            css: ["cssmin"]
          },
          post: []
        }
      }
    },
    usemin: {
      html: ["<%= yeoman.dist %>/**/*.html", "!<%= yeoman.dist %>/bower_components/**"],
      css: ["<%= yeoman.dist %>/styles/**/*.css"],
      options: {
        dirs: ["<%= yeoman.dist %>"]
      }
    },
    htmlmin: {
      dist: {
        options: {},
        files: [
          {
            expand: true,
            cwd: "<%= yeoman.app %>",
            src: ["*.html", "views/*.html"],
            dest: "<%= yeoman.dist %>"
          }
        ]
      }
    },
    copy: {
      dist: {
        files: [
          {
            expand: true,
            dot: true,
            cwd: "<%= yeoman.app %>",
            dest: "<%= yeoman.dist %>",
            src: [
              "favicon.ico",
              "bower_components/font-awesome/css/*",
              "bower_components/font-awesome/fonts/*",
              "bower_components/weather-icons/css/*",
              "bower_components/weather-icons/fonts/*",
              "bower_components/weather-icons/font/*",
              "fonts/**/*",
              "i18n/**/*",
              "images/**/*",
              "styles/fonts/**/*",
              "styles/img/**/*",
              "styles/ui/images/*",
              "app/**/*.html"
            ]
          }, {
            expand: true,
            cwd: ".tmp",
            dest: "<%= yeoman.dist %>",
            src: ["styles/**", "assets/**"]
          }, {
            expand: true,
            cwd: ".tmp/images",
            dest: "<%= yeoman.dist %>/images",
            src: ["generated/*"]
          }
        ]
      },
      styles: {
        expand: true,
        cwd: "<%= yeoman.app %>/styles",
        dest: ".tmp/styles/",
        src: "**/*.css"
      }
    },
    concurrent: {
      server: ["compass:server", "copy:styles"],
      dist: ["compass:dist", "copy:styles", "htmlmin"],
      lessServer: ["less:server", "copy:styles"],
      lessDist: ["less:dist", "copy:styles", "htmlmin"]
    },
    cssmin: {
      options: {
        keepSpecialComments: '0'
      },
      dist: {}
    },
    concat: {
      options: {
        separator: grunt.util.linefeed + ';' + grunt.util.linefeed
      },
      dist: {}
    },
    uglify: {
      options: {
        mangle: false,
        compress: {
          drop_console: true
        }
      },
      dist: {
        files: {
          "<%= yeoman.dist %>/scripts/app.js": [".tmp/**/*.js", "<%= yeoman.app %>/scripts/**/*.js", "!<%= yeoman.app %>/scripts/vendors/**"]
        }
      }
    }
  });
  grunt.registerTask("docs", function() {
    return grunt.task.run(["jade:docs", "connect:docs", "open", "watch"]);
  });
  grunt.registerTask("server", function(target) {
    if (target === "dist") {
      return grunt.task.run(["serve:dist"]);
    }
    return grunt.task.run(["serve"]);
  });
  grunt.registerTask("serve", function(target) {
    if (target === "dist") {
      return grunt.task.run(["build", "open", "connect:dist:keepalive"]);
    }
    return grunt.task.run(["clean:server", "concurrent:server", "express:server", "connect:livereload", "open", "watch"]);
  });
  grunt.registerTask("build", ["clean:dist", "useminPrepare", "concurrent:dist", "copy:dist", "cssmin", "concat", "uglify", "usemin"]);
  return grunt.registerTask("default", ["serve"]);
};

服务器.js

  var express         = require('express'),
    fs              = require('fs'),
    passport        = require('passport'),
    mongoose        = require('mongoose'),
    http            = require('http'),
    app             = express(),
    server          = require('http').createServer(app),
    config          = require('./config/environment'),
    auth            = require('./config/middlewares/authorization'),
    models_path     = __dirname + '/app/models',
    routes_path     = __dirname + '/app/routes';
fs.readdirSync(models_path).forEach(function (file) {
    require(models_path + '/' + file);
});

app.set('port', process.env.OPENSHIFT_NODEJS_PORT || 3000);
app.set('ipaddr', process.env.OPENSHIFT_NODEJS_IP || 'localhost');

require('./config/express')(app, config, passport);
require('./config/passport')(passport, config);

fs.readdirSync(routes_path).forEach(function (file) {
    require(routes_path + '/' + file)(app, passport, auth);
});

mongoose.connect(config.db);
server.listen(app.get('port'), app.get('ipaddr'), function(){
    console.log('Express server listening on IP/hostname: "' + app.get('ipaddr') + '" and port: "' + app.get('port') + '"');
});

最佳答案

好的。我用grunt-connect-proxy解决了这个问题。我添加了连接任务代理,它终于起作用了。这是 gruntfile 的所有代码:

"use strict";
var LIVERELOAD_PORT, lrSnippet, mountFolder, proxySnippet;

LIVERELOAD_PORT = 35728;

lrSnippet = require("connect-livereload")({
  port: LIVERELOAD_PORT
});

mountFolder = function(connect, dir) {
  return connect["static"](require("path").resolve(dir));
};

module.exports = function(grunt) {
  var yeomanConfig;
  proxySnippet = require("grunt-connect-proxy/lib/utils").proxyRequest;
  require("load-grunt-tasks")(grunt);
  require("time-grunt")(grunt);
  yeomanConfig = {
    app: "client",
    dist: "dist",
    docs: "documentation"
  };
  try {
    yeomanConfig.app = require("./bower.json").appPath || yeomanConfig.app;
  } catch (_error) {}
  grunt.initConfig({
    yeoman: yeomanConfig,
    appFiles: {
      serverJS: ["Gruntfile.js", "server.js", "config/{,*/}*.js", "app/**/*.js"]
    },
    watch: {
      express: {
        files: "<%= appFiles.serverJS %>",
        tasks: "express:dev",
        options: {
          nospawn: true
        }
      },
      compass: {
        files: ["<%= yeoman.app %>/styles/**/*.{scss,sass}"],
        tasks: ["compass:server"]
      },
      less: {
        files: ["<%= yeoman.app %>/styles-less/**/*.less"],
        tasks: ["less:server"]
      },
      jade: {
        files: ["<%= yeoman.docs %>/jade/*.jade"],
        tasks: ["jade:docs"]
      },
      livereload: {
        options: {
          livereload: LIVERELOAD_PORT
        },
        files: [
          "<%= yeoman.app %>/index.html",
          "<%= yeoman.app %>/app/**/*.html",
          "<%= yeoman.app %>/app/**/*.js",
          "<%= yeoman.app %>/styles/**/*.scss",
          "<%= yeoman.app %>/styles-less/**/*.less",
          ".tmp/styles/**/*.css",
          "<%= yeoman.app %>/images/**/*.{png,jpg,jpeg,gif,webp,svg}",
          "<%= yeoman.docs %>/jade/*.jade"
        ]
      }
    },
    express: {
      server: {
        options : {
          port: 3000,
          script: 'server.js'
        }
      }
    },
    connect: {
      options: {
        port: 5000,
        hostname: "localhost"
      },
      proxies: [
        {
          context: "/",
          host: "localhost",
          port: 3000 + "",
          https: false,
          changeOrigin: false
        }
      ],
      livereload: {
        options: {
          middleware: function(connect) {
            return [lrSnippet, mountFolder(connect, ".tmp"), mountFolder(connect, yeomanConfig.app), proxySnippet];
          }
        }
      },
      docs: {
        options: {
          middleware: function(connect) {
            return [lrSnippet, mountFolder(connect, yeomanConfig.docs)];
          }
        }
      },
      test: {
        options: {
          middleware: function(connect) {
            return [mountFolder(connect, ".tmp"), mountFolder(connect, "test")];
          }
        }
      },
      dist: {
        options: {
          middleware: function(connect) {
            return [mountFolder(connect, yeomanConfig.dist)];
          }
        }
      }
    },
    open: {
      server: {
        url: "http://localhost:<%= connect.options.port %>"
      }
    },
    clean: {
      dist: {
        files: [
          {
            dot: true,
            src: [".tmp", "<%= yeoman.dist %>/*", "!<%= yeoman.dist %>/.git*"]
          }
        ]
      },
      all: [".tmp", ".sass-cache", "readme.md", "client/bower_components", "documentation/jade", "documentation/config.codekit", "landing/jade", "landing/config.codekit", "node_modules", ".git"],
      server: ".tmp"
    },
    jshint: {
      options: {
        jshintrc: ".jshintrc"
      },
      all: ["Gruntfile.js", "<%= yeoman.app %>/scripts/**/*.js"]
    },
    injector: {
      options: {
        relative: true
      },
      local_dependencies: {
        files: {
          "<%= yeoman.app %>/index.html": [
            "<%= yeoman.app %>/app/**/*.module.js",
            "<%= yeoman.app %>/app/**/*.js",
            "!" + "<%= yeoman.app %>/**/*.spec.js"
          ]
        }
      },
    },
    jade: {
      docs: {
        options: {
          pretty: true
        },
        files: {
          "<%= yeoman.docs %>/index.html": ["<%= yeoman.docs %>/jade/index.jade"]
        }
      }
    },
    compass: {
      options: {
        sassDir: "<%= yeoman.app %>/styles",
        cssDir: ".tmp/styles",
        generatedImagesDir: ".tmp/styles/ui/images/",
        imagesDir: "<%= yeoman.app %>/styles/ui/images/",
        javascriptsDir: "<%= yeoman.app %>/scripts",
        fontsDir: "<%= yeoman.app %>/fonts",
        importPath: "<%= yeoman.app %>/bower_components",
        httpImagesPath: "styles/ui/images/",
        httpGeneratedImagesPath: "styles/ui/images/",
        httpFontsPath: "fonts",
        relativeAssets: true
      },
      dist: {
        options: {
          outputStyle: 'compressed',
          debugInfo: false,
          noLineComments: true
        }
      },
      server: {
        options: {
          debugInfo: true
        }
      },
      forvalidation: {
        options: {
          debugInfo: false,
          noLineComments: false
        }
      }
    },
    less: {
      server: {
        options: {
          strictMath: true,
          dumpLineNumbers: true,
          sourceMap: true,
          sourceMapRootpath: "",
          outputSourceFiles: true
        },
        files: [
          {
            expand: true,
            cwd: "<%= yeoman.app %>/styles-less",
            src: "main.less",
            dest: ".tmp/styles",
            ext: ".css"
          }
        ]
      },
      dist: {
        options: {
          cleancss: true,
          report: 'min'
        },
        files: [
          {
            expand: true,
            cwd: "<%= yeoman.app %>/styles-less",
            src: "main.less",
            dest: ".tmp/styles",
            ext: ".css"
          }
        ]
      }
    },
    useminPrepare: {
      html: "<%= yeoman.app %>/index.html",
      options: {
        dest: "<%= yeoman.dist %>",
        flow: {
          steps: {
            js: ["concat"],
            css: ["cssmin"]
          },
          post: []
        }
      }
    },
    usemin: {
      html: ["<%= yeoman.dist %>/**/*.html", "!<%= yeoman.dist %>/bower_components/**"],
      css: ["<%= yeoman.dist %>/styles/**/*.css"],
      options: {
        dirs: ["<%= yeoman.dist %>"]
      }
    },
    htmlmin: {
      dist: {
        options: {},
        files: [
          {
            expand: true,
            cwd: "<%= yeoman.app %>",
            src: ["*.html", "views/*.html"],
            dest: "<%= yeoman.dist %>"
          }
        ]
      }
    },
    copy: {
      dist: {
        files: [
          {
            expand: true,
            dot: true,
            cwd: "<%= yeoman.app %>",
            dest: "<%= yeoman.dist %>",
            src: [
              "favicon.ico",
              "bower_components/font-awesome/css/*",
              "bower_components/font-awesome/fonts/*",
              "bower_components/weather-icons/css/*",
              "bower_components/weather-icons/fonts/*",
              "bower_components/weather-icons/font/*",
              "fonts/**/*",
              "i18n/**/*",
              "images/**/*",
              "styles/fonts/**/*",
              "styles/img/**/*",
              "styles/ui/images/*",
              "app/**/*.html"
            ]
          }, {
            expand: true,
            cwd: ".tmp",
            dest: "<%= yeoman.dist %>",
            src: ["styles/**", "assets/**"]
          }, {
            expand: true,
            cwd: ".tmp/images",
            dest: "<%= yeoman.dist %>/images",
            src: ["generated/*"]
          }
        ]
      },
      styles: {
        expand: true,
        cwd: "<%= yeoman.app %>/styles",
        dest: ".tmp/styles/",
        src: "**/*.css"
      }
    },
    concurrent: {
      server: ["compass:server", "copy:styles"],
      dist: ["compass:dist", "copy:styles", "htmlmin"],
      lessServer: ["less:server", "copy:styles"],
      lessDist: ["less:dist", "copy:styles", "htmlmin"]
    },
    cssmin: {
      options: {
        keepSpecialComments: '0'
      },
      dist: {}
    },
    concat: {
      options: {
        separator: grunt.util.linefeed + ';' + grunt.util.linefeed
      },
      dist: {}
    },
    uglify: {
      options: {
        mangle: false,
        compress: {
          drop_console: true
        }
      },
      dist: {
        files: {
          "<%= yeoman.dist %>/scripts/app.js": [".tmp/**/*.js", "<%= yeoman.app %>/scripts/**/*.js", "!<%= yeoman.app %>/scripts/vendors/**"]
        }
      }
    }
  });
  grunt.registerTask("docs", function() {
    return grunt.task.run(["jade:docs", "connect:docs", "open", "watch"]);
  });
  grunt.registerTask("server", function(target) {
    if (target === "dist") {
      return grunt.task.run(["serve:dist"]);
    }
    return grunt.task.run(["serve"]);
  });
  grunt.registerTask("serve", function(target) {
    if (target === "dist") {
      return grunt.task.run(["build", "open", "connect:dist:keepalive"]);
    }
    return grunt.task.run(["clean:server", "concurrent:server", "configureProxies", "express:server", "connect:livereload", "open", "watch"]);
  });
  grunt.registerTask("build", ["clean:dist", "useminPrepare", "concurrent:dist", "copy:dist", "cssmin", "concat", "uglify", "usemin"]);
  return grunt.registerTask("default", ["serve"]);
};

关于node.js - 如何在 grunt.js 上绑定(bind)服务器和客户端?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31044953/

相关文章:

javascript - Node 中的基本回调帮助

node.js - 使用批处理文件安装多个 Node 模块

javascript - watch 和 sass 的不同 grunt 任务

javascript - 使用 Grunt Serve 在本地主机上显示网站?

node.js - 在 Azure 中使用 grunt 发出 ENOTUP 警告

javascript - 让 grun-express 重新启动更改

mysql - 使用 mysql 而不是 redis 来为访问多个实例的客户端共享上下文

javascript - selenium-webdriver的nodejs服务器错误