Как правильно добавлять пользовательские JavaScript файлы на сайт?

19 авг. 2010 г., 11:18:46
Просмотры: 33.5K
Голосов: 73

Я уже добавил свои скрипты, но хотел бы узнать предпочтительный способ.
Я просто поместил тег <script> непосредственно в файл header.php моего шаблона.

Существует ли предпочтительный метод вставки внешних или пользовательских js файлов?
Как мне подключить js файл только к одной странице? (Я имею в виду главную страницу)

5
Комментарии

Отличный вопрос! Это очень распространенный вопрос, который задают люди, и нам определенно нужно иметь хорошую документацию по этому поводу.

MikeSchinkel MikeSchinkel
19 авг. 2010 г. 13:03:57

Также см. http://wordpress.stackexchange.com/questions/575/why-isnt-is-home-working-correctly

naugtur naugtur
23 авг. 2010 г. 13:23:44

Посмотрите мой вопрос нескольких дней назад, ответ на часть вашего вопроса там: - Как подключить внешние файлы jQuery/Javascript в WordPress

Ben Everard Ben Everard
19 авг. 2010 г. 12:09:50

Спасибо. Я уже видел это, но это не полностью ответило на мой вопрос.

naugtur naugtur
19 авг. 2010 г. 15:18:03

Это нормально, я знал, что это не ответит на все вопросы, но для людей, которые будут искать информацию в будущем, есть ссылка на другой пост :-)

Ben Everard Ben Everard
19 авг. 2010 г. 15:20:30
Все ответы на вопрос 4
10
82

Использование wp_enqueue_script() в вашей теме

Основной ответ заключается в использовании wp_enqueue_script() в хуке wp_enqueue_scripts для фронтенда и admin_enqueue_scripts для админки. Это может выглядеть примерно так (предполагается, что вы вызываете это из файла functions.php вашей темы; обратите внимание, как я ссылаюсь на директорию стилей):

<?php
add_action( 'wp_enqueue_scripts', 'mysite_enqueue' );

function mysite_enqueue() {
  $ss_url = get_stylesheet_directory_uri();
  wp_enqueue_script( 'mysite-scripts', "{$ss_url}/js/mysite-scripts.js" );
}

Это основы.

Предопределенные и множественные зависимые скрипты

Но допустим, вы хотите включить как jQuery, так и jQuery UI Sortable из списка стандартных скриптов, включенных в WordPress, и хотите, чтобы ваш скрипт зависел от них? Легко: просто включите первые два скрипта, используя предопределенные handles в WordPress, а для вашего скрипта укажите третий параметр в wp_enqueue_script() — массив handles скриптов, от которых он зависит, вот так:

<?php
add_action( 'wp_enqueue_scripts', 'mysite_enqueue' );

function mysite_enqueue() {
  $ss_url = get_stylesheet_directory_uri();
  wp_enqueue_script( 'mysite-scripts', "{$ss_url}/js/mysite-scripts.js", array( 'jquery', 'jquery-ui-sortable' ) );
}

Скрипты в плагине

Что если вы хотите сделать это в плагине? Используйте функцию plugins_url() для указания URL вашего Javascript-файла:

<?php
define( 'MY_PLUGIN_VERSION', '2.0.1' );
add_action( 'wp_enqueue_scripts', 'my_plugin_enqueue' );

function my_plugin_enqueue() {
  wp_enqueue_script( 'my-script', plugins_url('/js/my-script.js',__FILE__), array('jquery','jquery-ui-sortable'), MY_PLUGIN_VERSION );
}

Версионирование скриптов

Также обратите внимание, что выше мы задали для нашего плагина номер версии и передали его в качестве 4-го параметра в wp_enqueue_script(). Номер версии выводится в исходном коде как аргумент запроса в URL к скрипту и служит для принудительной загрузки браузером возможно закэшированного файла, если версия изменилась.

Загрузка скриптов только на нужных страницах

Первое правило веб-производительности гласит: Минимизируйте HTTP-запросы, поэтому по возможности следует ограничивать загрузку скриптов только там, где они необходимы. Например, если ваш скрипт нужен только в админке, ограничьте его загрузку административными страницами, используя хук admin_enqueue_scripts:

<?php
define( 'MY_PLUGIN_VERSION', '2.0.1' );
add_action( 'admin_enqueue_scripts', 'my_plugin_admin_enqueue' );

function my_plugin_admin_enqueue() {
  wp_enqueue_script( 'my-script', plugins_url( '/js/my-script.js', __FILE__ ), array( 'jquery', 'jquery-ui-sortable' ), MY_PLUGIN_VERSION );
}

Загрузка скриптов в подвале

Если ваш скрипт должен загружаться в подвале (footer), пятый параметр wp_enqueue_script() указывает WordPress отложить его и разместить в подвале (при условии, что ваша тема ведет себя правильно и действительно вызывает хук wp_footer, как и положено хорошим темам WordPress):

<?php
define( 'MY_PLUGIN_VERSION', '2.0.1' );
add_action( 'admin_enqueue_scripts', 'my_plugin_admin_enqueue' );

function my_plugin_admin_enqueue() {
  wp_enqueue_script( 'my-script', plugins_url( '/js/my-script.js', __FILE__ ), array( 'jquery', 'jquery-ui-sortable' ), MY_PLUGIN_VERSION, true );
}

Более тонкий контроль

Если вам нужен более тонкий контроль, у Ozh есть отличная статья под названием How To: Load Javascript With Your WordPress Plugin, где подробно описаны дополнительные методы.

Отключение скриптов для получения контроля

Justin Tadlock написал хорошую статью How to disable scripts and styles, если вам нужно:

  1. Объединить несколько файлов в один (результаты могут различаться для JavaScript).
  2. Загружать файлы только на страницах, где используется скрипт или стиль.
  3. Перестать использовать !important в файле style.css для простых CSS-правок.

Передача значений из PHP в JS с помощью wp_localize_script()

В своем блоге Vladimir Prelovac написал отличную статью Best practice for adding JavaScript code to WordPress plugins, где обсуждает использование wp_localize_script() для передачи значений переменных из серверного PHP в клиентский JavaScript.

Очень тонкий контроль с wp_print_scripts()

И наконец, если вам нужен очень тонкий контроль, вы можете изучить wp_print_scripts(), как описано на Beer Planet в посте How To Include CSS and JavaScript Conditionally And Only When Needed By The Posts.

Эпилог

Это все основные лучшие практики включения Javascript-файлов в WordPress. Если я что-то упустил (а я наверняка упустил), обязательно сообщите мне в комментариях, чтобы я мог добавить обновление для будущих путешественников.

19 авг. 2010 г. 13:03:06
Комментарии

Это огромная статья! Теперь у меня есть из чего выбирать ;)

naugtur naugtur
19 авг. 2010 г. 15:19:40

Хорошо, это сработало. Теперь вторая часть вопроса — как проверить, что я на главной странице?

naugtur naugtur
19 авг. 2010 г. 16:39:58

Ищите ответ здесь: http://wordpress.stackexchange.com/questions/575/why-isnt-is-home-working-correctly

naugtur naugtur
23 авг. 2010 г. 13:23:18

Используйте хук admin_init вместо проверки is_admin(). Удалите параметр версии, если используете CDN Google, иначе браузер будет хранить две версии: одну без строки запроса с других сайтов и вашу.

fuxia fuxia
10 нояб. 2010 г. 01:02:40

@toscho - Хорошее замечание, обновлю код.

MikeSchinkel MikeSchinkel
10 нояб. 2010 г. 03:11:25

@toscho Я думаю, что лучше удалять параметр ver выборочно, а не всю строку запроса (для Google это не важно, но может быть важно для более сложных URL). Смотрите мою версию в коллекции functions.php @MikeSchinkel там же есть полезный трюк с URL, который всегда загружает последнюю версию скрипта из Google CDN, недавно узнал об этом

Rarst Rarst
10 нояб. 2010 г. 09:14:12

@Rarst, да, моя функция затрагивает только URI Google CDN. В других случаях может быть полезно сохранить параметр.

fuxia fuxia
10 нояб. 2010 г. 16:39:24

Майк, возможно, тебе стоит отметить, что при объявлении массива зависимостей не нужно отдельно ставить в очередь эти скрипты. В большинстве приведённых примеров несколько вызовов enqueue на самом деле не нужны (они будут загружены в любом случае, просто потому что были указаны как зависимости).

t31os t31os
11 нояб. 2010 г. 16:28:25

@t31os - Я немного перегружен в данный момент; почему бы тебе не добавить ещё один ответ здесь, дополнив мой, с детализацией этого предложения?

MikeSchinkel MikeSchinkel
11 нояб. 2010 г. 18:27:59
Показать остальные 5 комментариев
2
11

В дополнение к прекрасной иллюстрации Майка о использовании enqueue, хочу отметить, что скрипты, включенные как зависимости, не нужно регистрировать отдельно...

Я воспользуюсь примером под заголовком Scripts in a Plugin в ответе Майка.

define('MY_PLUGIN_VERSION','2.0.1');

add_action( 'wp_enqueue_scripts', 'my_plugin_enqueue_scripts' );
function my_plugin_enqueue_scripts() {
    wp_enqueue_script('jquery');
    wp_enqueue_script('jquery-ui-sortable');
    wp_enqueue_script('my-script',plugins_url('/js/my-script.js',__FILE__),array('jquery','jquery-ui-sortable'),MY_PLUGIN_VERSION);
}

Это можно сократить до следующего вида:

define('MY_PLUGIN_VERSION','2.0.1');

add_action( 'wp_enqueue_scripts', 'my_plugin_enqueue_scripts' );
function my_plugin_enqueue_scripts() {
    wp_enqueue_script('my-script', plugins_url( '/js/my-script.js', __FILE__ ), array('jquery','jquery-ui-sortable'), MY_PLUGIN_VERSION);
}

Когда вы указываете зависимости, WordPress автоматически найдет и зарегистрирует их для вашего скрипта, поэтому вам не нужно делать отдельные вызовы для этих скриптов.

Кроме того, некоторые из вас могут задаться вопросом: может ли указание нескольких зависимостей привести к неправильному порядку загрузки скриптов? Приведу пример:

wp_enqueue_script( 'first-script', 'example/path/example_script_1.js', array('second-script','third-script') );

Если второй скрипт зависит от третьего (т.е. третий скрипт должен загружаться первым), это не имеет значения. WordPress определит приоритеты регистрации для этих скриптов и выведет их в правильном порядке. Короче говоря, WordPress автоматически разберется за вас.

13 нояб. 2010 г. 14:04:45
Комментарии

Я считаю, что init — это не лучшее место для вызова enqueue.

brasofilo brasofilo
22 сент. 2013 г. 02:14:01

Исходный код был скопирован из ответа Майка, а затем изменён для иллюстрации определённого момента. Однако вы правы, поэтому я обновил ответ, чтобы использовать более правильный и подходящий хук.

t31os t31os
28 янв. 2014 г. 16:42:20
0

Для небольших фрагментов скриптов, которые вы, возможно, не хотите включать в отдельный файл (например, потому что они генерируются динамически), WordPress 4.5 и выше предлагает функцию wp_add_inline_script. Эта функция, по сути, прикрепляет скрипт к другому скрипту.

Допустим, например, что вы разрабатываете тему и хотите, чтобы ваш клиент мог вставлять свои собственные скрипты (например, Google Analytics или AddThis) через страницу настроек. В этом случае вы можете использовать wp_add_inline_script, чтобы прикрепить этот скрипт к вашему основному JS-файлу (например, mainjs) следующим образом:

$custom_script = get_option('my-script')
if (!empty($custom_script)) wp_add_inline_script ('mainjs', $custom_script);
31 окт. 2016 г. 10:51:05
0

Мой предпочтительный способ достижения хорошей производительности — вместо использования wp_enqueue_script я применяю HEREDOC с Fetch API для асинхронной параллельной загрузки всего:

$jquery_script_path = '/wp-includes/js/jquery/jquery.js?ver=1.12.4';
$jquery_dependent_script_paths = [
  get_theme_file_uri( '/assets/js/global.js' ),
  get_theme_file_uri( '/assets/js/jquery.scrollTo.js' ),
  get_theme_file_uri( '/assets/js/skip-link-focus-fix.js' ),
  get_theme_file_uri( '/assets/js/navigation.js' )
];
$jquery_dependent_script_paths_json = json_encode($jquery_dependent_script_paths);
$inline_scripts = <<<EOD
<script>
(function () {
  'use strict';
  if (!window.fetch) return;
  /**
   * Fetch Inject v1.6.8
   * Copyright (c) 2017 Josh Habdas
   * @licence ISC
   */
  var fetchInject=function(){"use strict";const e=function(e,t,n,r,o,i,c){i=t.createElement(n),c=t.getElementsByTagName(n)[0],i.type=r.blob.type,i.appendChild(t.createTextNode(r.text)),i.onload=o(r),c?c.parentNode.insertBefore(i,c):t.head.appendChild(i)},t=function(t,n){if(!t||!Array.isArray(t))return Promise.reject(new Error("`inputs` must be an array"));if(n&&!(n instanceof Promise))return Promise.reject(new Error("`promise` must be a promise"));const r=[],o=n?[].concat(n):[],i=[];return t.forEach(e=>o.push(window.fetch(e).then(e=>{return[e.clone().text(),e.blob()]}).then(e=>{return Promise.all(e).then(e=>{r.push({text:e[0],blob:e[1]})})}))),Promise.all(o).then(()=>{return r.forEach(t=>{i.push({then:n=>{"text/css"===t.blob.type?e(window,document,"style",t,n):e(window,document,"script",t,n)}})}),Promise.all(i)})};return t}();
  fetchInject(
    $jquery_dependent_script_paths_json
  , fetchInject([
    "{$jquery_script_path}"
  ]));
})();
</script>
EOD;

Затем я вставляю их в head, иногда вместе со стилями, вот так:

function wc_inline_head() {
  global $inline_scripts;
  echo "{$inline_scripts}";
  global $inline_styles;
  echo "{$inline_styles}";
}

В результате получается водопадная загрузка, которая выглядит так — всё загружается одновременно, но порядок выполнения контролируется:

График водопадной загрузки скриптов

Примечание: Для этого требуется использование Fetch API, который поддерживается не во всех браузерах.

17 апр. 2017 г. 23:22:54