Haruskah saya menghapus console.log dari kode produksi?

88

Saat ini saya memiliki pernyataan JS ini di mana-mana dalam kode saya:

window.console && console.log("Foo");

Saya bertanya-tanya apakah ini mahal sama sekali, atau memiliki efek samping negatif dalam produksi.

Apakah saya bebas untuk meninggalkan sisi klien masuk, atau haruskah pergi?

EDIT: Pada akhirnya, saya kira argumen terbaik yang dapat saya (dan orang lain?) Berikan adalah bahwa ada jumlah data tambahan yang mungkin tidak dapat diabaikan yang ditransfer antara server dan klien dengan meninggalkan pesan logging yang tertinggal. Jika kode produksi harus dioptimalkan sepenuhnya, logging harus dihapus untuk mengurangi ukuran javascript yang dikirim ke klien.

Sean Anderson
sumber

Jawaban:

41

Anda tidak boleh menambahkan alat pengembangan ke halaman produksi.

Untuk menjawab pertanyaan lain: Kode tidak boleh memiliki efek samping negatif:

  • window.consoleakan dievaluasi menjadi salah jika consoletidak ditentukan
  • console.log("Foo")akan mencetak pesan ke konsol saat ditentukan (asalkan halaman tidak ditimpa console.logoleh non-fungsi).
Rob W.
sumber
43
Saya setuju dengan Anda pada prinsipnya. Tapi, saya pikir kita semua setuju bahwa menerapkan logging yang tidak menyala kecuali selama mode debug diperlukan untuk kode sisi server yang berkualitas. Tidak ada yang melewati dan menghapus logging mereka untuk rilis produksi - program menentukan tingkat logging apa yang diperlukan dan bereaksi sesuai dengan itu. Saya berharap ada sesuatu yang mirip dengan ini untuk pemrograman sisi klien ... bahkan hanya mengatur variabel "isDebug", jika perlu. Mengapa saya ingin membebani pengembang berikutnya dengan mengharuskan kembali dan menambahkan kembali penebangan untuk area bermasalah di masa mendatang?
Sean Anderson
11
Lusuh bagaimana? Saya berpendapat bahwa mengatakan konsol pengembang adalah bagian dari situs web produksi sama seperti mengatakan file log adalah bagian dari aplikasi. Ya, keduanya dihasilkan oleh kode, tetapi harus ada tingkat pemahaman bahwa log harus ditinggalkan di suatu tempat. Apakah pernyataan di dalam log ramah pengguna atau tidak adalah masalah lain.
Sean Anderson
4
Bagaimana seseorang secara otomatis menghapus kode debugging sebelum meminimalkan? Ada banyak bentuk yang dapat dilakukan oleh pesan log sisi klien.
Sean Anderson
6
Anda dapat menandai setiap bagian dari kode debug, misalnya dengan mengawali / memperbaiki baris kode debug dengan komentar. Contoh: /*DEBUG:start*/console.log("Foo");/*DEBUG:end*/. Kemudian, gunakan RegExp untuk menghapus semua kemunculan /*DENUG-start*/[\S\s]*?/*DEBUG-end*/. Karakter ruang kosong yang tersisa akan dihapus oleh minimizer.
Rob W
3
Kecuali jika jawaban ini mengatakan MENGAPA Anda tidak boleh melakukannya, itu benar-benar tidak berguna. Kami hanya seharusnya menerima begitu saja bahwa itu buruk tanpa bukti atau alasan?
ESR
48

Cara lain untuk menangani ini adalah dengan 'mematikan' objek konsol ketika tidak didefinisikan sehingga tidak ada kesalahan yang dilemparkan dalam konteks yang tidak memiliki konsol, mis.

if (!window.console) {
  var noOp = function(){}; // no-op function
  console = {
    log: noOp,
    warn: noOp,
    error: noOp
  }
}

Anda mengerti ... ada banyak fungsi yang ditentukan pada berbagai implementasi konsol, jadi Anda dapat menghentikan semuanya atau hanya yang Anda gunakan (misalnya jika Anda hanya pernah menggunakan console.logdan tidak pernah digunakan console.profile, console.timedll ...)

Bagi saya ini adalah alternatif yang lebih baik dalam pengembangan daripada menambahkan persyaratan di depan setiap panggilan, atau tidak menggunakannya.

lihat juga: Apakah ide yang buruk untuk meninggalkan panggilan "console.log ()" di produk Anda pada kode JavaScript?

craigb.dll
sumber
6
Ide bagus. Hanya perlu beberapa perbaikan. Visual Studio JS debugger melempar di console.log = noOp () pertama karena objek konsol itu sendiri tidak ditentukan. Saya melakukannya seperti ini: console = {log: noOp, warn: noOp, error: noOp}. Juga perhatikan bahwa Anda tidak ingin meletakkan () setelah noOp - Anda ingin menetapkan fungsi itu sendiri dan bukan nilai kembaliannya. Diuji pada Visual Studio JS debugger dan IE9 - sekarang berfungsi dengan baik.
JustAMartin
3
FYI, jika Anda sudah menggunakan jQuery, mereka menyediakan fungsi noop: $.noop .
hancurkan
28

UglifyJS2

Jika Anda menggunakan minifier ini, Anda dapat mengatur drop_consoleopsi :

Berikan true untuk membuang panggilan ke fungsi konsol. *

Jadi saya akan menyarankan untuk meninggalkan console.logpanggilan karena itu untuk bagian yang paling sulit dari basis kode.

terales
sumber
3
Jika Anda menggunakan grunt dan uglify , opsi yang sama juga tersedia (tampaknya uglify didasarkan pada UglifyJS2): github.com/gruntjs/…
Miringkan
1
Pertanyaannya adalah "haruskah saya", bukan "bagaimana saya".
ESR
Anda harus membiarkan console.errors masuk. Jika seseorang di bagian produksi memiliki masalah, maka Anda dapat dengan mudah mendiagnosisnya. Jangan menghapus console.errors!
Oliver Watkins
Jika akan ada kebutuhan untuk mereka maka Anda dapat hanya mengatur drop_consoleuntuk false, mengamati mereka dan menyembunyikan mereka lagi.
terales
16

Jika minifikasi adalah bagian dari proses build Anda, Anda dapat menggunakannya untuk menghapus kode debug, seperti yang dijelaskan di sini dengan kompiler penutupan Google: Kecualikan kode JavaScript debug selama minifikasi

if (DEBUG) {
  console.log("Won't be logged if compiled with --define='DEBUG=false'")
}

Jika Anda mengkompilasi dengan pengoptimalan lanjutan, kode ini bahkan akan diidentifikasi sebagai mati dan dihapus seluruhnya

wutz
sumber
1
Terima kasih! Saya mencari ini. :)
Sean Anderson
5

Iya. console.log akan menampilkan pengecualian di browser yang tidak mendukungnya (objek konsol tidak akan ditemukan).

MK_Dev
sumber
bukan dengan evaluasi korsletingnya, selama jendela ditentukan
Joe
1
Meskipun saya melewatkannya di jawaban awal saya, periksa console.log juga harus dilakukan.
MK_Dev
Saya kebanyakan hanya melakukan window.console untuk mencegah gangguan dengan IE. Saya belum pernah mengalami situasi di mana log ditimpa secara tidak sengaja, tetapi saya yakin itu bisa terjadi.
Sean Anderson
@MK_Dev Yaitu, browser yang mana?
goodpixels
Ini tahun 2019. Saya ragu ada browser yang tidak mendukung konsol.
Oliver Watkins
5

Secara umum, ya, bukanlah ide yang bagus untuk mengekspos pesan log dalam kode produksi Anda.

Idealnya, Anda harus menghapus pesan log tersebut dengan skrip build sebelum menerapkan; tetapi banyak (kebanyakan) orang tidak menggunakan proses membangun (termasuk saya).

Berikut cuplikan singkat dari beberapa kode yang saya gunakan akhir-akhir ini untuk mengatasi dilema ini. Ini memperbaiki kesalahan yang disebabkan oleh yang tidak ditentukan consoledi IE lama, serta menonaktifkan logging jika di "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);
}

Saya cukup yakin saya mengambil banyak addConsoleNoOpf'n di atas dari jawaban lain di SO, tetapi tidak dapat menemukannya sekarang. Saya akan menambahkan referensi nanti jika saya menemukannya.

sunting: Bukan pos yang saya pikirkan, tetapi inilah pendekatan serupa: https://github.com/paulmillr/console-polyfill/blob/master/index.js

Zach Lysobey
sumber
3
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;
})();

Pemakaian:

var debugMode=true;
var appLogger = new AppLogger(debugMode);
appLogger.conlog('test');
dynamiclynk.dll
sumber
1

Ya, praktik yang baik untuk digunakan console.loguntuk tujuan debug javascript, tetapi perlu dihapus dari server produksi atau jika perlu dapat ditambahkan di server produksi dengan beberapa poin penting yang harus dipertimbangkan:

**var isDebugEnabled="Get boolean value from Configuration file to check whether debug is enabled or not".**
if (window.console && isDebugEnabled) {
    console.log("Debug Message");
}

Blok kode di atas harus digunakan di mana saja untuk logging guna memverifikasi terlebih dahulu apakah konsol didukung untuk browser saat ini dan apakah debug diaktifkan atau tidak.

isDebugEnabled harus disetel sebagai benar atau salah berdasarkan lingkungan kita.

shanky
sumber
1

TL; DR

Ide: Objek penebangan menghalangi mereka dari Pengumpulan Sampah.

Detail

  1. Jika Anda meneruskan objek ke objek tersebut console.logmaka objek ini dapat diakses dengan referensi dari konsol DevTools. Anda dapat memeriksanya dengan mencatat objek, memutasinya dan menemukan bahwa pesan lama mencerminkan perubahan objek nanti.
  2. Jika log terlalu panjang, pesan lama bisa dihapus di Chrome.
  3. Jika log pendek maka pesan lama tidak dihapus, jika pesan referensi objek maka objek ini tidak Sampah Dikumpulkan.

Itu hanya ide: Saya memeriksa poin 1 dan 2 tetapi bukan 3.

Larutan

Jika Anda ingin menyimpan log demi pemecahan masalah sisi klien atau kebutuhan lain, maka:

['log', 'warn', 'error'].forEach( (meth) => {
  const _meth = window.console[meth].bind(console);
  window.console[meth] = function(...args) { _meth(...args.map((arg) => '' + arg)) }
});
ilyaigpetrov
sumber
0

Saya pada dasarnya menimpa fungsi console.log dengan fungsi yang memiliki pengetahuan tentang di mana kode tersebut dijalankan. Jadi saya bisa tetap menggunakan console.log seperti biasa. Secara otomatis mengetahui bahwa saya dalam mode dev / qa atau dalam produksi. Ada juga cara untuk memaksanya. Ini biola yang berfungsi. http://jsfiddle.net/bsurela/Zneek/

Berikut adalah potongan karena stack overflow diintimasikan oleh orang-orang yang memposting 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);
    }
},
Bhavin
sumber
0

Saya tahu ini adalah pertanyaan lama dan sudah lama tidak banyak aktivitas. Saya hanya ingin menambahkan solusi yang saya dapatkan yang tampaknya bekerja dengan baik untuk saya.

    /**
     * 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;
            }
        }
    }

Kemudian saya biasanya membuat fungsi dalam skrip saya seperti ini atau Anda dapat membuatnya tersedia dalam skrip global:

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!');
        }           
    }   
}

Dan kemudian saya hanya menggunakan itu sebagai ganti console.log seperti ini:

try{
 // To Do Somehting
 Something.fail('Debug Something', data, 'debug', 'myFunc()', new Error().lineNumber);
}catch(error){
 Something.fail('Something Failed', error, 'error', 'myFunc()', new Error().lineNumber);
}
Kyle Coots
sumber
0

Jika alur kerja dilakukan menggunakan alat yang tepat seperti parcel/ webpackmaka tidak lagi pusing, karena dengan productionbuild console.logsedang dijatuhkan. Bahkan beberapa tahun sebelumnya dengan Gulp/Grunt itu bisa diotomatisasi juga.

Banyak kerangka modern seperti Angular, React, Svelte, Vue.jsdatang dengan setup yang out-of-the-box. Pada dasarnya, Anda tidak perlu melakukan apa pun, selama Anda menerapkan build yang benar, yaitu productionsatu, bukan developmentyang masih akan memilikinya console.log.

Daniel Danielecki
sumber