javascript angular google-chrome typescript webpack

javascript - Números de línea incorrectos-Sourcemaps, Webpack 2 Typescript



angular google-chrome (1)

Es un problema conocido que muchas personas enfrentaron anteriormente en el pasado sin resolución. Parece que el depurador de Chrome tiene algunos errores abiertos con respecto al comportamiento similar:

https://github.com/karma-runner/karma/issues/1141

o

https://groups.google.com/forum/#!topic/google-chrome-developer-tools/n4A0WemZhHc

o

Chrome parece informar una línea incorrecta por error

Sugiero en tales casos, use Firefox.

Este problema ocurre en Chrome 59.0.3071.115 y Firefox 54.0.1

He estado investigando mucho para tratar de obtener los números de línea correctos para mi código fuente de Typescript usando Webpack 2.2.1 y el open-browser-webpack-plugin . He intentado configurar devtool para las siguientes opciones diferentes:

//https://webpack.js.org/configuration/devtool/ //devtool: ''eval'', //eval vert fast but line numbers will be wrong //devtool: ''eval-source-map'', //starts off slow but fast rebuild speed and correct line numbers, supposedly, not correct line numbers for typescript //devtool: ''source-map'', //very slow, for production, most accurate source maps //devtool: ''cheap-module-eval-source-map'', //devtool: ''inline-source-map'',

Ninguna opción devtool anterior proporciona el número de línea correcto de mi código fuente.

Aquí hay un ejemplo en Chrome F12 Tools, esto es con la opción devtool de devtool "eval-source-map" que es lo mismo para "cheap-module-eval-source-map" también:

Ese es el archivo de código fuente correcto, número de línea incorrecta:

Y aquí está Firefox con un número de línea incorrecto:

Y aquí está login.component.ts, console.log console.log("hello world"); es la línea 32:

import { Component, OnDestroy, OnInit, EventEmitter, Input, Output } from ''@angular/core''; import { Http } from ''@angular/http''; import { ActivatedRoute, Router } from ''@angular/router''; import { FormBuilder, FormGroup, FormControl, Validators, AbstractControl, ValidatorFn, FormArray } from ''@angular/forms''; import { User } from ''./login.interface''; import ''rxjs/add/operator/debounceTime''; //Services import { LoginService } from ''./login.service''; import { SpinnerService } from ''../core/spinner/spinner.service''; import { DialogService } from "ng2-bootstrap-modal"; import { LoginModal } from ''./modal/modal.component''; //Animations import { pageTransition } from ''../animation''; import { Animate } from ''../core/const/animation.const''; @Component({ templateUrl: ''./login.component.html'', animations: [pageTransition] }) export class LoginComponent implements OnInit { ///////////////// // CONSTRUCTOR // ///////////////// constructor( private spinnerService: SpinnerService, private router: Router, public http: Http, private _fb: FormBuilder, private loginService: LoginService, private dialogService: DialogService) { console.log("hello world"); } ////////////// // BINDINGS // ////////////// //////////// // FIELDS // //////////// private state: string = Animate.in; private background = require(''../assets/images/construction-background.jpg''); private loginForm: FormGroup; //Username private userNameMessage: any[]; private userNameError: boolean = false; //password private passwordMessage: any[]; private passwordError: boolean; private NgbModalOptions = { closeByClickingOutside: true, size: "lg" }; //ANY VALIDATION OBJECT private validationMessages = { // Note: these validation messages could easily be populated with a backend server. required: ''This field is required'', pattern: ''please enter a valid email address'', minlength: ''I need more letters please'' } ngOnInit() { //view animations. this.state = (this.state === Animate.in ? Animate.out : Animate.in); // Creating the Form Group and Form Controls this.loginForm = this._fb.group({ userName: ['''', [Validators.minLength(2)]], password: ['''', [Validators.required]], }); const userNameControl = this.loginForm.get(''userName''); const passwordControl = this.loginForm.get(''password''); //Watch User Name Control userNameControl.valueChanges .debounceTime(1000) .subscribe(value => this.userNameMessage = this.setMessage(userNameControl, this.validationMessages, ''userNameError'')); //Watch Password Control passwordControl.valueChanges .debounceTime(1000) .subscribe(value => this.passwordMessage = this.setMessage(passwordControl, this.validationMessages, ''passwordError'')); // Mock Spinner wait time - http call starts this.spinnerService.display(true); //http call ends setTimeout(() => { this.spinnerService.display(false); }, 2000); }//end ngOnInit // LOGIN login(resp: boolean): void { if (resp) { this.router.navigate([''dashboard'']); } else { this.dialogService.addDialog(LoginModal, { message: ''Username or password are not correct'' }, this.NgbModalOptions); } } //CLEAR FORM AFTER SUMBIT CLICK clearData() { const loginForm = this.loginForm; loginForm.setValue({ userName: '''', password: '''' }) } //LOGIN CLICK loginClick() { // GET USER NAME AND PASSWORD TO SEND TO SERVER. let body = { ''username'': this.loginForm.get(''userName'').value, ''password'': this.loginForm.get(''password'').value }; this.loginService.validateUser(body).subscribe( // do something with response , just logging in and routing for now. response => this.login(true), error => this.login(error) ); //Clear Form this.clearData(); } // SET FIELD CONTROLL ERROR MESSAGES setMessage(control: AbstractControl, messages: any, errorId: string): any[] { //clear left over messages. If is has one this[errorId] = false; if ((control.touched || control.dirty) && control.errors) { this[errorId] = true; // Maps error type to string and returns array of appropriate error messages. return Object.keys(control.errors).map(key => messages[key]) } } }// End Class

Y aquí está mi webpack.config.js :

var webpack = require(''webpack''), htmlPlugin = require(''html-webpack-plugin''), revPlugin = require(''webpack-rev-replace-plugin''), config = require(''./build.config.json''), path = require(''path''), extendedDefinePlugin = require(''extended-define-webpack-plugin''), webpackDelPlugin = require(''webpack-del-plugin''); OpenBrowserPlugin = require(''open-browser-webpack-plugin''); output = require(''to-string-loader''); //Note : in package.json the last variable (dev) is the param delivered to this function { env: ''dev'' }. module.exports = function (env) { // Note : ''__dirname'' is the root file path. const ROOT_DIR = path.resolve(__dirname); const DIST_DIR = path.join(ROOT_DIR, config.dist); console.log(__dirname); // If no env make it the dev if (!env) { env = {}; env.env = config.envDev; } console.log(''env configuration'', env.env); // this takes path variables from build.config.json and builds it with given env var appConfigPath = config.envs + config.appConfig.replace(''{env}'', env.env); return { entry: config.src + config.entry,//main.ts output: { path: path.join(__dirname, config.dist), filename: config.buildjs, sourceMapFilename: config.buildjsmap }, module: { loaders: [ { test: //.html$/, use: ''raw-loader'' }, { test: //.css$/, use: ''raw-loader'' }, { test: //.ts$/, loaders: [ ''ts-loader'', ''angular2-template-loader'', ''angular-router-loader''] }, { test: //.scss$/, exclude: /node_modules/, loaders: [''style-loader'', ''css-loader'', ''sass-loader''], }, //For images. { test: //.(jpe?g|png|gif|svg)$/i, loader: "file-loader?name=app/assets/images/[name].[ext]"}, { test: //.(ttf|eot|woff|woff2)$/, loader: ''file-loader'' }, ] }, //https://webpack.js.org/configuration/devtool/ //devtool: ''eval'', //eval vert fast but line numbers will be wrong devtool: ''eval-source-map'', //starts off slow but fast rebuild speed and correct line numbers, supposedly, not correct line numbers for typescript //devtool: ''source-map'', //very slow, for production, most accurate source maps //devtool: ''cheap-module-eval-source-map'', //devtool: ''inline-source-map'', // resolve: { extensions: [''.js'', ''.ts'',''.scss'',''.css''] }, plugins: [ new htmlPlugin({ template: config.src + config.index }), // Not in use from what I can see - Nick July 9th 2017 new revPlugin({ cwd: config.src, files: ''**/*.html'', outputPageName: function (filename) { return filename; }, modifyReved: function (filename) { return filename.replace(/(//style//|//script//)/, '''') } }), //Makes AppConfig variable available in the application code. new extendedDefinePlugin({ AppConfig: require(appConfigPath) }), //Usefull if you need remove some files or folders before compilation processes. //currently not used (no dist file). new webpackDelPlugin({match: path.join(DIST_DIR, ''*.*'')}), //opens browser after compilation. new OpenBrowserPlugin({ url: ''http://localhost:8080'' }) ] } }

Y aquí está mi tsconfig.json :

{ "compilerOptions": { "target": "es5", //most browsers currently understand this version of Javascript "experimentalDecorators": true, //Angular2 uses Component,Injectable etc "emitDecoratorMetadata": true, //Required for Angular2 to use the metadata in our components "sourceMap": true, "types": [ "node", "jasmine" ] } }

Y aquí está mi package.json npm.json

{ "name": "angular2-starter", "version": "0.1.0", "scripts": { "test": "karma start", "build-dev": "webpack --progress --colors --env.env dev", "build-qa": "webpack --progress --colors --env.env qa", "build-prd": "webpack -p --progress --colors --env.env prd", "postinstall": "typings install", "serve": "webpack-dev-server --inline --progress --colors --env.env dev" }, "dependencies": { "@angular/animations": "^4.1.3", "@angular/common": "^4.1.3", "@angular/compiler": "^4.1.3", "@angular/compiler-cli": "^4.1.3", "@angular/core": "^4.1.3", "@angular/forms": "^4.1.3", "@angular/http": "^4.1.3", "@angular/material": "^2.0.0-beta.5", "@angular/platform-browser": "^4.1.3", "@angular/platform-browser-dynamic": "^4.1.3", "@angular/platform-server": "^4.1.3", "@angular/router": "^4.1.3", "@angular/cdk": "^2.0.0-beta.8", "@ng-bootstrap/ng-bootstrap": "^1.0.0-alpha.26", "angular2-jwt": "^0.2.3", "angular2-wizard": "^0.3.0", "bootstrap": "^4.0.0-alpha.6", "core-js": "2.4.1", "font-awesome": "^4.7.0", "hammerjs": "^2.0.8", "ng2-bootstrap-modal": "1.0.1", "ng2-drag-drop": "^2.0.1", "reflect-metadata": "0.1.8", "rxjs": "^5.0.0-beta.12", "systemjs": "0.19.40", "typescript": "^2.4.1", "zone.js": "^0.7.8" }, "devDependencies": { "@types/jasmine": "^2.5.53", "angular-router-loader": "^0.6.0", "angular2-router-loader": "^0.3.5", "angular2-template-loader": "^0.6.2", "css-loader": "^0.27.3", "extended-define-webpack-plugin": "^0.1.3", "file-loader": "^0.10.1", "html-webpack-plugin": "^2.28.0", "install": "^0.8.7", "jasmine": "^2.6.0", "karma": "^1.7.0", "karma-sourcemap-loader": "^0.3.7", "karma-webpack": "^2.0.4", "node-sass": "^4.5.0", "npm": "^4.4.1", "open-browser-webpack-plugin": "0.0.5", "path": "^0.12.7", "prepack-webpack-plugin": "^1.1.0", "raw-loader": "^0.5.1", "sass-loader": "^6.0.3", "style-loader": "^0.13.2", "to-string-loader": "^1.1.5", "ts-loader": "^2.0.1", "typings": "^2.1.0", "webpack": "^2.2.1", "webpack-del-plugin": "0.0.1", "webpack-dev-server": "^2.4.1", "webpack-merge": "^4.1.0", "webpack-rev-replace-plugin": "^0.1.1" } }

Entiendo que estoy viendo el número de línea de la versión login.component.ts de mi archivo login.component.ts , login.component.ts en las Herramientas para desarrolladores de Chrome, así que me pregunto si hay una forma de cambiar la configuración del mapa de fuentes de mi Webpack para ver el número de línea real de login.component.ts de login.component.ts antes de la compilación de login.component.ts ?