Saat saya memuat versi yang diperkecil (melalui UglifyJS) dari aplikasi AngularJS saya, saya mendapatkan kesalahan berikut di konsol:
Unknown provider: aProvider <- a
Sekarang, saya menyadari bahwa ini karena nama variabel mangling. Versi yang tidak diubah berfungsi dengan baik. Namun, saya tidak ingin menggunakan variabel nama mangling, karena secara drastis mengurangi ukuran file output JS kami.
Oleh karena itu, kami menggunakan ngmin dalam proses pembuatan kami, tetapi tampaknya tidak menyelesaikan masalah ini, meskipun ini membantu kami dengan baik di masa lalu.
Jadi, untuk men-debug masalah ini, saya mengaktifkan peta sumber di tugas grunt uglify kami. Mereka dihasilkan baik-baik saja dan Chrome tidak memuat peta dari server. Namun, saya masih mendapatkan pesan kesalahan tidak membantu yang sama, meskipun saya mendapat kesan bahwa sekarang saya harus melihat nama asli penyedia.
Bagaimana cara membuat Chrome menggunakan peta sumber untuk memberi tahu saya penyedia mana yang bermasalah di sini, atau, sebagai alternatif, bagaimana saya bisa mengetahui penyedia dengan cara lain?
sumber
Jawaban:
Saya masih ingin tahu bagaimana saya dapat menemukan tempat di kode sumber kami yang menyebabkan masalah ini, tetapi sejak itu saya dapat menemukan masalahnya secara manual.
Ada fungsi pengontrol yang dideklarasikan pada cakupan global, alih-alih menggunakan
.controller()
panggilan pada modul aplikasi.Jadi ada yang seperti ini:
Ini berfungsi dengan baik untuk AngularJS, tetapi untuk membuatnya berfungsi dengan benar dengan mangling, saya harus mengubahnya menjadi:
Setelah tes lebih lanjut, saya benar-benar menemukan contoh lebih banyak pengontrol yang juga menyebabkan masalah. Beginilah cara saya menemukan sumber semuanya secara manual :
Pertama-tama, saya menganggap cukup penting untuk mengaktifkan kecantikan keluaran dalam opsi uglify. Untuk tugas kasar kami yang berarti:
Saya kemudian membuka situs web proyek di Chrome, dengan DevTools terbuka. Yang menghasilkan kesalahan seperti yang di bawah ini sedang dicatat:
Metode dalam pelacakan panggilan yang kami minati, adalah yang saya tandai dengan panah. Ini
providerInjector
masukinjector.js
. Anda akan ingin menempatkan breakpoint di mana ia mengeluarkan pengecualian:Saat Anda sekarang menjalankan ulang aplikasi, breakpoint akan terkena dan Anda dapat melompat ke tumpukan panggilan. Akan ada panggilan dari
invoke
dalaminjector.js
, dikenali dari string "Token injeksi salah":The
locals
parameter (hancur ked
dalam kode saya) memberikan ide yang cukup baik tentang yang objek dalam sumber Anda adalah masalah:Sekilas
grep
sumber kami menemukan banyak contohmodalInstance
, tetapi pergi dari sana, mudah untuk menemukan tempat ini di sumber:Yang harus diubah menjadi:
Jika variabel tidak menyimpan informasi yang berguna, Anda juga dapat melompat lebih jauh ke atas tumpukan dan Anda harus menekan panggilan
invoke
yang seharusnya memiliki petunjuk tambahan:Cegah hal ini terjadi lagi
Sekarang setelah Anda menemukan masalahnya, saya merasa bahwa saya harus menyebutkan cara terbaik untuk menghindari hal ini terjadi lagi di masa mendatang.
Jelas, Anda bisa saja menggunakan anotasi larik sebaris di mana-mana, atau
$inject
anotasi properti (bergantung pada preferensi Anda) dan mencoba untuk tidak melupakannya di masa mendatang. Jika Anda melakukannya, pastikan untuk mengaktifkan mode injeksi ketergantungan ketat , untuk menangkap kesalahan seperti ini sedini mungkin.Atau Anda bisa membiarkan ng-anotasi mengurusnya. Saya sangat merekomendasikan melakukannya, karena ini menghilangkan banyak potensi kesalahan di area ini, seperti:
Menjaga anotasi tetap mutakhir hanya merepotkan dan Anda tidak perlu melakukannya jika dapat dilakukan secara otomatis. ng-annotate melakukan hal itu.
Ini harus terintegrasi dengan baik ke dalam proses build Anda dengan grunt-ng-annotate dan gulp-ng-annotate .
sumber
uglify({ output : { beautify : true }})
Tulisan Oliver Salzburg sangat fantastis. Suara positif.
Tip untuk siapa saja yang mungkin mengalami kesalahan ini. Milik saya hanya disebabkan oleh lupa untuk mengirimkan array untuk pengontrol direktif:
BURUK
BAIK
sumber
/* @ngInject */
sebelum fungsinya. Tampaknya melakukan bagian injeksi yang rumit tanpa perlu mengetikkan setiap modul yang disertakan (Saya menggunakan Yeoman)gunakan ng-strict-di dengan ng-app
Jika Anda menggunakan sudut 1,3 Anda dapat menyimpan sendiri dunia yang terluka dengan menggunakan ngStrictDi direktif dengan ngApp:
Sekarang - pra-minifikasi - apa pun yang tidak menggunakan anotasi akan meledakkan konsol Anda dan Anda dapat melihat nama sialan itu tanpa memburu melalui jejak tumpukan yang rusak.
Per dokumen:
Satu peringatan , hanya mendeteksi bahwa ada yang penjelasan, tidak bahwa penjelasan lengkap.
Berarti:
Tidak akan menangkap bahwa ThingB bukan bagian dari anotasi.
Penghargaan untuk tip ini diberikan kepada orang - orang ng-anotasi , yang direkomendasikan daripada ngMin yang sekarang sudah usang.
sumber
Untuk memperkecil sudut, yang perlu Anda lakukan adalah mengubah deklarasi Anda ke mode "deklarasi" "array", misalnya:
Dari:
Untuk
Bagaimana cara mendeklarasikan layanan pabrik?
sumber
Saya baru saja mengalami masalah yang sama dan menyelesaikannya hanya dengan mengganti ngmin (sekarang sudah tidak digunakan lagi) dengan ng-annotate untuk tugas build grunt saya.
Tampaknya sudut yeoman juga telah diperbarui untuk menggunakan ng-annotate pada komit ini: https://github.com/yeoman/generator-angular/commit/3eea4cbeb010eeaaf797c17604b4a3ab5371eccb
Namun jika Anda menggunakan yeoman angular versi lama seperti saya, ganti saja ng-min dengan ng-annotate di package.json Anda:
jalankan
npm install
(lalu opsionalnpm prune
), dan ikuti perubahan dalam komit untuk mengeditGruntfile.js
.sumber
untuk mengetahui apa nama variabel aslinya, Anda dapat mengubah cara uglify menghapus variabel:
dan sekarang kesalahannya jauh lebih jelas
EDIT
Sangat jelas sekarang ...
sekarang setiap variabel dihancurkan menjadi nilai unik yang juga berisi yang asli ... cukup buka javascript yang diperkecil dan cari "a_orig_ $ stateProvider_91212" atau apa pun ... Anda akan melihatnya dalam konteks aslinya ...
tidak bisa lebih mudah ...
sumber
Juga jangan lupakan
resolve
properti rutenya. Itu juga harus didefinisikan sebagai array:sumber
Dengan generator-gulp-angular:
Tulis / ** @ngInject * / sebelum setiap pengontrol, layanan, direktif.
sumber
Perbaikan cepat dan kotor untuk ini jika Anda tidak memerlukan Uglify untuk mengacaukan / mempersingkat nama variabel Anda adalah dengan menyetel mangle = false di Gruntfile Anda
sumber