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

Настроить общий плагин jQuery с помощью Browserify-shim?

Я использую browserify-shim, и я хочу использовать общий плагин jQuery. Я несколько раз просматривал документы Browserify-shim, и я просто не могу понять, что происходит и/или как он знает, где разместить плагины, прикрепить к объекту jQuery и т.д. Вот как выглядит мой файл package.json

"browser": {
  "jquery": "./src/js/vendor/jquery.js",
  "caret": "./src/js/vendor/jquery.caret.js"
},

"browserify-shim": {
  "caret": {
     "depends": ["jquery:$"]
  }
}

В соответствии с примером, приведенным в документации по обозревателю, я не хочу указывать экспорт, потому что этот плагин (и большинство, если не все плагины jQuery) присоединяется к объекту jQuery. Если я делаю что-то неправильно выше, я не понимаю, почему он не работает (я получаю сообщение об ошибке, когда функция undefined), когда я его использую. См. Ниже:

$('#contenteditable').caret(5);  // Uncaught TypeError: undefined is not a function

Итак, мой вопрос в том, как настроить общий jQuery-плагин (который прикрепляется к объекту jQuery) с помощью браузера и браузера-прокладки?

4b9b3361

Ответ 1

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

Фон

Предположим, вы хотите просто добавить тэг script в свою разметку (для тестирования или повышения производительности, таких как кеширование, CDN и т.п.). Включив в разметку тег script, браузер попадет в script, запустит его и, скорее всего, добавит свойство в объект окна (также известный как глобальный в JS). Конечно, к этому можно обратиться либо с помощью myGlobal, либо window.myGlobal. Но есть проблема с синтаксисом. Это не соответствует спецификации CommonJS, что означает, что если модуль начинает поддерживать синтаксис CommonJS (require()), вы не сможете его использовать.

Решение

Browserify-shim позволяет указать глобальный, который вы хотите "разоблачить" через синтаксис CommonJS require(). Помните, что вы могли бы сделать var whatever = global; или var whatever = window.global;, но вы не могли бы сделать var whatever = require('global') и ожидать, что он предоставит вам правильный lib/module. Не путайте имя переменной. Это может быть что угодно. Вы по сути делаете глобальную переменную локальной переменной. Это звучит глупо, но его печальное состояние JS в браузере. Опять же, есть надежда, что, когда lib поддерживает синтаксис CommonJS, он никогда не будет прикрепляться через глобальный объект окна. Это означает, что вы ДОЛЖНЫ использовать синтаксис require() и назначать его локальной переменной, а затем использовать ее там, где вам это нужно.

Примечание. Я обнаружил, что имя переменной несколько запутано в документах/примерах браузера. Помните, что ключ состоит в том, что вы хотите включить lib , как если бы он был правильно управляемым модулем CommonJS. Итак, что вы в конечном итоге делаете, говорит браузеру, что, когда вам требуется myGlobal require('myGlobal'), вы просто хотите получить глобальное свойство в объекте window, который равен window.myGlobal.

На самом деле, если вам интересно, что на самом деле делает функция require, это довольно просто. Вот что происходит под капотом:

var whatever = require('mygGlobal');

становится...

var whatever = window.mygGlobal;

Разоблачение

Итак, с этим фоном, посмотрим, как мы выставляем модуль /lib в нашей конфигурации browser-shim. В принципе, вы указываете браузеру-прокладку две вещи. Имя, с которым вы хотите получить доступ, при вызове require() и глобальном, которое он должен ожидать, найти на объекте окна. Итак, здесь, где присутствует этот синтаксис global:*. Посмотрим на пример. Я хочу добавить jQuery в качестве тега script в index.html, чтобы получить лучшую производительность. Вот что мне нужно сделать в моей конфигурации (это было бы в файле package.json или внешнем файле конфигурации JS):

"browserify-shim": {
  "jquery": "global:$"
}

Так вот что это значит. Я включил jQuery где-то в другом месте (помните, Browsify-shim не имеет понятия, где мы помещаем наш тег, но это не нужно знать), но все, что мне нужно, - это предоставить свойство $ в объекте window, когда Мне нужен модуль со строковым параметром "jquery". Далее проиллюстрируем. Я также мог бы сделать это:

"browserify-shim": {
  "thingy": "global:$"
}

В этом случае мне нужно передать "thingy" в качестве параметра функции require, чтобы вернуть экземпляр объекта jQuery (который он просто получает jQuery из window.$):

var $ = require('thingy');

И да, опять же, имя переменной может быть любым. Нет ничего особенного в том, что $ совпадает с глобальным свойством $, используемым в реальной библиотеке jQuery. Хотя имеет смысл использовать одно и то же имя, чтобы избежать путаницы. Это заканчивается ссылкой на свойство $ на объект окна, выбранным значением global:$ в объекте browserify-shim в package.json.

Шиммирование

Хорошо, так что довольно много обложки. Другая главная особенность браузера-прокладки - подгонка. Так что это? Обрезка делает практически то же самое, что и выставляя, кроме включения lib или модуля в HTML-разметку с чем-то вроде тега script, вы указываете браузеру-прокладку, где можно локально захватить JS файл. Нет необходимости использовать синтаксис global:*. Поэтому вернемся к нашему примеру jQuery, но на этот раз предположим, что мы не загружаем jQuery из CDN, а просто связываем его со всеми JS файлами. Итак, вот как выглядела бы конфигурация:

"browser": {
  "jquery": "./src/js/vendor/jquery.js", // Path to the local JS file relative to package.json or an external shim JS file
},
"browserify-shim": {
  "jquery": "$"
},

Эта конфигурация сообщает browserify-shim загружать jQuery из указанного локального пути, а затем захватывать свойство $из объекта window и возвращать его, когда вам требуется jQuery с параметром строки для функции require из jquery. Опять же, для иллюстративных целей вы также можете переименовать это в другое.

"browser": {
  "thingy": "./src/js/vendor/jquery.js", // Path to the local JS file relative to package.json or an external shim JS file
},
"browserify-shim": {
  "thingy": "$"
},

Что может потребоваться с помощью:

var whatever = require('thingy');

Я бы порекомендовал проверить документы для прокрутки браузера для получения дополнительной информации о длинном синтаксисе, используя свойство exports, а также свойство depends, которое позволяет вам указывать прокрутку браузера, если lib зависит от другого Библиотека/модуль. То, что я объяснил здесь, относится к обоим. Надеюсь, это поможет другим, кто пытается понять, что делает прокси-сервер, и как его использовать.

Анонимный обрез

Анонимный shimming - альтернатива Browsify-shim, которая позволяет вам преобразовывать библиотеки, такие как jQuery, в модули UMD, используя опцию browserify --standalone.

$ browserify ./src/js/vendor/jquery.js -s thingy > ../dist/jquery-UMD.js

Если вы упали в тег script, этот модуль добавит jQuery в объект окна как thingy. Конечно, это также может быть $ или что угодно.

Если, однако, он require ed в ваш пакет приложения browserify'd, var $ = require("./dist/jquery-UMD.js");, у вас будет доступ к jQuery внутри приложения, не добавляя его в объект окна.

Этот метод не требует прокрутки браузера и эксплойтов jQuery CommonJS, где он ищет объект module и передает флаг noGlobal в свой factory, который говорит ему не присоединяться к объекту окна.

Ответ 2

Для всех, кто ищет конкретный пример:

Ниже приведен пример файлов package.json и app.js для плагина jQuery, который прикрепляется к объекту jQuery/$, например: $('div').expose(). Я не хочу, чтобы jQuery являлась глобальной переменной (window.jQuery), когда я ее требую, поэтому для jQuery установлено значение 'exports': null. Однако, поскольку плагин ожидает глобального объекта jQuery, к которому он может присоединяться, вы должны указать его в зависимости от имени файла: ./jquery-2.1.3.js:jQuery. Кроме того, вы должны фактически экспортировать jQuery global при использовании плагина, даже если вы этого не хотите, потому что плагин не будет работать иначе (по крайней мере, этот конкретный).

package.json

{
  "name": "test",
  "version": "0.1.0",
  "description": "test",
  "browserify-shim": {
    "./jquery-2.1.3.js": { "exports": null },
    "./jquery.expose.js": { "exports": "jQuery", "depends": [ "./jquery-2.1.3.js:jQuery" ] }
  },
  "browserify": {
    "transform": [
      "browserify-shim"
    ]
  }
}

app.js

// copy and delete any previously defined jQuery objects
if (window.jQuery) {
  window.original_jQuery = window.jQuery;
  delete window.jQuery;

  if (typeof window.$.fn.jquery === 'string') {
    window.original_$ = window.$;
    delete window.$;
  }
}

// exposes the jQuery global
require('./jquery.expose.js');
// copy it to another variable of my choosing and delete the global one
var my_jQuery = jQuery;
delete window.jQuery;

// re-setting the original jQuery object (if any)
if (window.original_jQuery) { window.jQuery = window.original_jQuery; delete window.original_jQuery; }
if (window.original_$) { window.$ = window.original_$; delete window.original_$; }

my_jQuery(document).ready(function() {
  my_jQuery('button').click(function(){
    my_jQuery(this).expose();
  });
});

В приведенном выше примере я не хотел, чтобы мой код устанавливал любые глобальные переменные, но я временно должен был сделать это, чтобы заставить плагин работать. Если вам нужен только jQuery, вы можете просто сделать это и не нуждаетесь в обходном пути: var my_jQuery = require('./jquery-2.1.3.js'). Если вам хорошо, когда ваш jQuery отображается как глобальный, вы можете изменить приведенный выше пример package.json следующим образом:

  "browserify-shim": {
    "./jquery-2.1.3.js": { "exports": "$" },
    "./jquery.expose.js": { "exports": null, "depends": [ "./jquery-2.1.3.js" ] }

Надеюсь, что это поможет некоторым людям, которые искали конкретные примеры (например, я был, когда нашел этот вопрос).

Ответ 3

Просто для полноты, вот метод, который использует jQuery CommonJS, чтобы не беспокоиться о загрязнении объекта window, не требуя при этом прокладки.

Особенности

  • jQuery, включенный в комплект
  • плагин включен в комплект
  • Отсутствие загрязнения объекта window

Config

В./package.json добавьте browser node для создания псевдонимов для местоположений ресурсов. Это чисто для удобства, нет необходимости в том, чтобы ничего подделать, потому что нет связи между модулем и глобальным пространством (script теги).

{
  "main": "app.cb.js",
  "scripts": {
    "build": "browserify ./app.cb.js > ./app.cb.bundle.js"
  },
  "browser": {
    "jquery": "./node_modules/jquery/dist/jquery.js",
    "expose": "./js/jquery.expose.js",
    "app": "./app.cb.js"
  },
  "author": "cool.blue",
  "license": "MIT",
  "dependencies": {
    "jquery": "^3.1.0"
  },
  "devDependencies": {
    "browserify": "^13.0.1",
    "browserify-shim": "^3.8.12"
  }
}

Метод

  • Поскольку jQuery является в настоящее время знаком CommonJS, он будет ощущать присутствие объекта module, предоставляемого браузером, и возвращает экземпляр, не добавляя его в объект window.
  • В приложении require jquery и добавьте его в объект module.exports (вместе с любым другим контекстом, который должен быть общим).
  • Добавьте одну строку в начале плагина, чтобы приложение обращалось к экземпляру jQuery, который он создал.
  • В приложении скопируйте экземпляр jQuery в $ и используйте jQuery с плагином.
  • Просмотрите приложение с параметрами по умолчанию и оставьте полученный пакет в тег script в вашем HTML.

Код

app.cb.js

var $ = module.exports.jQuery = require("jquery");
require('expose');

$(document).ready(function() {

    $('body').append(
        $('<button name="button" >Click me</button>')
            .css({"position": "relative",
                  "top": "100px", "left": "100px"})
            .click(function() {
                $(this).expose();
            })
    );
});

в верхней части плагина

var jQuery = require("app").jQuery;

в HTML

<script type="text/javascript" src="app.cb.bundle.js"></script>

Фон

Шаблон, используемый jQuery, должен называть его factory флагом noGlobal, если он воспринимает среду CommonJS. Он не добавит экземпляр в объект window и вернет экземпляр, как всегда.

Контекст CommonJS создается браузером по умолчанию. Ниже приведен упрощенный фрагмент из пакета, показывающий структуру модуля jQuery. Для ясности я удалил код, связанный с изоморфной обработкой объекта window.

3: [function(require, module, exports) {

    ( function( global, factory ) {

        "use strict";

        if ( typeof module === "object" && typeof module.exports === "object" ) {
            module.exports = factory( global, true );
        } else {
            factory( global );
        }

    // Pass this if window is not defined yet
    } )( window, function( window, noGlobal ) {

    // ...

    if ( !noGlobal ) {
        window.jQuery = window.$ = jQuery;
    }

    return jQuery;
    }) );
}, {}]

Лучший метод, который я нашел, - это заставить все работать в модульной системе node, а затем будет работать каждый раз после браузера.
Просто используйте jsdom для выравнивания объекта window, чтобы код был изоморфным. Затем просто сосредоточьтесь на том, чтобы заставить его работать в node. Затем закрепите любой трафик между модулем и глобальным пространством и, наконец, прокрутите его, и он просто будет работать в браузере.

Ответ 4

Я использовал wordpress. Следовательно, я был вынужден использовать ядро ​​wordpress jQuery, доступное в window объекте.

Он генерировал slick() не определенную ошибку, когда я пытался использовать плагин slick() от npm. Добавление browserify-shim не помогло.

Я немного поработал и выяснил, что require('jquery') не всегда был последовательным.

В моем javascript файле темы он вызывал ядро ​​wordpress jQuery.

Но в плагине slick jquery он вызывал последний jquery из модулей node.

Наконец, я смог его решить. Итак, разделите конфигурацию package.json и gulpfile.

package.json:

"browserify": { "transform": [ "browserify-shim" ] }, "browserify-shim": { "jquery": "global:jQuery" },

gulpfile.babel.js:

browserify({entries: 'main.js', extensions: ['js'], debug: true}) .transform(babelify.configure({ presets: ["es2015"] })) .transform('browserify-shim', {global: true})

Выполнение преобразования 'browserify-shim' было важной частью, я пропал раньше. Без него browserify-shim не был согласован.