我目前在我的代码中到处都有这个JS语句:
window.console && console.log("Foo");
我想知道这是否代价高昂,或者在生产中是否有任何负面影响。
我可以自由离开客户端登录,还是应该离开?
编辑:最后,我认为我(以及其他任何人?)能够提出的最好的论点是,通过留下记录消息,在服务器和客户端之间传输的额外数据可能是不可忽略的。如果要完全优化生产代码,则必须删除日志记录以减少发送给客户端的javascript的大小。
答案 0 :(得分:47)
另一种解决这个问题的方法是在未定义控制台对象时将其“存根”出来,这样在没有控制台的情境中就不会抛出任何错误,即
if (!window.console) {
var noOp = function(){}; // no-op function
console = {
log: noOp,
warn: noOp,
error: noOp
}
}
你明白了...在控制台的各种实现上定义了很多函数,所以你可以将它们全部或仅使用你所使用的函数(例如,如果你只使用console.log
和从未使用console.profile
,console.time
等...)
这对我来说是一个更好的选择,而不是在每次通话前添加条件,或者不使用它们。
另见:Is it a bad idea to leave "console.log()" calls in your producton JavaScript code?
答案 1 :(得分:33)
您应该不将开发工具添加到生产页面。
回答另一个问题:代码不能产生负面影响:
window.console
未定义,console
将评估为false
console.log("Foo")
会在定义时将消息打印到控制台(前提是该页面不会被非功能覆盖console.log
)。答案 2 :(得分:27)
如果您使用此缩小器,则可以设置drop_console
option:
传递true以放弃对console。*函数的调用
所以我建议保留console.log
次调用,因为它们是代码库中最棘手的部分。
答案 3 :(得分:16)
如果缩小是构建过程的一部分,您可以使用它去除调试代码,如此处使用Google闭包编译器所述:Exclude debug JavaScript code during minification
if (DEBUG) {
console.log("Won't be logged if compiled with --define='DEBUG=false'")
}
如果使用高级优化进行编译,则此代码甚至会被识别为已死并完全删除
答案 4 :(得分:5)
是。 console.log将在不支持它的浏览器中抛出异常(将找不到控制台对象)。
答案 5 :(得分:4)
通常是的,在生产代码中公开日志消息并不是一个好主意。
理想情况下,您应该在部署之前使用构建脚本删除此类日志消息;但是很多(大多数)人不使用构建过程(包括我)。
这是我最近一直用来解决这个难题的一些代码的简短摘要。它修复了旧IE中由未定义的console
引起的错误,以及在“development_mode”中禁用日志记录。
// fn to add blank (noOp) function for all console methods
var addConsoleNoOp = function (window) {
var names = ["log", "debug", "info", "warn", "error",
"assert", "dir", "dirxml", "group", "groupEnd", "time",
"timeEnd", "count", "trace", "profile", "profileEnd"],
i, l = names.length,
noOp = function () {};
window.console = {};
for (i = 0; i < l; i = i + 1) {
window.console[names[i]] = noOp;
}
};
// call addConsoleNoOp() if console is undefined or if in production
if (!window.console || !window.development_mode) {
this.addConsoleNoOp(window);
}
我很确定我从SO上的另一个答案中取了上述addConsoleNoOp
f'n的大部分内容,但现在找不到。如果我找到它,我会稍后添加一个参考。
编辑:不是我想到的帖子,但这是一个类似的方法:https://github.com/paulmillr/console-polyfill/blob/master/index.js
答案 6 :(得分:2)
var AppLogger = (function () {
var debug = false;
var AppLogger = function (isDebug) {
debug = isDebug;
}
AppLogger.conlog = function (data) {
if (window.console && debug) {
console.log(data);
}
}
AppLogger.prototype = {
conlog: function (data) {
if (window.console && debug) {
console.log(data);
}
}
};
return AppLogger;
})();
<强> 用法:的强>
var debugMode=true;
var appLogger = new AppLogger(debugMode);
appLogger.conlog('test');
答案 7 :(得分:1)
是的,使用console.log
进行javascript调试的良好做法,但需要从生产服务器中删除它,或者如果需要可以在生产服务器上添加一些关键点考虑:
**var isDebugEnabled="Get boolean value from Configuration file to check whether debug is enabled or not".**
if (window.console && isDebugEnabled) {
console.log("Debug Message");
}
以上代码块必须在任何地方用于记录,以便首先验证当前浏览器是否支持控制台以及是否启用了调试。
isDebugEnabled
必须根据我们的设置为真或假 环境。
答案 8 :(得分:1)
想法:记录对象阻止它们被垃圾收集。
console.log
,则可以通过DevTools控制台的引用访问这些对象。您可以通过记录对象,对其进行变更以及发现旧消息反映对象的后续更改来检查它。这只是一个想法:我检查了第1点和第2点,但没有检查3点。
如果您想为了客户端故障排除或其他需要而保留日志,那么:
['log', 'warn', 'error'].forEach( (meth) => {
const _meth = window.console[meth].bind(console);
window.console[meth] = function(...args) { _meth(...args.map((arg) => '' + arg)) }
});
答案 9 :(得分:0)
我基本上用一个知道运行代码的地方覆盖console.log函数。因此,我可以像往常一样继续使用console.log。它会自动知道我处于dev / qa模式或生产中。还有一种强迫它的方法。 这是一个工作小提琴。 http://jsfiddle.net/bsurela/Zneek/
这是一个片段,因为发布jsfiddle
的人会暗示堆栈溢出 log:function(obj)
{
if(window.location.hostname === domainName)
{
if(window.myLogger.force === true)
{
window.myLogger.original.apply(this,arguments);
}
}else {
window.myLogger.original.apply(this,arguments);
}
},
答案 10 :(得分:0)
我知道这是一个很老的问题,而且一段时间内没有太多活动。我只是想添加自己想出的解决方案,对我来说似乎很好用。
CryptAcquireCertificatePrivateKey
然后我通常会在这样的脚本中创建一个函数,或者您可以在全局脚本中使它可用:
/**
* Logger For Console Logging
*/
Global.loggingEnabled = true;
Global.logMode = 'all';
Global.log = (mode, string) => {
if(Global.loggingEnabled){
switch(mode){
case 'debug':
if(Global.logMode == 'debug' || Global.logMode == 'all'){
console.log('Debug: '+JSON.stringify(string));
}
break;
case 'error':
if(Global.logMode == 'error' || Global.logMode == 'all'){
console.log('Error: '+JSON.stringify(string));
}
break;
case 'info':
if(Global.logMode == 'info' || Global.logMode == 'all'){
console.log('Info: '+JSON.stringify(string));
}
break;
}
}
}
然后我就这样使用它而不是console.log:
Something.fail = (message_string, data, error_type, function_name, line_number) => {
try{
if(error_type == undefined){
error_type = 'error';
}
Global.showErrorMessage(message_string, true);
Global.spinner(100, false);
Global.log(error_type, function_name);
Global.log(error_type, 'Line: '+line_number);
Global.log(error_type, 'Error: '+data);
}catch(error){
if(is_global){
Global.spinner(100, false);
Global.log('error', 'Error: '+error);
Global.log('error', 'Undefined Error...');
}else{
console.log('Error:'+error);
console.log('Global Not Loaded!');
}
}
}
答案 11 :(得分:0)
如果使用正确的工具(例如parcel
/ webpack
完成工作流,则不再麻烦,因为使用production
构建console.log
被丢弃。甚至早在几年前,Gulp
/ Grunt
就可以实现自动化。
许多现代框架,例如Angular
,React
,Svelte
,Vue.js
都是现成的设置。基本上,只要部署正确的构建即可,您无需执行任何操作,即production
而不是development
仍将具有console.log
的构建。
答案 12 :(得分:0)
不要把事情复杂化!我个人在开发过程中一直都在使用 console.log,这样可以节省时间。对于生产,我只添加一行代码(在我的例子中的“生产配置文件”中)禁用所有日志:
window.console.log = () => {};
完成;) 这个猴子修补 window.console 并用空函数替换 log 函数,禁用输出。
在大多数情况下,这对我来说已经足够了。如果您想“一路”并从代码中删除 console.logs 以减小包大小,则必须更改 js 的捆绑方式(例如,使用 minifier 或其他内容删除 console.logs)
此外,我认为您实际上可以强调将它们留在其中 - 即使在生产中也是如此。它对普通用户没有任何改变,但可以真正加快理解奇怪的“异国浏览器”问题。它不像可能包含关键信息的后端日志。无论如何,这一切都在前端,不显示日志消息,因为您害怕透露用户不应该知道的内容实际上只是“默默无闻的安全性”,并且应该让您思考为什么这些信息甚至在前端可用地方。只是我的意见。