wp enqueue script – Ładowanie najnowszego pliku modułu zależności javascript w functions.php
Problem
Importuj oświadczenie, takie jak:
import { export1 } from "./module-name.js";
jest nazywany statyczny import
deklaracja.
Dynamiczny ciąg zapytania (aby wymusić załadowanie najnowszego pliku) nie może być używany jako statyczny import
deklaracje. Aby rozwiązać ten problem, musisz wybrać jedną z następujących czterech opcji:
-
Usunąć
export
Iimport
instrukcje ze wszystkich plików JavaScript i umieszcza je w kolejce jako niemodułowy JavaScript. -
Nie ustawiaj się w kolejce
ads.js
w WordPress podawaj tylko numer wersjiads.js
plik jako zmienną globalną JavaScript zwp_add_inline_script()
funkcję na stronę i dynamicznie importowaćads.js
jako moduł zbanners.js
Iads-search.js
. -
Ustaw w kolejce
ads.js
jako moduł przekaż numer wersjiads.js
plik jako zmienną globalną JavaScript zwp_add_inline_script()
funkcja na stronie, kolejkujbanners.js
Iads-search.js
jako niemodułowy JavaScript (zads.js
w tablicy zależności) i dynamicznie importowaćads.js
jako moduł zbanners.js
Iads-search.js
. Różni się to nieco od opcji 2 i może przynieść pewne korzyści w zależności od implementacji. -
Użyj pakietu, takiego jak Rollup lub Webpack, i zbuduj pojedynczy zminimalizowany skrypt za pomocą obserwatora plików i umieść skompilowany zminimalizowany plik JavaScript w WordPress jako niemodułowy plik JavaScript. Poleciłbym tę metodę, ale nie wyjaśniałbym jej tutaj, ponieważ wykracza to poza zakres tego pytania.
Opcja-1: Spraw, aby wszystkie pliki JS nie były modułami
Po prostu usuń export
I import
instrukcje ze wszystkich plików JavaScript, jak poniżej:
// in ads.js
// removed the export declaration
async function selectADS(adNumber, element, adsArray) {
let usedNum = [];
let i = 0;
while (1) {
var randomNum = Math.floor(Math.random() * adsArray.length);
if (!usedNum.includes(randomNum)) {
let link = document.createElement("a");
link.setAttribute("href", adsArray[randomNum].link);
link.setAttribute("target", "_blank");
let ad = document.createElement("img");
ad.setAttribute("alt", adsArray[randomNum].alt);
ad.setAttribute("src", adsArray[randomNum].src);
element.appendChild(link);
link.appendChild(ad);
usedNum.push(randomNum);
i++;
if (i == adNumber) break;
}
}
}
// in banners.js
// call selectADS function normally, no import declaration
selectADS();
Następnie na końcu WordPress umieść je w kolejce my_custom_theme_scripts()
tak jak napisałeś w pytaniu
Opcja-2: pas ads.js
wersja do JS i dynamicznie importuj ads.js
Jeśli z jakiegoś powodu musisz zachować plik export
deklaracja w ads.js
i nadal chcesz zaimportować najnowszy plik w banners.js
I ads-search.js
będziesz musiał wprowadzić pewne zmiany w kodzie kolejkowania WordPress oraz w kodzie JavaScript banners.js
I ads-search.js
.
Na przykład twój my_custom_theme_scripts()
funkcja może wyglądać tak:
function my_custom_theme_scripts() {
$ads_version = filemtime( get_stylesheet_directory() . '/js/ads.js' );
$banners_version = filemtime( get_stylesheet_directory() . '/js/banners.js' );
wp_enqueue_script(
'banners',
get_stylesheet_directory_uri() . '/js/banners.js',
array(),
$banners_version,
true
);
wp_add_inline_script(
'banners',
'const My_Custom_Ads_Version = "' . $ads_version . '";',
'before'
);
}
W tym przypadku, ads.js
plik może być taki jak poprzednio z export
oświadczenie i banners.js
plik może dynamicznie import
to jak poniżej:
(async () => {
if( typeof My_Custom_Ads_Version !== 'undefined' ) {
const adsModule = await import( `./ads.js?ver=${My_Custom_Ads_Version}` );
const selectADS = adsModule.selectADS;
selectADS();
}
})();
Będziesz musiał wprowadzić podobne zmiany w ads-search.js
. Po tym twój kod będzie działał.
Pamiętaj, w tym przypadku export
deklaracje mogą być takie jak poprzednio (w ads.js
), ale instrukcje importu w banners.js
I ads-search.js
należy zmienić ze statycznego import
Deklaracja dynamiczna import
instrukcje, jak pokazano w powyższym kodzie.
Opcja-3: Ustaw w kolejce ads.js
jako moduł, zalicz ads.js
wersja do JS i dynamicznie importuj ads.js
Ta opcja jest bardzo podobna do Opcja 2 powyżej. Jednak opcja-2 importuje ads.js
w czasie wykonywania. Więc jeśli implementacja chce opóźnić wykonanie ads.js
moduł obiektów, ale nadal chce załadować ads.js
moduł z ładowaniem strony, to ta implementacja będzie preferowana.
Aby to zrobić, musisz najpierw podłączyć się do script_loader_tag
filtr, aby WordPress dodał type="module"
W <script>
etykietka.
Poniżej znajduje się przykładowy kod WordPress, który go implementuje:
add_filter( 'script_loader_tag', 'my_custom_module_support', PHP_INT_MAX, 2 );
function my_custom_module_support( $tag, $handle ) {
if( strpos( $handle, 'my_custom_module_' ) === 0 ) {
if( current_theme_supports( 'html5', 'script' ) ) {
return substr_replace( $tag, '<script type="module"', strpos( $tag, '<script' ), 7 );
}
else {
return substr_replace( $tag, 'module', strpos( $tag, 'text/javascript' ), 15 );
}
}
return $tag;
}
function my_custom_theme_scripts() {
$ads_version = filemtime( get_stylesheet_directory() . '/js/ads.js' );
$banners_version = filemtime( get_stylesheet_directory() . '/js/banners.js' );
// we are loading ads.js as a module.
// my_custom_module_support() function checks any handle
// that begins with "my_custom_module_" and adds type="modle"
// to print it as a ES6 module script
wp_enqueue_script(
'my_custom_module_ads',
get_stylesheet_directory_uri() . '/js/ads.js',
array(),
$ads_version,
true
);
wp_add_inline_script(
'my_custom_module_ads',
'const My_Custom_Ads_Version = "' . $ads_version . '";'
);
wp_enqueue_script(
'banners',
get_stylesheet_directory_uri() . '/js/banners.js',
array( 'my_custom_module_ads' ),
$banners_version,
true
);
}
add_action( 'wp_enqueue_scripts', 'my_custom_theme_scripts' );
Również z tą opcją ads.js
plik może być taki jak poprzednio z export
oświadczenie i banners.js
I ads-search.js
może dynamicznie import
z ads.js
jak pokazano w opcji-2 powyżej.
Jednak przy tej opcji przeglądarka się załaduje ads.js
module przed dynamicznym importem do banners.js
. Więc kiedy wykonywany jest import dynamiczny, przeglądarka użyje już załadowanego pliku.
W większości przypadków nie jest to istotne. Może to jednak mieć znaczenie, gdy wykonujesz import dynamiczny na zdarzeniu takim jak poniższy kod (zwłaszcza jeśli ads.js
ładowanie pliku zajmuje dużo czasu):
// sample ads.js code
console.log( 'ads.js loaded:START' );
export async function selectADS( adNumber, element, adsArray ) {
console.log( 'ads.js as a module loaded' );
};
console.log( 'ads.js loaded:END' );
// banners.js code
console.log( 'banners.js load:START' );
let clicked = false;
document.addEventListener( 'click', async (event) => {
if( ! clicked && typeof My_Custom_Ads_Version !== 'undefined' ) {
const adsModule = await import( `./ads.js?ver=${My_Custom_Ads_Version}` );
const selectADS = adsModule.selectADS;
selectADS();
}
clicked = true;
});
console.log( 'banners.js load:END' );
Dzięki tej implementacji, jeśli ads.js
plik jest znacznie duży i jest importowany dynamicznie tylko podczas zdarzenia, kod staje się prostszy bez konieczności czekania na zaimportowany plik.
Nie jest to jednak najważniejsza zaleta, ponieważ możesz przepisać ten kod JS, aby nadal importować wcześniej. Bardziej znaczącą zaletą tej implementacji jest użycie systemu buforowania lub pakietu, który obserwuje zmiany w kodzie HTML. Dzięki tej opcji łatwiej jest obsłużyć taki scenariusz w przeciwieństwie do opcji-2 (ponieważ z opcją-2 adj.js
nie jest widoczny z HTML).