概要
highlight.js
がwebpack
とあまり相性が良くない。
本系からダウンロードしてきたのをそのままwebpackでビルドするとエラーになる。
単純にscript
タグでインクルードすれば使えるけど、
せっかくなのでwebpack
の知識も深めるという意味でなんとか対応してみた話。
現象
フォルダ構成
html
はこんな感じ
<!DOCTYPE html>
<html lang="jp">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>testing highlight with webpack</title>
<link rel="stylesheet" href="./github.css">
</head>
<body>
<div>
<pre><code>
angular.module('myApp').service('AwesomeService', ['$http',
function($http) {
var i = 1;
this.yo = function() {
return 'AwesomeService:' + new Date().getTime();
};
this.name = 'AwesomeService';
this.ts = new Date().getTime();
this.up = function() {
i = i + 1;
};
}
]);
</code></pre>
</div>
<script src="../lib/js/jquery.min.js"></script>
<script src="http://localhost:3010/assets/hl.bundle.js"></script>
</body>
</html>
普通にrequire
する
/* globals jQuery: true */
(function( undefined ) {
var $, hljs;
$ = require( 'jquery' );
// autoreload for html
require( 'raw!./hl.html' );
hljs = require( './highlight.pack' );
$(function() {
$( document ).ready(function() {
$( 'pre code' ).each(function( i, block ) {
hljs.highlightBlock( block );
});
});
});
})();
これだけだとhljs
が見つからないとのこと、もちろんハイライトもされない
ダウンロードしてきたhighlight.pack.js
を整形して見てみると
モジュール化したあとで言語を登録している模様。
この状態ではglobal
で普通にインクルードする時はこれで動くが
webpack
でビルドするとhighlight.pack.js
が読み込まれた時点でhljs
が存在しないから当然エラーになる。
解決策
モジュールと言語登録処理を分割し、言語登録処理でモジュールをインクルードしてそれを返せば良い。
使うときはモジュールファイルではなく言語登録ファイルをインクルードする。
こうすれば両方のファイルをインクルードする必要もなくなる。
手順
-
highlight.js
をカスタムパッケージ無しの状態でダウンロードする。 - ダウンロードしてきたピュアな
highlight.pack.js
のファイル名をhighlight.min.js
(hljs.js
と略称)に変更。 - それから空の新たな
highlight.pack.js
(pack.js
と略称)を用意。 - この
pack.js
が実際にインクルードされるライブラリーとなる。
pack.js
の中にhljs.js
をインクルードし言語登録をしてあげる
13行目のようにファクトリーを実行する際にhljs.js
を依存モジュールとしてインクルードして渡す。
script
タグのインクルードされる際はwindow
のhljs
を渡す。
CommonJSモジュールの考え方
CommonJS
形式でrequire
する際、依存先のモジュールの関数を呼出して値をセットすることはできるが、依存先モジュールをそのまま返すことはできない。
CommonJS
はexports
にメンバーを追加することでそれがrequire
先で使えるようになる(理解が正しいかわからん)。
ということはpack.js
の中でhljs.js
をreturn
で返しても何も受け取れない。
使い方が少し変わってしまうがこれを解決するために27行目のようにexports
オブジェクトにhljs
プロパティとしてモジュールをセットしてあげる。
require
先では下記のようにプロパティから取得すればOK。
hljs = require( './highlight.pack' ).hljs;
これでも新たな言語を追加したい場合はpack.js
に登録処理を追加して上げる必要があるという問題が残る。
結果
これでちゃんとハイライトされ、エラーも出ずに全てが丸く収まる
言語登録コマンド
highlight.jsは様々な言語を対応しており、それぞれのハイライト定義ファイルが別に用意されている。
対象言語だけをビルドするコマンドがnode
とブラウザー用に言語登録の用意されている。
それで試して見てもがやはりうまくいかないので上記の対策をせざるの得なかった。