angular-fullstack / generator-angular-fullstack

Yeoman generator for an Angular app with an Express server
https://awk34.gitbook.io/generator-angular-fullstack
6.12k stars 1.23k forks source link

WebStorm debugging. #1900

Open Stalso opened 8 years ago

Stalso commented 8 years ago

Hello. I am .Net developer and new in NodeJs. The first point to start learning this - your template. And the first thing I wanted to have - debugging code in some IDE, because I am used to IDE (Visual studio). Debugging in WebTools is awfull. Your server code is written using ES6 and Babel. And I have invested some time to make it debuggable in IDE. I have chosen Webstorm (last version) for it.

I have generated project with such options

Item Version
generator-angular-fullstack 3.7.2
Node 5.10.1
npm 3.8.3
Operating System Windows 8.1
Item Answer
Transpiler TypeScript
Markup Jade
CSS LESS
Router ui-router
Build Tool Gulp
Client Tests Mocha
DB MongoDB
Auth Y

Neither WebStrom nor VisualStudio Code cannot debug ES6. That's why I need to transpile server in ES5 during development. I did it in .tmpsrv folder. For that reason I have added new variable to paths object in gulpfile.babel.js:

 tmpsrv: '.tmpsrv'

Also I have created some gulp tasks and added them in gulpfile.babel.js :

// web storm tasks

// transiles server in ES5 to .tmpsrv folder
gulp.task('transpile:server:ide', () => {
    return gulp.src(_.union(paths.server.scripts, paths.server.json))
        .pipe(transpileServer())
        .pipe(gulp.dest(`${paths.tmpsrv}/${serverPath}`));
});

// clean .tmpsrv folder
gulp.task('clean:tmpsrv', () => del(['.tmpsrv/**/*'], {dot: true}));

// set 'developmentIde' variable
gulp.task('env:ide', () => {
    plugins.env({
        vars: {NODE_ENV: 'developmentIde'}
    });
});

// prepares all stuff for debugging in WebStorm
gulp.task('serve:ide', cb => {
    runSequence(['clean:tmp','clean:tmpsrv', 'constant', 'env:all','env:ide', 'typings'],
        ['lint:scripts', 'inject', 'jade'],
        ['wiredep:client'],
        ['transpile:client', 'styles','transpile:server:ide'],

        cb);
});

Now, if I fire gulp:serve:ide task, .tmpfolder with transpiled client and .tmpsrv folder with transpiled server and source maps wiil be created (but you SHOULD NOT do it right now). index.js of the server in this folder will be startup file for debugging session in WebStrom ( this IDE can debug ES6 with source maps, if we start debugging session for ES5 code and put breakpoints in ES6 code). As you see I will start my server from .tmpsrv folder during debugging, that is why I need to modify some paths and settings in projects.

First of all I go to server/config/environment/index.js and add such code in allobject:

// Root path of transpiled server
transpiledRoot: path.normalize(__dirname + '/../../../..'),

Than I add file 'developmentIde.js' in server/config/express.js' folder and copy contents ofserver/config/environment/development.js' there.

Then I go to `server/config/express.js' and replace this:

app.set('views', config.root + '/server/views');

with this:

if ('development' === env || 'test' === env)
{
  app.set('views', config.root + '/server/views');
}
else
{
  app.set('views', config.transpiledRoot + '/server/views');
}

Also I replace this:

app.set('appPath', path.join(config.root, 'client'));

with this:

if('developmentIde' === env){
  app.set('appPath', path.join(config.transpiledRoot, 'client'));
} else{
  app.set('appPath', path.join(config.root, 'client'));
}

Also I replace this:

if ('development' === env) {
  app.use(require('connect-livereload')({
    ignore: [
      /^\/api\/(.*)/,
      /\.js(\?.*)?$/, /\.css(\?.*)?$/, /\.svg(\?.*)?$/, /\.ico(\?.*)?$/, /\.woff(\?.*)?$/,
      /\.png(\?.*)?$/, /\.jpg(\?.*)?$/, /\.jpeg(\?.*)?$/, /\.gif(\?.*)?$/, /\.pdf(\?.*)?$/
    ]
  }));
}

with this:

if ('development' === env || 'developmentIde' === env) {
  app.use(require('connect-livereload')({
    ignore: [
      /^\/api\/(.*)/,
      /\.js(\?.*)?$/, /\.css(\?.*)?$/, /\.svg(\?.*)?$/, /\.ico(\?.*)?$/, /\.woff(\?.*)?$/,
      /\.png(\?.*)?$/, /\.jpg(\?.*)?$/, /\.jpeg(\?.*)?$/, /\.gif(\?.*)?$/, /\.pdf(\?.*)?$/
    ]
  }));
}

Also I replace this:

if ('development' === env || 'test' === env) {
  app.use(express.static(path.join(config.root, '.tmp')));
  app.use(express.static(app.get('appPath')));
  app.use(morgan('dev'));
  app.use(errorHandler()); // Error handler - has to be last
}

with this:

if ('development' === env || 'test' === env || 'developmentIde' === env) {
  if('developmentIde' === env){
    app.use(express.static(path.join(config.transpiledRoot, '.tmp')));
  } else{
    app.use(express.static(path.join(config.root, '.tmp')));
  }

  app.use(express.static(app.get('appPath')));
  app.use(morgan('dev'));
  app.use(errorHandler()); // Error handler - has to be last
}

All this code makes my debugging server to find client content in right places. Also I need to transpile server for every code change in server scripts. That's why I go back to gulp file and replace modify code in watchtask. I replace this:

plugins.watch(_.union(paths.server.scripts, testFiles))
    .pipe(plugins.plumber())
    .pipe(lintServerScripts())
    .pipe(plugins.livereload());

with this:

plugins.watch(_.union(paths.server.scripts, testFiles, paths.server.json))
    .pipe(plugins.plumber())
    .pipe(transpileServer())
    .pipe(gulp.dest(`${paths.tmpsrv}/${serverPath}`))
    .pipe(lintServerScripts())
    .pipe(plugins.livereload());

Finally I have to create Run Configuration, where start up file will be .tmpsrv\server\index.js, startup task will be gulp:serve:ide (or you can run it manually). Also you have to set NODE_ENV=developmentIde for this run configuration. And during debug session gulp:watch task should work. Everything is working. Now you can debug this in WebStorm. But I am newbee in all that NodeJS and gulp stuff. Can somebody look at my modifications and propose better solutions? It is really a lot of things to modify. Maybe somebody will use it

Awk34 commented 8 years ago

Have you tried using the gulp serve:debug task, which runs node-inspector? I know you said "Debugging in WebTools is awfull", but node-inspector uses the same interface as the Chrome dev tools to debug your server-side code

Stalso commented 8 years ago

Yes, I have tried. And I do no not like them. Restart of the server is really slow. Debugging is inconvenient and not visual. Switching between three tabs (editor, browser with client and webtools) is annoying. I have only two monitors 😊

akcasoy commented 8 years ago

It is really frustrating for me too, having a project which you cannot debug..
should "grunt serve:debug" also run the debugger? I think i have tried that but did not really work... in terminal appears at the end sth like "open localhost:8080/debug?port=5858 to debug".. but nothing is really running there..

Awk34 commented 8 years ago

@akcasoy grunt serve:debug && gulp serve:debug both use node-inspector, an environment-agnostic server debugging tool that uses the Chrome dev tools to debug your server. You can open the URL it tells you to to use the chrome debug tools on your server.

The generator isn't set up to support built-in WebStorm debugging out-of-the-box, but I'd be happy to have people help investigate how to get everything set up, and make a docs section about it.

Stalso commented 8 years ago

@Awk34 , everything I wrote in start post is working. Feel free to use, if nobody have better solution.

Awk34 commented 8 years ago

@Stalso while it works for you, I feel like there's a simpler solution. I use WebStorm personally, so I'll try to investigate when I get some time.

Stalso commented 8 years ago

It will be cool. The reason, why I have created the isuue is to ind a better way to establish debugging