Kapan saya harus menggunakan Javascript Inline vs. External?

129

Saya ingin tahu kapan saya harus memasukkan skrip eksternal atau menulisnya sesuai dengan kode html, dalam hal kinerja dan kemudahan pemeliharaan.

Apa praktik umum untuk ini?

Skenario dunia nyata - Saya memiliki beberapa halaman html yang memerlukan validasi formulir sisi klien. Untuk ini saya menggunakan plugin jQuery yang saya sertakan di semua halaman ini. Tetapi pertanyaannya adalah, apakah saya:

  • tulis bit kode yang mengkonfigurasi skrip inline ini?
  • termasuk semua bit dalam satu file yang dibagi di antara semua halaman html ini?
  • termasuk setiap bit dalam file eksternal yang terpisah, satu untuk setiap halaman html?

Terima kasih.

Dan Burzo
sumber

Jawaban:

114

Pada saat jawaban ini awalnya diposting (2008), aturannya sederhana: Semua skrip harus eksternal. Baik untuk pemeliharaan dan kinerja.

(Mengapa kinerja? Karena jika kodenya terpisah, lebih mudah di-cache oleh browser.)

JavaScript tidak termasuk dalam kode HTML dan jika mengandung karakter khusus (seperti <, >) itu bahkan membuat masalah.

Saat ini, skalabilitas web telah berubah. Mengurangi jumlah permintaan telah menjadi pertimbangan yang valid karena latensi membuat beberapa permintaan HTTP. Ini membuat jawabannya lebih rumit: dalam kebanyakan kasus, memiliki JavaScript eksternal masih disarankan. Tetapi untuk kasus-kasus tertentu, terutama potongan kode yang sangat kecil, memasukkannya ke dalam HTML situs masuk akal.

Konrad Rudolph
sumber
6
@Nick: sebagian besar masalah bisa diatasi. Lebih baik tidak menghasilkannya sejak awal.
Konrad Rudolph
17
Terkadang Anda mendapatkan kinerja yang lebih baik saat inlining. Lihatlah sumber google.com . Mereka tahu apa yang mereka lakukan.
callum
13
@callum Google memiliki use case berbeda dari 99,999999% situs web. Tentu saja mereka mengukur dengan sangat hati-hati dan bahkan perbedaan terkecil pun penting. Tetapi hanya karena mereka menemukan bahwa dalam kasus penggunaan khusus mereka, inlining berfungsi lebih baik (mungkin karena skrip berubah sangat sering?) Tidak berarti bahwa kita dapat memperoleh aturan umum dari itu, atau bahkan bahwa kita harus mengabaikan "konvensional" aturan (untuk eksternalisasi skrip).
Konrad Rudolph
8
@KonradRudolph - Setuju, tidak ada aturan umum yang harus diturunkan dari pendekatan Google. Saya hanya mengatakan itu isyarat bahwa mungkin ada baiknya mempertanyakan aturan dalam jawaban Anda. Bagaimanapun, saya pikir alasan Google melakukannya adalah untuk mengurangi permintaan HTTP, dan ini mungkin menguntungkan lebih dari 0,000001% situs. Bandwidth semakin tinggi tetapi waktu pulang pergi tetap sama. Menghapus seluruh permintaan HTTP serial terkadang lebih baik daripada manfaat caching JS eksternal. Tergantung pada ukuran JS Anda tentu saja.
callum
5
@callum Meskipun ini benar, poin tentang caching masih ada dan tetap penting. Mengurangi bolak-balik hanya penting jika pengunjung Anda tidak kembali (dan kemudian Anda tidak akan mendapatkan cukup banyak klik halaman untuk menjadikannya penting) atau jika konten Anda sering berubah sehingga cache file skrip tidak memiliki manfaat.
Konrad Rudolph
31

Maintainability jelas merupakan alasan untuk menjadikannya eksternal, tetapi jika konfigurasinya adalah satu-liner (atau secara umum lebih pendek dari overhead HTTP yang akan Anda peroleh untuk membuat file-file itu eksternal) sebaiknya dilakukan dengan menjaga performa agar tetap sejajar. Selalu ingat, bahwa setiap permintaan HTTP menghasilkan beberapa overhead dalam hal waktu dan lalu lintas eksekusi.

Tentu ini semua menjadi tidak relevan saat kode Anda lebih panjang dari beberapa baris dan tidak benar-benar spesifik untuk satu halaman. Saat Anda ingin dapat menggunakan kembali kode itu, buatlah eksternal. Jika tidak, lihat ukurannya dan putuskan.

Horst Gutmann
sumber
5
Itu salah satu kekhawatiran saya. Memiliki permintaan HTTP terpisah untuk beberapa baris kode tampaknya sia-sia.
Dan Burzo
Bisakah Anda memposting konfigurasi sampel untuk kode Anda? IMO jika di bawah 300 karakter dan benar-benar spesifik halaman, sebariskan itu.
Horst Gutmann
Ini harus menjadi jawaban teratas imo
sgarcia.dev
@Bisa diingat bahwa permintaan terpisah hanya terjadi pertama kali. Jika Anda mengharapkan pengguna memuat halaman lebih dari satu kali, cache eksternal (bahkan untuk beberapa baris) jelas lebih cepat daripada menunggu byte untuk beberapa baris di atas kabel pada n = 2 + halaman dimuat.
jinglesthula
@HorstGutmann bagaimana cara memiliki file bantuan eksternal dengan rawatan? Saya pribadi lebih suka js eksternal bila memungkinkan, tetapi apakah ada sesuatu yang objektif yang membuatnya lebih mudah untuk dipertahankan?
jinglesthula
21

Externalizing javascript adalah salah satu aturan kinerja yahoo: http://developer.yahoo.com/performance/rules.html#external

Meskipun aturan keras dan cepat bahwa Anda harus selalu mengeksternalisasi skrip umumnya akan menjadi taruhan yang baik, dalam beberapa kasus Anda mungkin ingin menyejajarkan beberapa skrip dan gaya. Namun Anda harus hanya sebaris hal-hal yang Anda tahu akan meningkatkan kinerja (karena Anda mengukur ini)

Joeri Sebrechts
sumber
1
Saya pikir Yahoo juga merekomendasikan untuk menambahkan semua Javascript ke dalam satu panggilan HTTP juga - ini tidak berarti bahwa semua skrip harus berada dalam file yang sama selama pengembangan
Paul Shannon
Juga, seperti disebutkan di atas, HTTP / 2 mengubah praktik "1 panggilan" juga.
Jinglesthula
19

Jika Anda hanya peduli dengan kinerja, sebagian besar saran di utas ini benar-benar salah, dan menjadi semakin salah di era SPA, di mana kita dapat menganggap bahwa halaman tersebut tidak berguna tanpa kode JS. Saya telah menghabiskan banyak waktu untuk mengoptimalkan waktu pemuatan halaman SPA, dan memverifikasi hasil ini dengan browser yang berbeda. Di seluruh papan, peningkatan kinerja dengan mengatur ulang html Anda, bisa sangat dramatis.

Untuk mendapatkan kinerja terbaik, Anda harus menganggap halaman sebagai roket dua tahap. Kedua tahap ini secara kasar berhubungan dengan <head>dan <body>fase, tetapi menganggapnya sebagai <static>dan <dynamic>. Bagian statis pada dasarnya adalah konstanta string yang Anda sorong ke bawah pipa respon secepat mungkin. Ini bisa sedikit rumit jika Anda menggunakan banyak middleware yang mengatur cookie (ini perlu diatur sebelum mengirim konten http), tetapi pada prinsipnya itu hanya menyiram buffer respon, mudah-mudahan sebelum beralih ke beberapa kode templating (razor, php, dll) di server. Ini mungkin terdengar sulit, tetapi kemudian saya hanya menjelaskannya salah, karena hampir sepele. Seperti yang mungkin sudah Anda duga, bagian statis ini harus berisi semua javascript yang digarisbawahi dan diperkecil. Itu akan terlihat seperti

<!DOCTYPE html>
     <html>
         <head>
             <script>/*...inlined jquery, angular, your code*/</script>
             <style>/* ditto css */</style>
         </head>
         <body>
             <!-- inline all your templates, if applicable -->
             <script type='template-mime' id='1'></script>
             <script type='template-mime' id='2'></script>
             <script type='template-mime' id='3'></script>

Karena hampir tidak ada biaya untuk mengirimkan bagian ini, Anda dapat berharap bahwa klien akan mulai menerima ini sekitar 5 ms + latensi setelah tersambung ke server Anda. Dengan asumsi server cukup dekat, latensi ini bisa antara 20 ms hingga 60 ms. Browser akan mulai memproses bagian ini segera setelah mereka mendapatkannya, dan waktu pemrosesan biasanya akan mendominasi waktu transfer dengan faktor 20 atau lebih, yang sekarang menjadi jendela diamortisasi Anda untuk pemrosesan <dynamic>bagian sisi server .

Dibutuhkan sekitar 50 ms untuk browser (chrome, sisanya mungkin 20% lebih lambat) untuk memproses jquery inline + signalr + angular + ng animasi + ng sentuh + ng rute + lodash. Itu cukup luar biasa dalam dan dari dirinya sendiri. Sebagian besar aplikasi web memiliki kode lebih sedikit daripada semua perpustakaan populer yang disatukan, tetapi katakanlah Anda memiliki jumlah yang sama, jadi kami akan memenangkan latensi + 100ms pemrosesan pada klien (kemenangan latensi ini berasal dari potongan transfer kedua). Pada saat chunk kedua tiba, kami telah memproses semua kode js dan templat dan kami dapat mulai menjalankan transformasi dom.

Anda mungkin keberatan bahwa metode ini ortogonal dengan konsep inlining, tetapi tidak. Jika Anda, alih-alih meluruskan, menautkan ke cdns atau server Anda sendiri, browser harus membuka koneksi lain dan menunda eksekusi. Karena eksekusi ini pada dasarnya gratis (karena sisi server sedang berbicara ke database), harus jelas bahwa semua lompatan ini akan lebih mahal daripada tidak melompat sama sekali. Jika ada kekhasan browser yang mengatakan js eksternal mengeksekusi lebih cepat kita bisa mengukur faktor mana yang mendominasi. Pengukuran saya menunjukkan bahwa permintaan tambahan membunuh kinerja pada tahap ini.

Saya banyak bekerja dengan optimalisasi aplikasi SPA. Sudah umum bagi orang untuk berpikir bahwa volume data adalah masalah besar, sementara dalam latensi kebenaran, dan eksekusi sering mendominasi. Pustaka yang diperkecil yang saya daftarkan menambahkan hingga 300kb data, dan itu hanya 68 kb di-gzip, atau 200ms diunduh pada telepon 2mbit 3g / 4g, yang merupakan latensi yang diperlukan pada telepon yang sama untuk memeriksa JIKA ada data yang sama dalam cache sudah, bahkan jika itu adalah proxy di-cache, karena pajak latensi seluler (telepon-ke-menara-latensi) masih berlaku. Sementara itu, koneksi desktop yang memiliki latensi first-hop lebih rendah biasanya memiliki bandwidth yang lebih tinggi pula.

Singkatnya, sekarang (2014), yang terbaik adalah inline semua skrip, gaya, dan templat.

EDIT (MEI 2016)

Ketika aplikasi JS terus tumbuh, dan beberapa muatan saya sekarang menumpuk hingga 3+ megabyte kode minified, menjadi jelas bahwa paling tidak perpustakaan umum seharusnya tidak lagi digariskan.

Gleno
sumber
Saya tidak mendapatkan yang sekarang merupakan jendela diamortisasi Anda untuk pemrosesan sisi-server dari bagian porsi <dinamik> - Server memproses apa yang dibutuhkannya dan hanya kemudian melayani seluruh html yang dirender (head + body), apa pemrosesan server lain diperlukan setelah itu?
BornToCode
@BornToCode Idenya adalah untuk memberikan klien sesuatu untuk dilakukan pada saat yang sama sisi server memiliki sesuatu untuk dilakukan. Karena pustaka klien perlu ditafsirkan - lebih baik untuk memulai proses itu sebelum melakukan perhitungan apa pun di server. Jendela diamortisasi adalah waktu yang dibutuhkan klien untuk memproses JS. Anda mendapatkan jendela itu secara gratis, jika Anda membuat roket 2 tahap.
Gleno
9

Sebenarnya, ada kasus yang cukup kuat untuk menggunakan javascript inline. Jika js cukup kecil (satu-liner), saya cenderung lebih suka inline javascript karena dua faktor:

  • Lokalitas . Tidak perlu menavigasi file eksternal untuk memvalidasi perilaku beberapa javascript
  • AJAX . Jika Anda me-refresh beberapa bagian halaman melalui AJAX, Anda mungkin kehilangan semua penangan DOM Anda (klik, dll) untuk bagian itu, tergantung pada bagaimana Anda mengikatnya. Sebagai contoh, menggunakan jQueryAnda dapat menggunakan metode liveatau delegateuntuk mengelak ini, tapi saya menemukan bahwa jika js cukup kecil itu lebih disukai untuk hanya meletakkannya sebaris.
Miguel Ping
sumber
5

Alasan lain mengapa Anda harus selalu menggunakan skrip eksternal adalah untuk transisi yang lebih mudah ke Kebijakan Keamanan Konten (CSP) . Default CSP melarang semua skrip sebaris, membuat situs Anda lebih tahan terhadap serangan XSS.

Chiborg
sumber
4

Saya akan melihat kode yang diperlukan dan membaginya menjadi file terpisah sebanyak yang diperlukan. Setiap file js hanya akan menampung satu "set logis" fungsi dll. Mis. satu file untuk semua fungsi terkait login.

Kemudian selama pengembangan situs pada setiap halaman html Anda hanya menyertakan yang dibutuhkan. Ketika Anda tayang langsung dengan situs Anda, Anda dapat mengoptimalkan dengan menggabungkan setiap file js yang dibutuhkan suatu halaman menjadi satu file.

Gene
sumber
4

Satu-satunya pertahanan yang dapat saya tawarkan untuk javascipt inline adalah bahwa ketika menggunakan tampilan yang sangat diketik dengan .net MVC Anda dapat merujuk ke variabel c # mid javascript yang menurut saya berguna.

Austin_G
sumber
3

Tiga pertimbangan:

  • Berapa banyak kode yang Anda butuhkan (kadang-kadang perpustakaan adalah konsumen kelas satu)?
  • Kekhususan: apakah kode ini hanya berfungsi dalam konteks dokumen atau elemen khusus ini?
  • Setiap kode di dalam dokumen cenderung membuatnya lebih lama dan karenanya lebih lambat. Selain itu pertimbangan SEO membuatnya jelas, bahwa Anda meminimalkan skrip internal ...
roenving
sumber
2

Skrip eksternal juga lebih mudah di-debug menggunakan Firebug. Saya suka Unit Test JavaScript saya dan memiliki semuanya membantu eksternal. Saya benci melihat JavaScript dalam kode PHP dan HTML sepertinya berantakan bagi saya.

Kopling
sumber
2

Pada titik menjaga JavaScript eksternal:

ASP.NET 3.5SP1 baru-baru ini memperkenalkan fungsionalitas untuk membuat sumber daya skrip Komposit (menggabungkan sekelompok file js menjadi satu). Manfaat lain dari hal ini adalah ketika kompresi Webserver dihidupkan, mengunduh satu file yang sedikit lebih besar akan memiliki rasio kompresi yang lebih baik daripada banyak file yang lebih kecil (juga lebih sedikit overhead http, pulang pergi dll ...). Saya kira ini menghemat pada memuat halaman awal, kemudian caching browser tendangan seperti yang disebutkan di atas.

Selain ASP.NET, screencast ini menjelaskan manfaat lebih terinci: http://www.asp.net/learn/3.5-SP1/video-296.aspx

Brendan Kowitz
sumber
2

Manfaat tersembunyi lain dari skrip eksternal adalah Anda dapat dengan mudah menjalankannya melalui pemeriksa sintaksis seperti jslint . Itu dapat menyelamatkan Anda dari banyak bug IE6 yang memilukan dan sulit ditemukan.

Ken
sumber
1

Dalam skenario Anda, sepertinya menulis hal-hal eksternal dalam satu file yang dibagikan di antara halaman akan baik untuk Anda. Saya setuju dengan semua yang dikatakan di atas.

mattlant
sumber
1

Selama pembuatan purwarupa awal, pertahankan kode Anda tetap untuk keuntungan iterasi yang cepat, tetapi pastikan untuk menjadikannya eksternal ketika Anda mencapai produksi.

Saya bahkan berani mengatakan bahwa jika Anda tidak dapat menempatkan semua Javascript Anda secara eksternal, maka Anda memiliki desain yang buruk di tangan Anda, dan Anda harus memperbaiki data dan skrip Anda

Robert Gould
sumber
1

Google telah memasukkan waktu muat ke dalam pengukuran peringkat halaman itu, jika Anda banyak inline, itu akan memakan waktu lebih lama bagi laba-laba untuk merangkak melalui halaman Anda, ini mungkin mempengaruhi peringkat halaman Anda jika Anda harus banyak disertakan. dalam hal apa pun strategi yang berbeda dapat memengaruhi peringkat Anda.

Kees Hessels
sumber
1

baik saya pikir Anda harus menggunakan inline ketika membuat situs web satu halaman sebagai skrip tidak perlu dibagi di beberapa halaman

Zak Sheikh
sumber
-3

Selalu mencoba menggunakan Js eksternal karena inline js selalu sulit dipertahankan.

Selain itu, secara profesional diperlukan bahwa Anda menggunakan js eksternal karena mayoritas pengembang merekomendasikan menggunakan js secara eksternal.

Saya sendiri menggunakan js eksternal.

Daniel Puiu
sumber
2
Diperlukan secara profesional? Mengapa? Siapa yang mengatakan itu?
Siyah