Подтвердить что ты не робот

Один JS файл для нескольких страниц

Я обычно помещаю все сценарии JavaScript в один файл, например. scripts.js (чем меньше HTTP-запрос, тем лучше). Итак, как и ожидалось, некоторые скрипты необходимы для некоторых страниц, а некоторые нет.

Чтобы настроить таргетинг на определенную страницу, я использую что-то вроде:

if ($("body#share").length > 0) {
    // Place the logic pertaining to the page with ID 'share' here...
}

// The file / script continues...

Другие или лучшие предложения? Спасибо!

Уточнение: Я не искал плюсы и минусы между объединением нескольких JS файлов в один большой файл и хранением нескольких отдельных файлов JS. Ответ на это, безусловно, "зависит от ситуации" (мы это знаем). Мой вопрос заключается в том, что, полагая, что вся моя JS-логика помещается в один большой файл, как сделать конкретный (кусок) script запускается только при загрузке соответствующей страницы? Один из способов, которыми я занимался, - использовать if ($('#id-of-target-element')) { /* run the script */}; есть лучший способ?

4b9b3361

Ответ 1

Мне нравится подход Пола Айриша... Вы не должны точно следовать ему, но общая идея очень тверда.

Это может выглядеть примерно так на вашем примере

Html

<body id="share">

Javascript для вашей страницы

YourNamespace = {
  share : {
    init : function(){
      // Place the logic pertaining to the page with ID 'share' here...
    }
  }
}

Пол ирландский Javascript, который заставляет волшебство случиться

UTIL = { 
  fire : function(func,funcname, args){
    var namespace = YourNamespace;  // indicate your obj literal namespace here

    funcname = (funcname === undefined) ? 'init' : funcname;
    if (func !== '' && namespace[func] && typeof namespace[func][funcname] == 'function'){
      namespace[func][funcname](args);
    }
  }, 

  loadEvents : function(){
    var bodyId = document.body.id;

    // hit up common first.
    UTIL.fire('common');

    // do all the classes too.
    $.each(document.body.className.split(/\s+/),function(i,classnm){
      UTIL.fire(classnm);
      UTIL.fire(classnm,bodyId);
    });

    UTIL.fire('common','finalize');
  }
};

// kick it all off here 
$(document).ready(UTIL.loadEvents);

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

YourNamespace.common.init()
YourNamespace.share.init()
YourNamespace.common.finalize()

Прочитайте его сообщение в блоге и несколько вариантов, связанных с ним.

Ответ 2

Аналогичные questions уже заданы, и правильный ответ был и всегда будет

Это зависит от ситуации.

Однако, если ваша проблема связана с минимизацией времени округления (RTT), то несомненно, что

Сочетание внешних скриптов с минимальным количеством файлов RTT и задержки при загрузке других ресурсов.

Хорошо держать его как можно меньше, но вам не обязательно строго хранить его в одном файле.

Посмотрим, почему это так.

В то время как код раздела в модульные программные компоненты является хорошим инженерная практика, импортирование модулей в HTML-страницу на время может значительно увеличить время загрузки страницы. Во-первых, для клиентов с пустой кеш, браузер должен выдать HTTP-запрос для каждого ресурса, и нести соответствующие время в оба конца. Во-вторых, большинство браузеры не позволяют загружать остальную часть страницы, пока Файл JavaScript загружается и анализируется.

Эти изображения более четко показывают, почему объединение нескольких файлов JavaScript в меньшее количество выходных файлов может значительно сократить время ожидания:

All files are downloaded serially, and take a total of 4.46 seconds to complete Все файлы загружаются серийно и занимают в общей сложности 4,46 секунды.

После свертывания файлов 13 js в 2 файла: The same 729 kilobytes now take only 1.87 seconds to download Те же самые 729 килобайт теперь занимают всего 1,87 секунды для загрузки

Изменить после разъяснения, данного Siku-Siku.Com: Сожалею! Я полностью не понял ваш вопрос. Я не знаю ни одного лучшего способа сделать конкретный (кусок) script запустим только при загрузке соответствующей страницы. Я думаю, что ваш путь достаточно хорош.

Ответ 3

Ваше предложение кажется нормальным. Однако я бы использовал атрибут HTML 5 data-, чтобы пометить каждую страницу следующим образом:

<body data-title="my_page_title">

Затем вы можете написать условный код javascript, проверив это свойство (начиная с jQuery 1.4.3):

if ($("body").data("title") === "my_page_title") {
    // Place the logic pertaining to the page with title 'my_page_title' here...
}

Это позволяет систематически группировать весь код для определенной страницы разумным способом.

Ответ 4

Другой вариант - это то, что вы могли бы иметь в HTML-коде

<script>
    callYourJSFunctionHere();  /*Things you would want to happen on Page load*/
</script>

Это будет следовать нормальному потоку страницы. Поэтому, если вы играете с элементами на странице, вам нужно будет разместить эту часть <script> в нижней части страницы, после того как все элементы будут загружены браузером.

Я не уверен на 100%, что это более эффективно, чем текущее решение, которое у вас есть, но, с другой стороны, он будет рассказывать кому-то, кто смотрит на вашу HTML-страницу, какой JavaScript будет запускаться при загрузке страницы. Это может быть полезно с точки зрения обслуживания по дороге.... не так много угадывающей игры о том, что script запускается при загрузке страницы.

Надеюсь, это поможет!

Ответ 5

Ok. Надеюсь, пример кода скажет это лучше, чем стена текста:


ваш one-and-only.js файл:

var MY_SITE = {
    // you have one namespace-object where you hold all your stuff
    main_page: {
        // inside you have smaller chunks, for specific pages or widgets
        // this one is for main page
        _init: function () {
        ... 
        },
        ... 
        showSplashScreen: function () {
        ...
        }      
    },
    ... 
    // but there are other pages
    contacts: { ... },
    // or widgets
    cool_menu: { ... },
    // and maybe you want to put common functions into dedicated block
    global_utilities: { ... },
    // and of course - the loader
    _start: function () {
        // here we simply call one _init of the page module that was specified 
        this[PAGE_TYPE]._init(); 
        // and more tricky stuff - we can search the page for elements
        // that contain special data-attribute, collect them
        var widgets = $('[data-our-widget]').each().getAttributeValue( 'data-or-widget' );
       // and then _init each of those widgets just like we did with main page 
        widgets.forEach( function (v) {
            this[v]._init();
        }
    }
};
document.on('ready', MY_SITE.start); // here we assume some random js framework

ваши теги <script> на странице:

<script>var PAGE_TYPE = 'main_page';</script>
<script src="one-and-only.js" />

ваши "магические" элементы на странице:

<div id="whatever" data-our-widget="cool_menu"> ... </div>

Отказ от ответственности: Это обзор высокого уровня! Сведения о реализации могут и должны меняться в зависимости от ваших потребностей.

Ответ 6

В вашем вопросе спрашивается, как загружать только куски ваших скриптов на основе определенной страницы. Однако, поскольку ваша заявленная цель заключается в минимизации HTTP-запросов (и трафика, я полагаю), я думаю, что моя уникальная (сложная) реализация по крайней мере актуальна для этого вопроса, если не хорошая альтернатива/дополнение к вашему подходу.

Я использую это во встроенном приложении, где я объединяю все файлы javascript в один большой для сокращения HTTP-запросов. Мне также пришлось выяснить метод кеширования. Файл с javascript объемом 120 килобайт в дополнение к нескольким изображениям с приличным размером занимает некоторое время, чтобы загрузить его при использовании веб-сервера с бай-инами на 50 килобайт.

Во-первых, я использую YUI Compressor для сжатия моих файлов javascript, так как это простой способ сэкономить пропускную способность.

Классная "функция", которую я обнаружил, была, если вы ссылаетесь на что-либо (css, js, img), как показано ниже, вы просто загрузите файл и проигнорируете параметры, прошедшие через?? в 'src':

<script type="text/Javascript" src="js/all.js?2382a97f099f42cc43c1b616cd24f281"></script>

Теперь, казалось бы, случайный беспорядок чисел и букв на самом деле является контрольной суммой md5 файла javascript! Затем я изменил заголовок ответа сервера для коррелированных расширений (css, js, img и т.д.), Чтобы никогда не истекать. Этот заголовок не отправляется для html файлов, так как мы всегда хотим получить последние версии этих файлов.

Cache-Control:max-age=290304000

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

Я на самом деле собираю файлы html/js/css/image с кодом C, поэтому у меня есть perl script, который автоматически вставляет те контрольные суммы md5 в html файлы перед компиляцией. Это, очевидно, не будет работать в вашем случае, но вы можете использовать любое количество способов справиться с этим, если у вас есть серверный язык, который поможет вам. Например, вы можете настроить php на контрольную сумму "на лету", или вы можете иметь php для хранения контрольных сумм в базе данных или плоском файле, чтобы их легко найти. Чтобы флаг php пересчитывал контрольную сумму, вы можете проверить время файла или удалить записи базы данных/плоский файл.

Я понимаю, что это очень много работы и, возможно, не так, как вы, но для меня это работает чудесно. Производительность для меня невероятна. Загрузка первой страницы ужасно медленная (8.5 секунд), но после этого все ваши скрипты, css и изображения теперь кэшируются. Загрузка новой страницы в пределах одного и того же приложения падает до ~ 300 мс.

Ответ 7

Как вы правильно сказали, идея разделения/объединения файлов действительно зависит от ситуации.

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

Например (выдержка из facebook):

<body class="hasLeftCol home fbx hasSlimHeader safari4 win Locale_en_US defaultScrollbar">

Есть еще одно большое преимущество, которое вы можете извлечь из этого. Вы можете выборочно применять некоторый JS-код в группы страниц, используя атрибут class.

т.

if $('body.pagesThatHaveThisClass').length > 0)
{.... code ...}

if $('body#singlePageWithThisId').length > 0)
{.... code ...}

Кроме того, существует метод, который многие меню на основе JS/jQ используют для автоматического отображения другого стиля на текущей странице. Вы можете сопоставить window.location с конкретным адресом.

т.

if (window.top.location.href == 'http://domain.com/mypage1.html')
{ .... code ....}

или даже

switch (window.top.location.href)
{
   case 'http://domain.com/mypage1.html' :
    { .... code ....}

   case 'http://domain.com/mypage2.html' :
    { .... code ....}

}

Я по-прежнему предпочитаю вашу технику, так как вы можете группировать код для нескольких страниц вместе. Единственная причина, по которой я могу думать о применении второго метода, - это когда люди JS не имеют доступа к HTML-странице страницы, чтобы изменить класс /id и т.д.

Надеюсь, это то, что вы искали!

Ответ 8

Как насчет тестирования window.location? Для меня это кажется очевидным.

Или, как вы уже, кажется, делаете, проверьте наличие необходимых элементов. Это довольно надежный метод, я не вижу в этом ничего плохого.

Ответ 9

Это будет обзор высокого уровня, но я рекомендую использовать Backbone для организации логики для каждого "представления" (или page.) Я использую корневой элемент и изменяю класс этого элемента для переключения между другими представлениями (или состояниями) макета. Затем вы можете упорядочить вторичные стили по классам и сохранить основной стиль под идентификатором.

HTML

<div id="layout" class="default">
    <!-- PUT DEFAULT HTML IN HERE -->
</div>
<script id="shareTemplate" type="text/html">
    <!-- PUT SHARE HTML IN HERE -->
</script>

CSS

#layout {
    /* primary style */
}

#layout.share {
   /* secondary style */
}

JavaScript

window.LayoutView = Backbone.View.extend({

    el: "#layout",

    shareTemplate: _.template($("#shareTemplate").html()),

    initialize: function() {
        this.render(shareTemplate, data);
        this.el.className = "share";
    },

    render: function(template, data) {
        $(this.el).html(template(data));
        return this;
    }

});

window.Layout = new LayoutView;

Ответ 10

Исходя из предположения, что все разные страницы вашего сайта категорически или, по крайней мере, логически сгруппированы в разные "модели представлений", с другой моделью просмотра для другого типа страницы (например, "результаты поиска", "blogposts" "," front page "," single blogpost "и т.д.), у вас может быть один файл javascript, содержащий общие сценарии для всего вашего сайта и один конкретный для каждой модели представления (если вы сочтете это необходимым).

Затем вы могли бы указать серверу вставить имя модели представления в, например, тег данных HTML, для последующего использования JavaScript и дополнительный тег script после основной библиотеки script.

Например:

<head>
  <!--
    Two JavaScript files, one for the common functionality,
    and one for the view model specfic
  -->
  <script type="text/javascript" src="path/to/scriptslib.js"></script>
  <script type="text/javascript" src="path/to/viewmodel.front_page.js"></script>
</head>
<body data-view-model="front_page">
  ...
</body>

В scriptslib.js:

var
  GlobalSettings = {},
  ViewModel = {};

$(function () {
  // Save the view model in a variable when the body been loaded
  GlobalSettings.viewModel = $("body").attr("data-view-model");
  // Assuming that the viewmodel JavaScript file has been loaded, call a method that it'll have by convention here
  ViewModel.initialize();
  // Additionally, you can later test for specific view models and perform necessary actions, if needed
  if (viewModel === "front_page") {
    // ...
  }
});

Затем в viewmodel.front_page.js (или любом другом файле модели представления):

ViewModel.FrontPage = {
  // data and methods specific for this view model
}
ViewModel.initialize = function () {
  // do stuff specific for this view model
  this.FrontPage.someFunction();
};

Обратите внимание, что описанный здесь подход относится к сайтам, которые полагаются на перезагрузку страниц для переключения между страницами. Если вы использовали Ajax для переключения между страницами, вы хотите, чтобы JavaScript динамически загружал новые модели представлений и выполнял их.

Надеюсь, это сработает для вас;)

Ответ 11

Вы можете следить за своим подходом, но предположим, что ваш javascript файл с "коктейлем" имеет 20k строк кода, и вы включаете его во все ваши html файлы, даже те, которые показывают "404" или "500", не так ли? использовать больше ненужной полосы пропускания?

Я предпочитаю использовать разные js для каждой HTML-страницы, и все, что используется на нескольких страницах, выгружает их в "utils.js" или что-то, что вы хотите назвать, например

\www
  \pages
    \index.html
    \dashboard.html
    \account.html
    \ ...
  \scripts
    \index.js <- for index.html
    \dashboard.js <- for dashboard.html
    \account.js <- for account.html
    \ ...
    \utils.js|shared.js|sharedlib.js <- used by all pages

поэтому в основном это приведет к:

  • 1 запрос для html
  • 1 для страницы script
  • 1 для общего script, если используется
  • n для css, но я предполагаю, что 1

Это всего лишь мои два цента.