Как динамически объединить все файлы JavaScript в один

227194

На этот раз, мы обсудим, как объединить файлы JavaScript в один файл на WordPress. Этот процесс – часть оптимизации (уменьшения количества) http-запросов, для увеличения скорости сайта.

Объединение вручную

Казалось бы, самый очевидный способ объединить js файлы – просмотреть исходный код веб-страницы, найти все скрипты сайта, затем скопировать их содержимое и последовательно вставить их в новый js файл. Однако, этот метод не рекомендуется, так как имеет много недостатков:

  • Отсутствие гибкости. Если нужно добавить или удалить скрипт, то нужно заново делать это вручную.
  • Невозможно гарантировать совместимость между файлами. Это связано с определенной последовательностью подключения скриптов.
  • Если будут использованы дополнительные сторонние плагины, есть вероятность двойной загрузки скриптов, что увеличивает вес загружаемой страницы.

Учитывая все минусы данного подхода, попробуем решить его более простым способом – с использованием php.

Объединяем скрипты автоматически

Итак, определив наиболее рациональный способ решения проблемы, давайте элегантно объединим скрипты в один файл, разместив данный сниппет в function.php.

add_action( 'wp_enqueue_scripts', 'merge_all_scripts', 9999 );
function merge_all_scripts() {
	global $wp_scripts;
	/*
	#1. Reorder the handles based on its dependency, 
	The result will be saved in the to_do property ($wp_scripts->to_do)
	*/
	$wp_scripts->all_deps($wp_scripts->queue); 
 
	// Располагаем новый js файл по пути: \wp-content\theme\merged-script.js
	$merged_file_location = get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'merged-script.js';
 
	$merged_script = '';
 
	// Запускаем цикл, который последовательно сохраняет их в переменную $merged_script
	foreach( $wp_scripts->to_do as $handle) {
	/*
	Очищаем скрипт от версии, например, вместо wp-content/themes/merged-script.js?v=1.2.4
	будет wp-content/themes/merged-script.js
	*/
	$src = strtok($wp_scripts->registered[$handle]->src, '?');
 
	/**
	#2. Объединяем js файлы.
	*/
	// Учитываем протокол http / https 
	if (strpos($src, 'http') !== false) {
		// Получаем урл сайта
		$site_url = site_url();
 
		if (strpos($src, $site_url) !== false)
			$js_file_path = str_replace($site_url, '', $src);
		else
			$js_file_path = $src;
		$js_file_path = ltrim($js_file_path, '/');
	} else { 
		$js_file_path = ltrim($src, '/');
	}
 
	// Проверим, существует ли файл после слияния
	if (file_exists($js_file_path)) {
		// #3. Проверяем wp_localize_script
		$localize = '';
		if (@key_exists('data', $wp_scripts->registered[$handle]->extra)) {
			$localize = $obj->extra['data'] . ';';
		}
		$merged_script .= $localize . file_get_contents($js_file_path) . ';';
 	}
 }
 
 	// записываем скрипты в файл
 	file_put_contents ( $merged_file_location , $merged_script);
 
 	// #4. Подключаем в теме созданный скрипт
	wp_enqueue_script('merged-script', get_stylesheet_directory_uri() . '/merged-script.js');
 
	// 5. Отключаем все файлы, которые были слиты
	foreach( $wp_scripts->to_do as $handle ) {
		wp_deregister_script($handle);
	}
}

Убедитесь, что процесс объединения прошел успешно. Проверьте, что объединение скриптов прошло без ошибок. Для этого откройте инструменты разработчика в браузере (нажмите F12 для Google Chrome) и выберите вкладку “Консоль”. Если ошибок нет, то консоль не выдаст никаких предупреждений.

Следует отметить, что некоторые файлы не объединяются, например wp-embed.min.js и akismet.js. Это связано с тем, что указанные скрипты загружаются позже, чем наш фрагмент кода.

Если ошибки в консоли браузера присутствуют, проверьте исходные скрипты на наличие строк комментариев. При автоматическом слиянии, мог быть “закомментирован” нужный код.

4 comments to post “"Как динамически объединить все файлы JavaScript в один"
  • Ян Александров
    Асахаро26 Apr 2018 12:29

    Добрый! Как исключить из такого способа конкатенации инлайновые скрипты?

    Reply
    • Ян Александров
      Yan AlexandrovAuthor26 Apr 2018 13:03

      Когда столкнулся с тем, что инлайновые скрипты данное решение просто выбрасывает, сделал следующим образом:

      // #4.5. Получаем встраиваемые в html скрипты
      foreach ( $wp_scripts->registered as $k=>$v ) {
      	foreach ( $wp_scripts->to_do as $script ) {
      		if ( $k == $script ) {
      			$scr = $v->extra;
      			if ( $scr ) {
      				$allajaxs[] = $scr['data'];
      			}
      		}
      	}
      }
      
      // теперь можно вернуть на место ajax скрипты
      $allajaxs = array_diff( $allajaxs, array('') );
      foreach ( $allajaxs as $key => $value ) {
      	$inc .= '<script type="text/javascript">';
      	$inc .= '/* <![CDATA[ */';
      	$inc .= $value;
      	$inc .= '/* ]]> */';
      	$inc .= '</script>
      ';
      }
      print_r($inc);
      
      // #5. Отключаем все файлы, которые были слиты
      ...

      В $wp_scripts->registered содержится информация обо всех подключаемых скриптах. Перед тем, как отключаем слитые файлы, ищем те которые встраивают скрипты в html и выводим их.

      Reply
  • Ян Александров
    Андрей WPM7 Sep 2019 14:14

    Блин, почти сработало. Но всё равно подкосило функционал. А как можно исключить определённые скрипты из выборки?

    Reply
  • Ян Александров
    Яков29 Oct 2023 22:29

    Подскажите, пожалуйста у меня хорошо объединились скрипты в один файл. Но, произошла проблема. Не все скрипты работают и в консоли появились ошибки. Создаетс впечатление, что браузер не увидел эти скрипты, хотя файл был подключен. Я его видел через консоль разработчика. Почему может быть такая проблема. Такое впечатление, что сайт не видел скрипт, хотя он был подключер. В чем может быть проблема?

    Reply
Leave a Reply

B I PHP JS

Made with by CodyShop