观察、重新编译和重启

11

我一直在寻找一个使用Grunt的watch模块在文件更改时执行几个步骤的示例。我还没有找到任何好的例子,所以如果有人能指导我正确的方向,那就太棒了。

  1. 构建TypeScript项目(我已经做到了这一点)
  2. 监视目录以进行文件更改(这也可以)
  3. 在运行编译后的JavaScript的同时,仍然监视文件更改的情况下启动Node进程。(通过Grunt最好的方式是什么?watch模块似乎可以成功启动重新编译任务)
  4. 当文件更改时,停止其他正在运行的进程、重新编译并在完成后重新启动。继续监视更改(对于这一点没有任何想法——重新启动是棘手的部分!)

我尝试了几种不同的方法,例如使用Grunt启动子进程,但我总是会遇到悬挂进程、锁定端口、错误的STDIO或其他问题。我希望如果Grunt进程退出,子进程可以被杀死。

有没有一个好的处理方式?谢谢!


看起来这可能是期望的一个不错解决方案,但没有使用grunt... https://www.npmjs.com/package/gulp-connect - Synoon
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - jocull
4个回答

10
我的简单实现是通过在package.json中的配置使用nodemon来监视src文件夹中的ts文件变化,并使用tsc编译typescript/ts文件... package.json中的"scripts"部分:
  "scripts": {
     "debug": "nodemon -e js,ts --watch src --exec \"yarn run build:ts && yarn run start:app\"",
     "build:ts": "node_modules/.bin/tsc",
     "start:app": "node dist/app"
  },

tsconfig.json

{
   "compilerOptions": {
     "target": "es6",
     "module": "commonjs",
     "outDir": "dist"
   },
   "include": [
     "src/**/*.ts"
   ],
   "exclude": [
     "node_modules"
   ]
}

5
这是我的解决方案。我使用nodemon来监视src文件夹,并在检测到更改时触发构建循环和节点调用。它使用npm run dev:src命令调用。这是一个相当简单的解决方案: package.json
"scripts": {
  ...
  "build:dev": "npm run clean && npm run compile:dev",
  "clean": "rimraf dist",
  "compile": "babel src -d dist && npm run copy:static",
  "compile:dev": "babel src -d dist -s && npm run copy:static",
  "copy:static": "cp -R src/static dist/static",
  "dev:dist": "npm run build:dev && node --inspect dist/server.js",
  "dev:src": "npm run build:dev && nodemon --watch src --exec npm run dev:dist",
}

编辑:

这是一种过时的技术选择。我知道这可能超出了范围,但我建议采用类似这样的webpack/rollup方法:

"scripts": {
    "start": "node build/index.js",
    "build": "webpack",
    "dev": "cross-env NODE_ENV=development nodemon --watch src --watch package.* --watch .env --watch .env.development --watch .env.development.local --watch webpack.config.js --exec \"npm run build && node build/index.js\"",
    "lint": "eslint ./src --ext .js && prettier --check ./src/**/*{.js,.mjs}",
    "lint:fix": "eslint ./src --ext .js --fix && prettier --write ./src/**/*{.js,.mjs}",
  },

或者强烈考虑Kent C. Dodds的方法:
"scripts": {
    "start": "node .",
    "build": "babel --delete-dir-on-start --out-dir dist --copy-files --ignore \"**/__tests__/**,**/__mocks__/**\" --no-copy-ignored src"
  }

https://kentcdodds.com/blog/how-i-structure-express-apps


你能分享带有这个配置的github项目吗? - Lewis Nakao
1
哎呀,我不再有访问那段代码的权限了。 我也不建议使用它 - 我建议切换到基于webpack/rollup的方法或者直接使用最新版本的node。 - Philippe Hebert

1
使用类似Nodemon这样的工具:https://www.npmjs.com/package/nodemon,还有一些Grunt / Gulp插件可供选择。当文件发生变化时,Nodemon会停止运行并重新启动应用程序。

Grunt的nodemon包显示不受支持,所以我不确定。你能将其暂停,重新编译,然后重新启动吗?我遇到了一个问题,nodemon锁定了文件夹并防止重新编译。 - jocull
我也没有遇到“端口被阻止”的问题。它对我来说很干净地运行……而且我在Windows和Mac上都使用它,我猜你的系统可能有所不同¯_(ツ)_/¯。 - basarat

0

最终我不得不使用子进程自己实现。Nodemon会阻止监视发生,并且不足以处理重新编译步骤。

这是我的Gruntfile,使用了watch、copy、clean和TypeScript模块。

var loader = require('load-grunt-tasks');
var cp = require('child_process');

module.exports = function (grunt) {
  loader(grunt, {});

  grunt.initConfig({
    tsFiles: [
      "**/*.ts",
      "!typings/**/*.ts",
      "typings/tsd.d.ts",
      "!build/**/*.ts",
      "!bower_modules/**/*.ts",
      "!node_modules/**/*.ts",
    ],
    buildDir: 'build/',

    clean: {
      build: '<%= buildDir %>'
    },

    ts: {
      build: {
        src: [
          "**/*.ts",
          "!typings/**/*.ts",
          "typings/tsd.d.ts",
          "!build/**/*.ts",
          "!bower_modules/**/*.ts",
          "!node_modules/**/*.ts",
        ],
        outDir: '<%= buildDir %>',
        options: {
          "target": 'ES5',
          "module": 'commonjs',
          "sourceMap": true,
        }
      }
    },

    copy: {
      build: {
        expand: true,
        cwd: './',
        src: [
          '*.json',
          'config/**/*.json',
          'test/**/*.js'
        ],
        dest: '<%= buildDir %>/',
        filter: 'isFile'
      }
    },

    watch: {
      run: {
        files: [
          '**/*.ts',
          '**/*.js',
          '**/*.json',
          '!.*/**/*.*',
          '!build/**/*.*',
          '!node_modules/**/*.*',
          '!logs/**/*.*'
        ],
        tasks: ['server-stop', 'build', 'server-restart'],
        options: {
          spawn: false
        }
      }
    }
  });

  var child = null;
  function killChild(){
    if (child){
      child.kill();
      child.disconnect();
      child = null;
    }    
  }

  grunt.registerTask('server-stop', 'Stop the dev server', function(){
    killChild();
  });

  grunt.registerTask('server-restart', 'Stop the dev server', function(){
    killChild();
    child = cp.fork('./build/app.js');
  });

  grunt.registerTask('build', ['copy', 'ts']);
  grunt.registerTask('rebuild', ['clean', 'build']);
  grunt.registerTask('default', ['rebuild']);
  grunt.registerTask('run', ['default', 'server-restart', 'watch']);
};

你还在使用这个方法吗?或者你已经找到了更好的方法?我也想尝试这个,但是由于缺乏相关信息,我认为我可能做错了什么。 - Kavi Siegel
1
@KaviSiegel 我仍在使用这个或其某种衍生物。它有点粗糙,子进程中的崩溃有时会导致它无法重新启动。 - jocull

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接