How to merge Javascript files in WordPress into one file. Combining objects Combine js into one file

77

I'm trying to optimize site performance by consolidating and compressing css files and JS. My question is more related to the (concrete) steps on how to achieve this, given the actual situation I'm facing (although this should be common for other developers as well).

For a product release, I would like to merge 3 CSS files into one and minify it using e.g. YUI Compressor. But then I would need to update all pages that need those 3 files to reference the newly changed CSS. It seems to be error prone (e.g. you delete and add some lines in many files). Any other less risky approach? Same issue for JS files.

  • 13 responses
  • Sorting:

    Activity

12

You can run it in an ant task and therefore include it in your messages/pre commit hooks if you are using svn/git.

UPDATE: Currently I'm using grunt with CONCAT, downplay & mutilate contributions. You can use it with a watcher so that it creates new minifiles in the background whenever the source changes. uglify contrib not only breaks the console logs, but also removes unused functions and properties.

19

I will need to update all pages that need these 3 files to reference the newly rooted CSS.

First, I would say that you should have a general title. Therefore, when it is necessary, it is not necessary to change all the headers. It's good practice to have one heading or 2-3. Since your page is needed, you can change your title. So when you want to extend your web application, it will be less risky and tedious.

You didn't mention your development environment. You can see that there are many compressing tools listed for different environments . And you use good tool i.e. YUI Compressor.

6

I don't see you mention content management system (Wordpress, Joomla, Drupal, etc) but if you are using any popular CMS they have all plugins/modules available (free options) that will minify and cache your css and js.

Using a plugin gives you the ability to keep uncompressed versions editable, and then when you make changes, the plugin automatically includes your changes and recompresses the file. Just make sure you choose a plugin that will allow you to exclude files (like a custom js file) if it breaks anything.

I have tried in the past to keep these files by hand and it always turns into a maintenance nightmare. Good luck, hope this helped.

3

If you're doing pre-processing on the files you're serving, you'll probably want to set up a proper build system (like a Makefile). This way you have source files with no duplication and whenever you make changes you run "make" and update all automatically generated files. If the build system is already installed, learn how it works and uses it. If not, you need to add it.

So first figure out how to merge and minify your files from command line(in the YUICompressor documentation). Designate a directory for the auto-generated stuff, separate from the stuff you're working on but available to the web server, and output there, like gen/scripts/combination.js. Put the commands you used in the Makefile and repeat "make" every time you made a change and want it to take effect. Then update the headers in the other files to point to the combo and mini files.

5

For people who want something a little lighter and more flexible, I created js.sh today to solve this problem. It's a simple command line tool targeting JS files that can be easily modified to take care of CSS files. Advantages:

  • easily configured for use by multiple developers on a project
  • Combines JS files in the order specified in script_order.txt
  • compresses them with Google's Closure Compiler
  • Splits JS into< 25kb куски где возможно, так как iPhone не будет кэшировать что-либо большее, чем 25kb.
  • Creates a small PHP file with

    ) мы можем определить это используя хук wp_footer.

    Открываем на редактирование файл functions.php, расположенный в папке темы которая используется, и добавляем туда код:

    Код: add_action("wp_head", "show_head_scripts", 9999);
    add_action("wp_footer", "show_footer_scripts", 9999);

    // Появиться сверху, перед открытием body
    function show_head_scripts(){
    global $wp_scripts;
    echo "

    "; print_r($wp_scripts->done); echo "
    ";
    }
    // Появляются внизу, после подвала
    function show_footer_scripts(){
    global $wp_scripts;
    echo "
    "; print_r($wp_scripts->done); echo "
    ";
    }

    Теперь открываем страницу, заглядываем в её исходник и видим там списки путей к JS-файлам (в верхней и нижней частях страницы).

    Объединение файлов javascript в один файл в WordPress

    Для объединения нужно собрать пути к файлам, которые можно обнаружить автоматически до отображения контента. Для этого подойдет хук wp_enqueue_scripts. Тут есть некоторые недостатки (описанные ниже), но это единственный трюк, который мы можем использовать автоматически.

    Как это делается (описание логики кода):

    1.) Копируется дескриптор файла javascript в соответствии с его зависимостью, чтобы после слияния он смог работать без ошибок. Мы можем сделать это, вызвав метод all_deps в объекте WP_Scripts ($ wp_scripts-> all_deps ($ wp_scripts-> queue));

    2.) Получения кода в файлах javascript (используя file_get_contents) и комбинация с остальными. Включая скрипт localize wp_localize_script (если есть). Этот скрипт можно найти в $ wp_scripts-> registered ["handle"] -> extra ["data"]

    3.) Запись комбинированного кода в файл (используя file_put_contents) и загрузка его с помощью функции wp_enqueue_scripts.

    4.) Отмена регистрацию всех скриптов / дескрипторов, которые были объединены, это делается после завершения процесса описанного в прошлом пункте (если мы отменим регистрацию сценария, тогда его зависимый скрипт также будет снят с регистрации).

    Чтобы движок проделал все эти задачи, вставьте следующий код в файл functions.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);

    // New file location: E:xampp\htdocs\wordpresswp-content\theme\wdc\merged-script.js
    $merged_file_location = get_stylesheet_directory() . DIRECTORY_SEPARATOR . "merged-script.js";

    $merged_script = "";

    // Loop javascript files and save to $merged_script variable
    foreach($wp_scripts->to_do as $handle)
    {
    /*
    Clean up url, for example wp-content/themes/wdc/main.js?v=1.2.4
    become wp-content/themes/wdc/main.js
    */
    $src = strtok($wp_scripts->registered[$handle]->src, "?");

    /**
    #2. Combine javascript file.
    */
    // If src is url http / https
    if (strpos($src, "http") !== false)
    {
    // Get our site url, for example: http://webdevzoom.com/wordpress
    $site_url = site_url();

    /*
    If we are on local server, then change url to relative path,
    e.g. http://webdevzoom.com/wordpress/wp-content/plugins/wpnewsman/css/menuicon.css
    become: /wp-content/plugins/wpnewsman/css/menuicon.css,
    this is for reduse the HTTP Request

    If not, e.g. https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css,
    then leave as is (we"ll skip it)
    */
    if (strpos($src, $site_url) !== false)
    $js_file_path = str_replace($site_url, "", $src);
    else
    $js_file_path = $src;

    /*
    To be able to use file_get_contents function we need to remove slash,
    e.g. /wp-content/plugins/wpnewsman/css/menuicon.css
    become wp-content/plugins/wpnewsman/css/menuicon.css
    */
    $js_file_path = ltrim($js_file_path, "/");
    }
    else
    {
    $js_file_path = ltrim($src, "/");
    }

    // Check wether file exists then merge
    if (file_exists($js_file_path))
    {
    // #3. Check for 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) . ";";
    }
    }

    // write the merged script into current theme directory
    file_put_contents ($merged_file_location , $merged_script);

    // #4. Load the URL of merged file
    wp_enqueue_script("merged-script", get_stylesheet_directory_uri() . "/merged-script.js");

    // 5. Deregister handles
    foreach($wp_scripts->to_do as $handle)
    {
    wp_deregister_script($handle);
    }
    }

    Проверяем, что слияние прошло успешно

    Идем на страницу блога, открываем исходник и ищем в нем подключенный файл merged-script.js

    Затем убедитесь, что в объединенном скрипте нет ошибок, для этого откройте «инструменты разработчика» браузера (нажмите F12 в Google Chrome) и выберите вкладку Console.

    Консоль показывает текст ошибки и ссылается на место возникновения. Если нет ругательств на файл merged-script.js значит все ок.

    Проверьте на работоспособность остальные скрипты, которые не участвовали в объединении.

    Original article in english you cat read there.

    Объединяет содержимое двух или более заданных javascript-объектов. Результат объединения записывается в первый из этих объектов (он же будет возвращен функцией, после ее выполнения). Функция имеет два варианта использования:

    объединяет содержимое объектов target , object1 ,.., objectN , помещая результат в объект target .

    Особенности использования

    Если задать два или более объекта, то результатом будет их объединение. В случае, если вы зададите только один объект, функция extend() добавит его содержимое в глобальный объект $ (jQuery). Таким образом можно расширять возможности библиотеки, добавляя свои функции в ее пространство имен. Это может быть полезно при написании плагинов.

    Напомним, что в результате объединения объектов, первый из них будет изменен (он же будет возвращен в качестве результата выполнения функции extend()). Если нужно, чтобы ни один из заданных объектов не был изменен, то можно задать в качестве параметра target пустой объект:

    var object = $.extend ({ } , object1, object2) ;

    Рекурсивное (глубокое) копирование

    При объединении объектов, совпадающие поля переписываются:

    var object1 = { apple: 0 , cherry: 97 } ; var object2 = { apple: 5 , durian: 100 } ; $.extend (object1, object2) ; /* Результат будет следующий: { apple:5, cherry:97, durian:100 }; */

    По умолчанию, extend() выполняет поверхностное объединение объектов, это означает, что если они содержат другие объекты внутри, то extend() будет перезаписывать их как и в предыдущем случае:

    var object1 = { apple: 0 , banana: { weight: 52 , price: 100 } , cherry: 97 } ; var object2 = { banana: { price: 200 } , durian: 100 } ; $.extend (object1, object2) ; /* Результат: { apple:0, banana:{price:200}, durian:100, cherry:97, }; */

    однако, если в качестве первого параметра указать true , то будет выполнено глубокое копирование, при котором к внутренним объектам будет применяться процедура объединения (а не переписывания как в прошлом случае):

    var object1 = { apple: 0 , banana: { weight: 52 , price: 100 } , cherry: 97 } ; var object2 = { banana: { price: 200 } , durian: 100 } ; $.extend (true , object1, object2) ; /* Результат: { apple:0, banana:{weight:52, price:200}, durian:100, cherry:97, }; */