browserifyでjQuery(CDN)とjQueryプラグインを使う

jQueryをCDNから取得し、jQuery pluginが活躍している場合のbrowserify導入の備忘録

CDNのjQueryをrequireする

CDNを使うことで、browserifyでbundleするファイルサイズは小さくなり、ファイル生成までの時間も短くなるという恩恵がある。

まず、CDNのjQueryを利用するのにbrowserify-shimを使う。
globalのjQueryを「jquery」というモジュール名でrequireできるようにする。

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

requireでincludeするjqueryはglobal(window)空間に存在しているので、
実際にはrequireなどせずとも使えるといえば使える。

require をするには以下の理由があるらしい。

  • require(‘jquery’)に統一することでwindow.jQueryというグローバルな名前空間へのアクセスを避け、依存解決方法を統一できる
  • 将来的にnpmパッケージとして運用する場合に、コードに変更がいらない
  • require することでディレクトリ構造などが変わる変更が生じても、その影響を受けにくくなる。

browserifyを実行すると

(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
(function (global){
var jquery = (typeof window !== "undefined" ? window.jQuery : typeof global !== "undefined" ? global.jQuery : null);
// code...
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}]},{},[1]);

となり、globalのjQueryをrequireしているのがわかる。

だが、node_modules配下にjQueryをrequireしているパッケージがある場合は、以下のようになる。

browserify -r jquery -o bundle.js
Error: Cannot find module 'jquery' from '/Users/XXXX/PROJECT'
view raw browserify.sh hosted with ❤ by GitHub

解決するにはいずれか、

  1. 素直にjQueryをnpm installしてdependenciesに追加する
  2. shim を作成して、jQueryをexportsする

1 の場合は、結局CDNから取得するjQueryを使うわけではなく、npmでinstallしたjQueryを使うことになるため今回の目的に沿わない。

2 で対応する。jquery_shim.jsを作りmodule.exportsにglobalのjQueryを渡すようにする。

module.exports = require('jquery');
view raw jquery_shim.js hosted with ❤ by GitHub

そして、 browserフィールド追加してにaliaseを作成

"browser": {
"jquery": "./jquery_shim.js",
}

これにより、以下のようなスクリプトを作成できるのでCDNの恩恵を受けることができる。
requireの引数にjqueryが追加されglobalのjQueryをexportしているのがわかる。

require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({"jquery":[function(require,module,exports){
(function (global){
'use strict';
module.exports = (typeof window !== "undefined" ? window.jQuery : typeof global !== "undefined" ? global.jQuery : null);
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}]},{},[]);
view raw cdn-jquery.js hosted with ❤ by GitHub

とこれでまずはjQueryはCDNの恩恵を受けることができる。

jQuery pluginの対応

jquery pluginもnpmから取得できるので、bowerを使用することなくnpm経由で直接installからexportsできる。
(Welcome, jQuery developers!)

任意のjquery.pluginと自作モジュールのmy_module.jsを利用するとした場合、

"browser": {
"jquery": "./jquery_shim.js",
"jqueryPlugin": "jquery.plugin",
"myModule": "./my_module.js"
}

ここではjquery.pluginをjqueryPluginでexport、
my_module.jsをmyModuleとしてexportしている。

それぞれ、require(‘jquery_plugin’)、require(‘myModule’)とすることで利用出来る。

module 形式でない package の場合でも、browserify -r jquery_plugin で require オプションを使うことで requireできるようになるのでとりあえずなんとかなる。

require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({"notModule":[function(require,module,exports){
"use strict";
// no module code...
},{}]},{},[]);

browserify (browser-pack) はどんなコードを出力するのか?あたりが詳しい。

サイトの規模によってはbrowserifyを利用して全てのファイルをまとめてしまうと、ファイルサイズが気になる。

たとえば、サイト全体で使う共通のモジュールやユーティリティ的なものをbrowserifyでrequireできるようにしておく。

各ページごとに必要な処理の多くはDOMをゴニョゴニョするものなどが多いと思うが、
こういったものは複数人で開発・運用などしているといろんな人が変更を行うので、
コアになる部分以外はあまりややこしなく扱えるようにしておきたい。

意図しないグローバルを汚染をしない程度にとどめておく程度にしておくとかでもいいのではないだろうかと。

(function(global) {
"use strict";
var jQuery = require('jquery');
// your code...
})(this);
view raw page-content.js hosted with ❤ by GitHub

お手軽に browserify-cdn もある。

参考にしたページ

Comments