cố này xảy ra trong Chrome 59.0.3071.115 và Firefox 54.0.1số dòng không đúng - sourcemaps, Webpack 2 nguyên cảo
tôi đã và đang làm rất nhiều nghiên cứu về cố gắng để có được con số chính xác cho dòng mã nguồn nguyên cảo của tôi sử dụng Webpack 2.2.1 và open-browser-webpack-plugin
. Tôi đã cố gắng thiết lập devtool với các tùy chọn khác nhau sau đây:
//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',
Không devtool
tùy chọn trên đây cung cấp số dòng đúng mã nguồn của tôi.
Dưới đây là một ví dụ trong Công cụ F12 Chrome, đây là với Webpack devtool
tùy chọn "eval-source-bản đồ" mà là như nhau cho "rẻ-module-eval-source-đồ" cũng như:
Đó là tập tin mã nguồn đúng, sai số dòng:
Và đây là Firefox với số dòng sai:
Và đây là login.component.ts, các console.log("hello world");
là dòng 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
Và đây là của tôi 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' })
]
}
}
Và đây là tsconfig.json
tôi:
{
"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"
]
}
}
Và đây là npm của tôi package.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"
}
}
Tôi hiểu rằng tôi đang nhìn thấy số dòng của phiên bản tuân thủ các tập tin typescript tôi, login.component.ts
trong Công cụ nhà phát triển Chrome để tôi tự hỏi nếu có một cách để thay đổi cài đặt Webpack tôi sourcemap để xem thực tế số dòng login.component.ts
trước khi biên soạn Typescript?
trang github dành cho webpack, khiến bạn khó xác định xem đó là v1 hay v2. Tôi đã thấy rất nhiều vấn đề. Nhưng nó có thể có liên quan đến v1. Tôi đã thấy ở đây https://medium.com/webpack/the-contributors-guide-to-webpack-part-1-a0410cc82ca4 rằng nó tham chiếu đến https: // github.com/webpack/source-list-map - quote: Loại bỏ và thêm các dòng được hỗ trợ - vậy là v1 hay v2? Tự hỏi nếu bạn đã thử điều đó? – JGFMK
Bạn có chắc 'sourceMap' được đặt thành' true' trong 'tsconfig.json' không? – shotor
@shotor Tôi làm, tôi đã thêm tsconfig.json vào câu hỏi của mình cho bạn để verfiy –