Cách tốt nhất để sử dụng jQuery được lưu trữ của Google, nhưng quay lại thư viện được lưu trữ của tôi trên Google không thành công


1016

Điều gì sẽ là một cách tốt để cố gắng tải jQuery được lưu trữ tại Google (hoặc các lib khác được lưu trữ trên Google), nhưng tải bản sao jQuery của tôi nếu nỗ lực của Google thất bại?

Tôi không nói rằng Google không ổn định. Có những trường hợp bản sao Google bị chặn (ví dụ như ở Iran).

Tôi có thể thiết lập bộ đếm thời gian và kiểm tra đối tượng jQuery không?

Điều gì sẽ là mối nguy hiểm của cả hai bản sao đi qua?

Không thực sự tìm kiếm câu trả lời như "chỉ sử dụng Google một" hoặc "chỉ sử dụng của riêng bạn." Tôi hiểu những lý lẽ đó. Tôi cũng hiểu rằng người dùng có thể có bộ nhớ cache phiên bản Google. Tôi đang nghĩ về dự phòng cho đám mây nói chung.


Chỉnh sửa: Phần này đã thêm ...

Vì Google đề xuất sử dụng google.load để tải các thư viện ajax và nó thực hiện gọi lại khi hoàn tất, tôi tự hỏi liệu đó có phải là chìa khóa để giải quyết vấn đề này không.

Tôi biết nó nghe có vẻ hơi điên rồ. Tôi chỉ đang cố gắng tìm hiểu xem nó có thể được thực hiện một cách đáng tin cậy hay không.


Cập nhật: jQuery hiện được lưu trữ trên CDN của Microsoft.

http://www.asp.net/ajax/cdn/


9
Tất nhiên câu trả lời đầu tiên là "không sử dụng phiên bản được lưu trữ trên google." :-)
Nosredna

7
Tất nhiên đó là vì nếu bạn muốn lưu trữ một trang web nghiêm túc, bạn không dựa vào người khác lưu trữ các tệp của mình.
Bryan Migliorisi

6
@Bryan Migliorisi, tôi đoán Twitter rốt cuộc không nghiêm trọng lắm phải không? Nhưng tôi thừa nhận họ có vấn đề với Google như một tháng trước khi Google ngừng hoạt động.
Ionuț G. Stan

18
Ưu điểm của việc sử dụng Google hay không cho lưu trữ lib lib là một điều đáng giá, nhưng nó đã được thảo luận trong một số chủ đề khác. Tôi đã tìm kiếm các câu trả lời kỹ thuật liên quan đến dự phòng JS khi tải chậm trễ.
Nosredna

2
@Joe Chung: Có khả năng nó sẽ được lưu trong bộ nhớ cache trên hệ thống của người dùng, tăng tốc độ tải trang. Tiết kiệm cho tôi băng thông. Sử dụng CDN của Google. V.v.
Nosredna

Câu trả lời:


810

Bạn có thể đạt được nó như thế này:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>

<script>
       window.jQuery || document.write('<script src="/path/to/your/jquery"><\/script>');
</script>

Điều này nên có trong trang của bạn <head>và bất kỳ trình xử lý sự kiện sẵn sàng nào của jQuery phải ở trong <body>để tránh lỗi (mặc dù đó không phải là bằng chứng ngu ngốc!).

Thêm một lý do để không sử dụng jQuery do Google lưu trữ là ở một số quốc gia, tên miền của Google bị cấm.


35
Không tải xuống javascript (đồng bộ)? Dường như với tôi vấn đề sao chép đôi sẽ không phải là vấn đề.
Matt Sherman

68
Tải xuống Javascript phải được đồng bộ hóa, như Matt Sherman nói. Mặt khác, nhiều vấn đề sẽ xảy ra nếu trang cố thực thi tập lệnh nội tuyến dựa trên thư viện chỉ được tải xuống một nửa hoặc phần mở rộng thư viện được thực thi mà không thư viện tải xuống và thực thi đầy đủ. Đó cũng là một lý do tại sao Yahoo YSlow khuyên bạn nên đặt javascript ở cuối trang; để nó không chặn tải xuống các yếu tố trang khác (bao gồm cả kiểu và hình ảnh). Ít nhất, trình duyệt sẽ phải trì hoãn thực hiện để xảy ra tuần tự.
gapple

42
Sửa chữa nhỏ từ một người hâm mộ trình xác nhận hợp lệ: Chuỗi '</' không được phép trong JavaScript, vì nó có thể bị hiểu sai là phần cuối của thẻ script (ký hiệu thẻ ngắn SGML). Thay vào đó hãy thực hiện '<' + '/ script>'. Chúc mừng,
Boldewyn

8
Ví dụ này sẽ không hoạt động. 1) nếu thư viện Google ajax không có sẵn, nó sẽ phải hết thời gian trước khi thất bại. Việc này có thể mất một lúc. Trong thử nghiệm ngắt kết nối máy tính của tôi với mạng, nó chỉ thử và thử và thử và không hết thời gian. 2) if (! JQuery) sẽ đưa ra lỗi vì jQuery không được xác định nên Javascript không biết phải làm gì với nó.
RedWolves

32
Để kiểm tra xem jQuery đã được tải chưa, (! Window.jQuery) hoạt động tốt và được rút ngắn sau đó kiểm tra typeof.
Jorn Zaefferer

335

Cách dễ nhất và sạch nhất để làm điều này cho đến nay:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="path/to/your/jquery"><\/script>')</script>

1
@jpp không dành cho XHTML 1.0HTML 4.01
BenjaminRH

5
Mọi người cứ yêu cầu tôi gỡ bỏ các type="text/javascript"phần, vì vậy với những người viết html cho các trình duyệt cũ hơn, hãy lưu ý rằng bây giờ bạn sẽ phải thêm phần đó vào.
BenjaminRH

6
@BenjaminRH: type="text/javascript"cũng không cần thiết trong các trình duyệt cũ hơn, vì tất cả chúng đều được mặc định là Javascript. Các trình duyệt thực sự cũ hơn đã xem xét languagethuộc tính; nhưng ngay cả khi đó, Javascript là mặc định nếu thuộc tính bị thiếu.
Martijn

1
@Martijn Nhưng tôi thích huy hiệu xác thực sáng bóng :)
BenjaminRH

3
@Trojan Hoàn toàn có thể, chỉ cần xếp chồng các cuộc gọi. Lưu ý rằng tại thời điểm này, bạn đang mở các máy chủ kết nối mới, do đó, đường ống HTTP có thể sẽ nhanh hơn. ... <script src="//cdn1.com/jquery.js"></script> <script>window.jQuery || document.write('<script src="//cdn2.com/jquery.js"><\/script>')</script> <script>window.jQuery || document.write('<script src="local/jquery.js"><\/script>')</script>
Tom McKenzie

76

Điều này dường như làm việc cho tôi:

<html>
<head>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
// has the google object loaded?
if (window.google && window.google.load) {
    google.load("jquery", "1.3.2");
} else {
    document.write('<script type="text/javascript" src="http://joecrawford.com/jquery-1.3.2.min.js"><\/script>');
}
window.onload = function() {
    $('#test').css({'border':'2px solid #f00'});
};
</script>
</head>
<body>
    <p id="test">hello jQuery</p>
</body>
</html>

Cách thức hoạt động của nó là sử dụng googleđối tượng gọi http://www.google.com/jsapi tải lên windowđối tượng. Nếu đối tượng đó không có mặt, chúng tôi cho rằng việc truy cập vào Google không thành công. Nếu đó là trường hợp, chúng tôi tải một bản sao cục bộ bằng cách sử dụng document.write. (Tôi đang sử dụng máy chủ của riêng tôi trong trường hợp này, vui lòng sử dụng máy chủ của riêng bạn để kiểm tra điều này).

Tôi cũng kiểm tra sự hiện diện của window.google.load- tôi cũng có thể typeofkiểm tra xem mọi thứ là đối tượng hay chức năng phù hợp. Nhưng tôi nghĩ rằng điều này không có mẹo.

Đây chỉ là logic tải, vì việc tô sáng mã dường như không thành công kể từ khi tôi đăng toàn bộ trang HTML mà tôi đang kiểm tra:

if (window.google && window.google.load) {
    google.load("jquery", "1.3.2");
} else {
    document.write('<script type="text/javascript" src="http://joecrawford.com/jquery-1.3.2.min.js"><\/script>');
}

Mặc dù tôi phải nói, tôi không chắc chắn rằng nếu đây là mối lo ngại cho khách truy cập trang web của bạn, bạn hoàn toàn không nên sử dụng API Thư viện AJAX của Google .

Sự thật thú vị : Ban đầu tôi đã thử sử dụng một khối try..catch cho điều này trong các phiên bản khác nhau nhưng không thể tìm thấy sự kết hợp nào sạch như thế này. Tôi rất muốn thấy những triển khai khác của ý tưởng này, hoàn toàn là một bài tập.


1
Lợi thế của việc sử dụng google.load trong tình huống này là gì, thay vì tải ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js, như Rony đề xuất? Tôi đoán việc tải nó cũng trực tiếp nắm bắt các vấn đề với các thư viện đã bị xóa (điều gì sẽ xảy ra nếu Google ngừng phục vụ JQuery 1.3.2). Hơn nữa, phiên bản của Rony thông báo các sự cố mạng SAU www.google.com.vn/jsapi đã được tìm nạp, đặc biệt là khi jsapi đã được tải từ bộ đệm? Người ta có thể cần phải sử dụng cuộc gọi lại google.load để chắc chắn (hoặc có thể có một số giá trị trả về để bao gồm google.load trong if (..)).
Arjan

Nếu một người đang kiểm tra sự hiện diện của Google.com, người ta có thể thực hiện cuộc gọi mạng hoặc người ta có thể kiểm tra sự hiện diện của đối tượng "người gác cổng". Những gì tôi đang làm là kiểm tra đối tượng google và chức năng "tải" của nó. Nếu cả hai đều thất bại, không có google và tôi cần phiên bản địa phương. Phiên bản của Rony thực sự bỏ qua URL www.google.com.vn/jsapi, vì vậy tôi không chắc tại sao bạn chỉ ra rằng nó sẽ được tìm nạp.
artlung

Cuối cùng, tất cả những gì cần thiết là thư viện jquery đã được tải. Bất kỳ thư viện Google không phải là một yêu cầu. Trong câu trả lời của Rony, người ta biết chắc chắn nếu tải từ Google (hoặc bộ đệm) thành công. Nhưng trong kiểm tra của bạn cho "if (window.google && window.google.load)", thư viện jquery vẫn chưa được tải. Tải thực tế của thư viện jquery không được xác nhận?
Arjan

ah, tôi thấy làm thế nào tôi gây ra sự nhầm lẫn. "Phiên bản của Rony thông báo các sự cố mạng SAU www.google.com.vn/jsapi đã được tìm nạp" nên đọc tốt hơn: "Phiên bản của bạn không nhận thấy sự cố mạng SAU www.google.com.vn/jsapi đã được tải xuống".
Arjan

2
Gần đây chúng tôi đã chuyển sang sử dụng Google làm máy chủ jQuery của chúng tôi; nếu chúng tôi nhận được bất kỳ báo cáo lỗi nào từ người dùng bị chặn, tôi sẽ sử dụng một biến thể câu trả lời của bạn để cấu trúc lại mã khách hàng của chúng tôi. Câu trả lời tốt!
Jarrod Dixon

30

Nếu bạn có Modernizr.js được nhúng trên trang web của mình, bạn có thể sử dụng yepnope.js tích hợp để tải các tập lệnh của mình một cách không đồng bộ - trong số các jQuery khác (có dự phòng).

Modernizr.load([{
    load : '//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js'
},{
    test : window.jQuery,
    nope : 'path/to/local/jquery-1.7.2.min.js',
    both : ['myscript.js', 'another-script.js'],
    complete : function () {
        MyApp.init();
    }
}]);

Điều này tải jQuery từ Google-cdn. Sau đó, nó đã được kiểm tra, nếu jQuery được tải thành công. Nếu không ("không"), phiên bản cục bộ được tải. Ngoài ra, các tập lệnh cá nhân của bạn được tải - "cả hai" cho biết, quá trình tải được đặt độc lập với kết quả của bài kiểm tra.

Khi tất cả các quá trình tải hoàn tất, một hàm sẽ được thực thi, trong trường hợp 'MyApp.init'.

Cá nhân tôi thích cách tải tập lệnh không đồng bộ này. Và vì tôi dựa vào các bài kiểm tra tính năng được cung cấp bởi Modernizr khi xây dựng một trang web, dù sao tôi cũng đã nhúng nó vào trang web. Vì vậy, thực sự không có chi phí.


2
Tôi nghĩ bạn đang thiếu điểm chính của câu hỏi - bạn sẽ tải tập lệnh moernizr từ CDN như thế nào?
George Filippakos

2
Tôi không thể khuyên bạn nên tải Modernizr từ CDN. Thay vào đó, bạn nên có bản dựng tùy chỉnh nhỏ nhất từ ​​Modernizr.com.
Emanuel Kluge

2
Vì vậy, tùy chọn này được +16, so với 500/200 + các tùy chọn khác đang nhận được. Nhưng điều này nghe có vẻ khá tốt. Có phải nó không phổ biến do dựa vào Modernizer? Tôi tình cờ sử dụng Modernizer trong trang web của chúng tôi, vì vậy nếu điều này tốt hơn các câu trả lời khác, ai đó có thể cho tôi biết không? Tôi khá mới với JQuery, vì vậy việc làm rõ được đánh giá cao.
redfox05

2
Đây là một lựa chọn thực sự tốt trong thời gian của câu trả lời, nhưng vào năm 2015, yepnope.jskhông được chấp nhận. xem stackoverflow.com/questions/33986561/
Mạnh

Modernizr được tạo ra để giải quyết vấn đề giống như câu hỏi này. +1
Carlos Quijano

21

Có một số giải pháp tuyệt vời ở đây, nhưng tôi muốn đưa nó thêm một bước nữa về tệp cục bộ.

Trong trường hợp Google thất bại, nó sẽ tải một nguồn cục bộ nhưng có thể một tệp vật lý trên máy chủ không nhất thiết là lựa chọn tốt nhất. Tôi đưa ra điều này bởi vì tôi hiện đang thực hiện cùng một giải pháp, chỉ tôi muốn quay lại một tệp cục bộ được tạo bởi một nguồn dữ liệu.

Lý do của tôi cho điều này là tôi muốn có một chút suy nghĩ khi theo dõi những gì tôi tải từ Google so với những gì tôi có trên máy chủ cục bộ. Nếu tôi muốn thay đổi phiên bản, tôi sẽ muốn đồng bộ hóa bản sao cục bộ của mình với những gì tôi đang cố tải từ Google. Trong một môi trường có nhiều nhà phát triển, tôi nghĩ cách tiếp cận tốt nhất sẽ là tự động hóa quá trình này để tất cả những gì phải làm là thay đổi số phiên bản trong tệp cấu hình.

Đây là giải pháp đề xuất của tôi nên hoạt động trên lý thuyết:

  • Trong tệp cấu hình ứng dụng, tôi sẽ lưu trữ 3 thứ: URL tuyệt đối cho thư viện, URL cho API JavaScript và số phiên bản
  • Viết một lớp lấy nội dung tệp của chính thư viện (lấy URL từ cấu hình ứng dụng), lưu trữ nó trong nguồn dữ liệu của tôi với tên và số phiên bản
  • Viết một trình xử lý kéo tệp cục bộ của tôi ra khỏi db và lưu trữ tệp cho đến khi số phiên bản thay đổi.
  • Nếu nó thay đổi (trong cấu hình ứng dụng của tôi), lớp của tôi sẽ lấy nội dung tệp dựa trên số phiên bản, lưu nó dưới dạng bản ghi mới trong nguồn dữ liệu của tôi, sau đó trình xử lý sẽ khởi động và phục vụ phiên bản mới.

Về lý thuyết, nếu mã của tôi được viết đúng, tất cả những gì tôi cần làm là thay đổi số phiên bản trong cấu hình ứng dụng của tôi sau đó là viola! Bạn có một giải pháp dự phòng được tự động hóa và bạn không phải duy trì các tệp vật lý trên máy chủ của mình.

Mọi người nghĩ gì? Có thể đây là quá mức cần thiết, nhưng nó có thể là một phương pháp tao nhã để duy trì các thư viện AJAX của bạn.

Acorn


Nếu bạn đang làm tất cả những gì chỉ hoạt động cho jQuery, thì tôi sẽ nói nó quá mức cần thiết. Tuy nhiên, nếu bạn đã có sẵn một số thành phần cho các phần khác của ứng dụng của mình (ví dụ: nếu bạn đã tải tập lệnh từ DB) thì nó trông khá đẹp.
Michael Haren

1
+1 vì kỹ lưỡng và mới lạ, mặc dù tôi không tin rằng lợi ích biện minh cho thời gian và độ phức tạp của nhà phát triển.
Nhà Cory

20
if (typeof jQuery == 'undefined') {
// or if ( ! window.jQuery)
// or if ( ! 'jQuery' in window)
// or if ( ! window.hasOwnProperty('jQuery'))    

  var script = document.createElement('script');
  script.type = 'text/javascript';
  script.src = '/libs/jquery.js';

  var scriptHook = document.getElementsByTagName('script')[0];
  scriptHook.parentNode.insertBefore(script, scriptHook);

}

Sau khi bạn cố gắng đưa bản sao của Google từ CDN.

Trong HTML5, bạn không cần đặt typethuộc tính.

Bạn cũng có thể dùng...

window.jQuery || document.write('<script src="/libs/jquery.js"><\/script>');

2
+1 trông gọn gàng hơn. có một lỗi đánh máy nhỏ ở đầu mà tôi không thể xóa vì nó rất nhỏ hai dấu ngoặc đóng sau 'không xác định'
naveen

1
Tùy chọn đầu tiên tránh cảnh báo Chrome[Violation] Avoid using document.write().
Bob Stein

Thật không may, tùy chọn đầu tiên không xuất hiện để tải đồng bộ . Lựa chọn thứ hai nào .
Bob Stein

10

Bạn có thể muốn sử dụng tệp cục bộ của mình như là phương sách cuối cùng.

Có vẻ như bây giờ CDN của jQuery không hỗ trợ https. Nếu nó đã làm bạn sau đó có thể muốn tải từ đó đầu tiên.

Vì vậy, đây là chuỗi: Google CDN => Microsoft CDN => Bản sao cục bộ của bạn.

<!-- load jQuery from Google's CDN -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> 
<!-- fallback to Microsoft's Ajax CDN -->
<script> window.jQuery || document.write('<script src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.3.min.js">\x3C/script>')</script> 
<!-- fallback to local file -->
<script> window.jQuery || document.write('<script src="Assets/jquery-1.8.3.min.js">\x3C/script>')</script> 

Có thực sự cần nhiều hơn một dự phòng? nếu cả hai đều ngoại tuyến, người dùng sẽ đợi hơn một phút trước khi xem trang web của bạn
George Filippakos

1
Nó không mất 1 phút để kịch bản không tải được, phải không.
Edward Olamisan

@ Geo1701 và Edward, Thực sự không cần thứ ba. Ngay cả một dự phòng vẫn chưa được chứng minh là đáng tin cậy. Nếu Google API ngừng hoạt động, tôi chưa thấy bất kỳ đảm bảo nào cho lần thử đầu tiên sẽ thất bại. Tôi đã trải nghiệm một trường hợp tình huống trong đó CDN không bao giờ tải, giữ trang từ bao giờ kết xuất, như đã đề cập ở đây: stevesouders.com/blog/2013/03/18/http-archive-jquery/ canh
hexalys

6

Tải có điều kiện phiên bản jQuery mới nhất / cũ và dự phòng:

<!--[if lt IE 9]>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="/public/vendor/jquery-legacy/dist/jquery.min.js">\x3C/script>')</script>
<![endif]-->
<!--[if gte IE 9]><!-->
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="/public/vendor/jquery/dist/jquery.min.js">\x3C/script>')</script>
<!--<![endif]-->

Đây không phải là tương thích trình duyệt chéo.
Josh Habdas

Josh, vâng, đúng vậy.
neiker



4

Dưới đây là một lời giải thích tuyệt vời về điều này!

Cũng thực hiện trì hoãn tải và thời gian chờ!

http://happyworm.com/blog/2010/01/11/a-simple-and-robust-cdn-failover-for-jquery-14-in-one-line/


Câu trả lời chỉ liên kết không hữu ích và được coi là chất lượng thấp. Xem xét sao chép các bit có liên quan vào câu trả lời của bạn, với sự quy kết tất nhiên cho nguồn.
Random_user_name

@cale_b Bạn đang đùa à? Câu trả lời này đã hơn 7 tuổi, vì vậy một nhận xét như vậy là không có cơ sở.
Stuart.Sklinar

Vâng, đó là một câu trả lời cũ. Mặc dù đề nghị của họ là hợp lệ. Câu trả lời chỉ đơn thuần là liên kết ở nơi khác là ứng cử viên để xóa. Độc giả khác: meta.stackoverflow.com/q/8259
Rob

Tôi hoàn toàn đồng ý, tôi tự kiểm duyệt với các đề xuất - nhưng thật vô nghĩa khi nói điều đó 7 năm sau. Đáng lẽ nó phải được kiểm duyệt như thế 7 năm trước chứ không phải 7 năm sau.
Stuart.Sklinar

1
@ Stuart.Sklinar - nếu tôi đã nhìn thấy nó 7 năm trước, tôi sẽ có :) Tôi thấy mình ở đây đang thực hiện một số nghiên cứu và lần đầu tiên nhìn thấy điều này. Xin lỗi đã làm bạn thất vọng - Tôi nghĩ rằng công việc của chúng tôi trên SO là người quản lý trang web, điều này đôi khi có nghĩa là bình luận, chỉnh sửa hoặc cải thiện các câu hỏi hoặc câu trả lời cũ ...
Random_user_name

4

Đối với những người sử dụng ASP.NET MVC 5, hãy thêm mã này vào BundleConfig.cs của bạn để bật CDN cho jquery:

bundles.UseCdn = true;
Bundle jqueryBundle = new ScriptBundle("~/bundles/jquery", "//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js").Include("~/Scripts/jquery-{version}.js");
jqueryBundle.CdnFallbackExpression = "window.jQuery";
bundles.Add(jqueryBundle);

4

CẬP NHẬT:
Câu trả lời này hóa ra là sai. Xin vui lòng xem các ý kiến ​​cho lời giải thích thực sự.


Hầu hết các câu hỏi của bạn đã được trả lời, nhưng về phần cuối cùng:

Điều gì sẽ là mối nguy hiểm của cả hai bản sao đi qua?

Không có thực sự. Bạn sẽ lãng phí băng thông, có thể thêm vài mili giây tải xuống bản sao vô dụng thứ hai, nhưng sẽ không có hại thực sự nếu cả hai đều đi qua. Tất nhiên, bạn nên tránh điều này bằng cách sử dụng các kỹ thuật được đề cập ở trên.


5
Trên thực tế, tải jQuery hai lần có thể gây ra nhiều vấn đề, theo câu hỏi này .
ShadowCat7

tại sao bạn không tự kiểm tra và tải thủ công thư viện jquery hai lần. sau đó câu trả lời sẽ được tiết lộ.
luke_mclachlan

Tại sao chính xác là nó sai? @ ShadowCat7 bạn có thể nói cụ thể hơn về các vấn đề mà nó gây ra không? Vấn đề duy nhất tôi thấy được xác định rõ ràng trong câu hỏi bạn liên kết là "xóa tất cả các plugin đã tải trước đó." Nhưng điều đó không nên áp dụng để tải cùng một tệp jQuery hai lần, phải không? Tôi yêu cầu bởi vì các giải pháp khác ở đây cho dự phòng cục bộ rất phức tạp và document.write bị coi là xấu xa ở một số nơi .
Bob Stein

2

Tôi đã tạo một Gist nên tải động jQuery nếu nó chưa được tải và nếu nguồn không thành công, nó sẽ chuyển sang dự phòng (được ghép từ nhiều câu trả lời): https://gist.github.com/tigerhawkvok/9673154

Xin lưu ý rằng tôi dự định cập nhật Gist nhưng không có câu trả lời này, vì những gì nó đáng giá!

/* See https://gist.github.com/tigerhawkvok/9673154 for the latest version */
function cascadeJQLoad(i) { // Use alternate CDNs where appropriate to load jQuery
    if (typeof(i) != "number") i = 0;
    // the actual paths to your jQuery CDNs
    var jq_paths = [
        "ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js",
        "ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.0.min.js"
    ];
    // Paths to your libraries that require jQuery
    var dependent_libraries = [
        "js/c.js"
    ];
    if (window.jQuery === undefined && i < jq_paths.length) {
        i++;
        loadJQ(jq_paths[i], i, dependent_libraries);
    }
    if (window.jQuery === undefined && i == jq_paths.length) {
        // jQuery failed to load
        // Insert your handler here
    }
}

/***
 * You shouldn't have to modify anything below here
 ***/

function loadJQ(jq_path, i, libs) { //load jQuery if it isn't already
    if (typeof(jq_path) == "undefined") return false;
    if (typeof(i) != "number") i = 1;
    var loadNextJQ = function() {
        var src = 'https:' == location.protocol ? 'https' : 'http';
        var script_url = src + '://' + jq_path;
        loadJS(script_url, function() {
            if (window.jQuery === undefined) cascadeJQLoad(i);
        });
    }
    window.onload = function() {
        if (window.jQuery === undefined) loadNextJQ();
        else {
            // Load libraries that rely on jQuery
            if (typeof(libs) == "object") {
                $.each(libs, function() {
                    loadJS(this.toString());
                });
            }
        }
    }
    if (i > 0) loadNextJQ();
}

function loadJS(src, callback) {
    var s = document.createElement('script');
    s.src = src;
    s.async = true;
    s.onreadystatechange = s.onload = function() {
        var state = s.readyState;
        try {
            if (!callback.done && (!state || /loaded|complete/.test(state))) {
                callback.done = true;
                callback();
            }
        } catch (e) {
            // do nothing, no callback function passed
        }
    };
    s.onerror = function() {
        try {
            if (!callback.done) {
                callback.done = true;
                callback();
            }
        } catch (e) {
            // do nothing, no callback function passed
        }
    }
    document.getElementsByTagName('head')[0].appendChild(s);
}

/*
 * The part that actually calls above
 */

if (window.readyState) { //older microsoft browsers
    window.onreadystatechange = function() {
        if (this.readyState == 'complete' || this.readyState == 'loaded') {
            cascadeJQLoad();
        }
    }
} else { //modern browsers
    cascadeJQLoad();
}

2

Google lưu trữ jQuery

  • Nếu bạn quan tâm đến các trình duyệt cũ hơn, chủ yếu là các phiên bản IE trước IE9, thì đây là phiên bản jQuery tương thích rộng rãi nhất
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
  • Nếu bạn không quan tâm đến oldIE, thì cái này nhỏ hơn và nhanh hơn:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

Kế hoạch dự phòng / dự phòng!

  • Dù bằng cách nào, bạn nên sử dụng dự phòng cho địa phương trong trường hợp Google CDN không thành công (không có khả năng) hoặc bị chặn ở vị trí mà người dùng của bạn truy cập trang web của bạn từ (rất có thể), như Iran hoặc đôi khi là Trung Quốc.
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>if (!window.jQuery) { document.write('<script src="/path/to/your/jquery"><\/script>'); }
</script>

Tham khảo: http://websitespeedoptimizes.com/ContentDeliveryNetworkPost.aspx


Lưu ý tải tập lệnh qua các giao thức không an toàn sẽ mở ra một vectơ tấn công XSS.
Josh Habdas

2

Tôi nghĩ rằng nên thoát khỏi <đến \ x3C cuối cùng trong chuỗi. Khi trình duyệt nhìn thấy, nó coi đây là phần cuối của khối tập lệnh (vì trình phân tích cú pháp HTML không có ý tưởng gì về JavaScript, nên nó không thể phân biệt giữa một thứ chỉ xuất hiện trong một chuỗi và một cái gì đó thực sự có nghĩa là kết thúc tập lệnh thành phần). Vì vậy, xuất hiện theo nghĩa đen trong JavaScript, bên trong trang HTML sẽ (trong trường hợp tốt nhất) gây ra lỗi và (trong trường hợp xấu nhất) là một lỗ hổng bảo mật rất lớn.

<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.0.0.min.js"></script>
<script>window.jQuery || document.write('<script src="js/jquery-2.0.0.min.js">\x3C/script>')</script>

2
if (typeof jQuery == 'undefined')) { ...

Hoặc là

if(!window.jQuery){

Sẽ không hoạt động nếu phiên bản cdn không được tải, bởi vì trình duyệt sẽ chạy qua điều kiện này và trong khi nó vẫn tải xuống phần còn lại của javascripts cần jQuery và nó trả về lỗi. Giải pháp là tải các tập lệnh thông qua điều kiện đó.

    <script src="http://WRONGPATH.code.jquery.com/jquery-1.4.2.min.js" type="text/javascript"></script><!--  WRONGPATH for test-->
  <script type="text/javascript">
  function loadCDN_or_local(){
    if(!window.jQuery){//jQuery not loaded, take a local copy of jQuery and then my scripts
      var scripts=['local_copy_jquery.js','my_javascripts.js'];
      for(var i=0;i<scripts.length;i++){
      scri=document.getElementsByTagName('head')[0].appendChild(document.createElement('script'));
      scri.type='text/javascript';
      scri.src=scripts[i];
    }
  }
  else{// jQuery loaded can load my scripts
    var s=document.getElementsByTagName('head')[0].appendChild(document.createElement('script'));
    s.type='text/javascript';
    s.src='my_javascripts.js';
  }
  }
  window.onload=function(){loadCDN_or_local();};
  </script>

Tôi đã tìm thấy một vấn đề trong việc kiểm tra tập lệnh trong Google Chrome - bộ nhớ đệm. Vì vậy, để thử nghiệm cục bộ, chỉ cần thay src trong phần khác bằng một cái gì đó như s.src = 'my_javascripts.js' + '?' + Math.floor (Math.random () * 10001);
Mirek Komárek

Câu trả lời của Alex sẽ không hoạt động nếu phiên bản cdn không được tải, bởi vì trình duyệt sẽ chạy qua điều kiện này và trong khi nó vẫn tải xuống phần còn lại của javascripts cần jquery và nó trả về lỗi -> Các tệp JavaScript được tải xuống sẽ chặn đoạn mã tiếp theo được chạy vì vậy nó không phải là một vấn đề .
alex

2

Hầu như tất cả các CDN công khai đều khá đáng tin cậy. Tuy nhiên, nếu bạn lo lắng về tên miền google bị chặn, thì bạn có thể chỉ cần dự phòng một CDN jQuery thay thế . Tuy nhiên, trong trường hợp như vậy, bạn có thể thích làm theo cách ngược lại và sử dụng một số CDN khác làm tùy chọn ưa thích và dự phòng cho Google CDN để tránh các yêu cầu thất bại và thời gian chờ đợi:

<script src="https://pagecdn.io/lib/jquery/3.2.1/jquery.min.js"></script>
<script>
   window.jQuery || document.write('<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"><\/script>');
</script>

1

Sử dụng cú pháp dao cạo trong ASP.NET, mã này cung cấp hỗ trợ dự phòng và hoạt động với một gốc ảo:

@{var jQueryPath = Url.Content("~/Scripts/jquery-1.7.1.min.js");}
<script type="text/javascript">
    if (typeof jQuery == 'undefined')
        document.write(unescape("%3Cscript src='@jQueryPath' type='text/javascript'%3E%3C/script%3E"));
</script>

Hoặc tạo một người trợ giúp ( tổng quan về người trợ giúp ):

@helper CdnScript(string script, string cdnPath, string test) {
    @Html.Raw("<script src=\"http://ajax.aspnetcdn.com/" + cdnPath + "/" + script + "\" type=\"text/javascript\"></script>" +
        "<script type=\"text/javascript\">" + test + " || document.write(unescape(\"%3Cscript src='" + Url.Content("~/Scripts/" + script) + "' type='text/javascript'%3E%3C/script%3E\"));</script>")
}

và sử dụng nó như thế này:

@CdnScript("jquery-1.7.1.min.js", "ajax/jQuery", "window.jQuery")
@CdnScript("jquery.validate.min.js", "ajax/jquery.validate/1.9", "jQuery.fn.validate")

Tôi chưa bao giờ quan tâm đến Dao cạo râu, nhưng nó trông giống như một obfuscator, ngoại trừ việc nó làm cho mã dài hơn thay vì ngắn hơn (nó dài gấp đôi cái này .
maaartinus

@maaartinus: Đó không phải là một so sánh táo với táo. Câu trả lời của BenjaminRH, mà bạn đề cập đến, là dành cho một tập lệnh được lưu trữ trên CDN. Với trình CdnScripttrợ giúp, bạn chỉ cần một dòng mã cho mỗi tập lệnh . Bạn càng có nhiều kịch bản, số tiền chi trả càng lớn.
Edward Brey

Chắc chắn ... đó chỉ là một lời nói. Tuy nhiên, tôi đoán đó không phải là cách tối ưu. Nếu có bất cứ điều gì thất bại, tôi sẽ bỏ qua CDN hoàn toàn và chuyển sang dự phòng cho tất cả các tập lệnh. Tôi không chắc liệu điều này có thể thực hiện được không vì tôi không biết cách tải chính xác hoạt động.
maaartinus

@maaartinus: Vì mỗi lần tải tập lệnh CDN có thể bị lỗi độc lập, bạn phải kiểm tra riêng từng tải. Không có phương pháp đáng tin cậy nào cho việc kiểm tra CDN duy nhất theo sau bằng cách tải tất cả các tập lệnh từ CDN so với cục bộ.
Edward Brey

Trường hợp làm tôi lo lắng là sự thất bại của trang CDN dẫn đến thời gian chờ đợi cho nhiều lần tải. Vì vậy, tôi muốn có một cái gì đó như try { for (Script s : ...) cdnLoad(s); } catch (...) { for (Script s : ...) ownLoad(s); }. Dịch điều này thành một loạt các ifs có thể là một cơn ác mộng.
maaartinus

1

Mặc dù việc viết document.write("<script></script>")có vẻ dễ dàng hơn đối với jQuery backoff, Chrome đưa ra lỗi xác thực trong trường hợp đó. Vì vậy, tôi thích phá vỡ từ "kịch bản". Vì vậy, nó trở nên an toàn hơn như trên.

<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.1.min.js"></script>
<script>if (typeof jQuery === "undefined") {
   window.jqFallback = true;
   document.write("<scr"+"ipt src='http://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.1/jquery.min.js'></scr"+"ipt>");
} </script>

Đối với các vấn đề dài hạn, sẽ tốt hơn nếu ghi nhật ký dự phòng JQuery. Trong đoạn mã trên, nếu CDN đầu tiên không có sẵn thì JQuery được tải từ một CDN khác. Nhưng bạn có thể muốn biết CDN sai lầm đó và xóa nó vĩnh viễn. (trường hợp này là trường hợp rất đặc biệt) Ngoài ra, tốt hơn là ghi nhật ký các vấn đề dự phòng. Vì vậy, bạn có thể gửi các trường hợp sai sót với AJAX. Do JQuery không được xác định, bạn nên sử dụng javilla javascript cho yêu cầu AJAX.

<script type="text/javascript">
    if (typeof jQuery === 'undefined' || window.jqFallback == true) {
        // XMLHttpRequest for IE7+, Firefox, Chrome, Opera, Safari
        // ActiveXObject for IE6, IE5
        var xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
        var url = window.jqFallback == true ? "/yourUrl/" : "/yourUrl2/";
        xmlhttp.open("POST", url, true);
        xmlhttp.send();
    }
</script>


0

Một dự phòng khác thay thế ajax.googleapis.com bằng cdnjs.cloudflare.com :

(function (doc, $)
{
    'use strict';

    if (typeof $ === 'undefined')
    {
        var script = doc.querySelector('script[src*="jquery.min.js"]'),
            src = script.src.replace('ajax.googleapis.com', 'cdnjs.cloudflare.com');

        script.parentNode.removeChild(script);
        doc.write('<script src="' + src + '"></script>');
    }
})(document, window.jQuery || window.Zepto);
  • Bạn có thể dính vào một phiên bản jQuery bằng cách chỉ định nó trong chuỗi
  • Hoàn hảo cho Quản lý tài sản không hoạt động với các đoạn mã HTML
  • Thử nghiệm trong tự nhiên - hoạt động hoàn hảo cho người dùng từ Trung Quốc

Bạn có thể giải thích về tuyên bố sau: "Bạn không cần phải quan tâm đến phiên bản jQuery"?
Josh Habdas

Phiên bản này là một phần của URL không được chạm vào bằng cách tiếp cận này ... jquery / 3.xx / jquery.min.js
redaxmedia

1
Điều đó có khả năng gây ra sự cố khi jQuery chuyển sang phiên bản 4 và đưa ra các thay đổi không tương thích ngược không?
Josh Habdas

-1 vì điều đó sẽ gây ra sự cố nếu jQuery giới thiệu các thay đổi vi phạm mà tập lệnh của bạn chưa hỗ trợ trừ khi phiên bản được chỉ định.
Lookaji

@lookaji Tôi nghĩ bạn không hiểu dự phòng. Nó không thay thế tên miền nơi nó được lưu trữ và KHÔNG chạm vào tên tệp / phiên bản nào cả.
redaxmedia

0

Bạn có thể sử dụng mã như:

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>window.jQuery || document.write('<script type="text/javascript" src="./scripts/jquery.min.js">\x3C/script>')</script>

Nhưng cũng có những thư viện bạn có thể sử dụng để thiết lập một số dự phòng có thể có cho tập lệnh của mình và tối ưu hóa quá trình tải:

  • giỏ.js
  • Yêu cầuJS
  • yepnope

Ví dụ:

Basket.js Tôi nghĩ rằng biến thể tốt nhất bây giờ. Sẽ lưu trữ tập lệnh của bạn trong localStorage, điều đó sẽ tăng tốc độ tải tiếp theo. Cuộc gọi đơn giản nhất:

basket.require({ url: '/path/to/jquery.js' });

Điều này sẽ trả lại một lời hứa và bạn có thể thực hiện cuộc gọi tiếp theo do lỗi hoặc tải phụ thuộc vào thành công:

basket
    .require({ url: '/path/to/jquery.js' })
    .then(function () {
        // Success
    }, function (error) {
        // There was an error fetching the script
        // Try to load jquery from the next cdn
    });

Yêu cầuJS

requirejs.config({
    enforceDefine: true,
    paths: {
        jquery: [
            '//ajax.aspnetcdn.com/ajax/jquery/jquery-2.0.0.min',
            //If the CDN location fails, load from this location
            'js/jquery-2.0.0.min'
        ]
    }
});

//Later
require(['jquery'], function ($) {
});

yepnope

yepnope([{
  load: 'http://ajax.aspnetcdn.com/ajax/jquery/jquery-2.0.0.min.js',
  complete: function () {
    if (!window.jQuery) {
      yepnope('js/jquery-2.0.0.min.js');
    }
  }
}]);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.