Текстовый плагин require.js добавляет ".js" к имени файла

Я пытаюсь работать с requirejs и текстовым плагином, и у меня странная проблема.

У меня есть два веб-сервера:

  1. localhost:3000 - действует как CDN и имеет все статические файлы: js, images, css и шаблоны
  2. localhost:3001 - сервер - выступать в качестве сервера REST и обслуживать только один файл - файл main.html

Файл main.html загружает все файлы js со второго сервера, используя следующую строку:

<script data-main="http://localhost:3000/js/main" 
        src="http://localhost:3000/lib/require-jquery.js"></script>

По какой-то причине при использовании текстового плагина requirejs он добавляет в шаблоны ".js" суффикс при переходе на локальный хост:3001

Я использую следующий синтаксис:

define ['jquery','backbone','underscore','models/model','text!templates/main.html', 
        'views/navigation', 'views/player', 'views/content', 'views/header']

когда я перехожу на localhost:3000, он работает нормально.

Можете ли вы вспомнить причину, по которой у текстового плагина будут проблемы с обслуживанием текстовых файлов с удаленного сервера (например, сервера CDN)?

6 ответов

Решение

Я копался в коде текстового плагина.

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

Я изменил код текстового плагина, чтобы не предполагать это.

Кто-то думает, что я что-то не так делаю?

Оригинальный код плагина:

            //Load the text. Use XHR if possible and in a browser.
            if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) {
                text.get(url, function (content) {
                    text.finishLoad(name, parsed.strip, content, onLoad, config);
                });
            } else {
                //Need to fetch the resource across domains. Assume
                //the resource has been optimized into a JS module. Fetch
                //by the module name + extension, but do not include the
                //!strip part to avoid file system issues.
                req([nonStripName], function (content) {
                    text.finishLoad(parsed.moduleName + '.' + parsed.ext,
                                    parsed.strip, content, onLoad, config);
                });
            }

У меня были проблемы с текстовым плагином при работе между доменами, и, возможно, ваши два локальных сервера тоже бьют по этому.

В веб-инспекторе я увидел, что require.js пытается получить такие вещи, как some-content.html.js вместо some-content.html,

Вы запускаете этот код в режиме разработки или встраиваете в производственный набор? Когда вы упаковываете все вместе, у текстового плагина не должно быть таких же междоменных проблем.

Вот часть документации по API, с которой я познакомился (по http://requirejs.org/docs/api.html):

BaseUrl может быть URL-адресом в другом домене в качестве страницы, которая будет загружать require.js. Загрузка скрипта RequireJS работает в разных доменах. Единственное ограничение на текстовое содержимое, загружаемое текстом! плагины: эти пути должны быть в том же домене, что и страница, по крайней мере во время разработки. Инструмент оптимизации встроит текст! ресурсы плагина, поэтому после использования инструмента оптимизации вы можете использовать ресурсы, которые ссылаются на текст! ресурсы плагина из другого домена.

Вот статья, которая помогла мне обойти это для браузеров, которые поддерживают CORS:

Документация по текстовому плагину дает подсказку к решению: возможно настроить плагин так, чтобы он всегда выбирал удаленные ресурсы через XHR, не добавляя .js суффикс и загрузка его через тег скрипта. Простое решение состоит в том, чтобы всегда применять XHR:

requirejs.config({
   config: {
      text: {
         useXhr: function (url, protocol, hostname, port) {
            return true;
         }
      }
   }
});

Обратите внимание, что удаленный сервер должен установить правильный заголовок CORS, и это может быть проблемой безопасности. Таким образом добавьте необходимые проверки для доверенных URL при использовании этого вместо простого возврата true,

В качестве другого альтернативного способа вы можете использовать метод get jQuery, чтобы извлечь содержимое шаблона в виде простого текста, а затем скомпилировать его с помощью Handlebars. Я пришел к этому решению как к последнему средству, потратив несколько часов на форумах, читающих о проблемах с текстовым плагином require.js и CORS. Вот пример:

Шаблон:

<span class="badge badge-pill badge-danger">Default</span>
<div class="entry">
    <h1>{{title}}</h1>
    <div class="body">
        {{body}}
    </div>
</div>

JS-скрипт:

var deps = [
    'jquery',
    'handlebars',
];

require(deps, function($, handlebars){

    var template = 'https://your_site/raw.templates/basic.handlebars';

    $.get(template, function( data, textStatus, jqxhr ) {
        var Handlebars = handlebars;

        var basicTemplate = Handlebars.compile(data);

        var context = {title: "My New Post", body: "This is my first post!"};

        var html = basicTemplate(context);

        var grid = document.createElement('div');
        grid.setAttribute('id', 'itemsGrid');
        grid.innerHTML = html;
        document.body.appendChild(grid);

    });

});

Такой конфиг не работает в текущем тексте! плагин. Мое решение было в переопределении метода useXhr в текстовом модуле

require(["text"], function (text)
{   if( location.port == '4502' || location.port == '4503' )// AEM env-t
        text.useXhr = function(){ return true; }
    require(["loader/widget/WidgetLoader"]); // dependent on HTML templates by text! plugin
});

Я взломал каждое решение, которое видел в Интернете, кроме запуска оптимизатора r.js и компиляции моих шаблонов в файл.js.

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

Я столкнулся с той же проблемой, и исправлением было убедиться, что файл main.js был загружен из того же домена, что и файлы *.htm. Когда они различаются, require добавит.js к html-файлам, что приведет к 404-му.

Другие вопросы по тегам