webpackを使ってNode.jsライブラリをNode.js環境以外で使用する

掲載日

はじめに

業務で「非エンジニア向けに、更新前、更新後のHTML文章の差分を出す」というタスクがあり、非エンジニア向けに考慮したdiff(タグは当然非エンジニアには理解できないので表示しない、画像の差分表示が必要など)を出す必要がありました。

diffライブラリ自体は優秀なものが沢山あるのですが、HTMLタグを考慮したdiffというと結構限られていて、しかも業務で使う本番機はPHPもしくはjavascriptな環境で、中々そんなライブラリが見つからず、しかし自力で差分表示やろうと思ったら構文解析とかそういう話になりそう(無理)だったのですが、「htmldiff-js」というライブラリを、webpackを使って非node環境でも使えるように出来たのでその備忘録です。

前提

  • 本番機以外でnodeを使える環境があり、環境構築済み。
    (※ローカル環境などで一旦ライブラリをインストールしたり、バンドルをするためにはnodeが必要になります。)

webpackでバンドルする

webpackを準備

まずはwebpackを使えるようにします。

$ npm init
# 色々聞かれるので、適切に入力します。テストなら全部空orデフォルトのままエンターキー連打でもOK

# webpackをinstall
$ npm install webpack webpack-cli

非node環境で使用したいライブラリをインストール

続いて、非node環境で使えるようにしたいライブラリをインストールします。

$ npm install htmldiff-js
# htmldiff-jsは任意のライブラリの名前に変えてもOK

webpack.config.jsを追加

続いて、ルートディレクトリにwebpack.config.jsファイルを追加して以下のコードを追加します。

const path = require('path')

var options = {
    entry: {
        htmldiff_generated: path.join(__dirname, 'app.js') // *1,*2
    },

    output: {
        path: path.join(__dirname, 'build'), // *3
        filename: '[name].js' // *4
    },
};

module.exports = options;

*1:htmldiff_generatedが出力されるファイル名になります。

*2:app.jsは任意のファイル名で大丈夫ですが、移行の操作に合わせたファイル名としてください。

*3:バンドルしたコードの出力先ディレクトリ名になります。

*4:*3ディレクトリに出力するファイル名の設定、entryの内容を使用するみたい。

app.jsを追加

同じくルートディレクトリにapp.jsファイルを追加して、以下を追加します。
※ コードの内容はライブラリに合わせて変更してください。

import HtmlDiff from 'htmldiff-js';
window.HtmlDiff = HtmlDiff;
// HtmlDiffクラスをwindow.HtmlDiffで呼び出せるようにする。

バンドルする

コマンドを実行すると、buildディレクトリ(もしくは*3で指定のディレクトリ名)にバンドルしたファイルが出力されます。

$ .\node_modules\.bin\webpack --mode production
asset htmldiff_generated.js 8.83 KiB [compared for emit] [minimized] (name: htmldiff_generated)
runtime modules 663 bytes 3 modules
cacheable modules 8.82 KiB
  ./app.js 68 bytes [built] [code generated]
  ./node_modules/htmldiff-js/dist/htmldiff.min.js 8.75 KiB [built] [code generated]
webpack 5.100.2 compiled successfully in 348 ms

バンドルしたファイルを読み込んで使えるか確かめる

バンドルしたファイルがちゃんと使用できるか確かめていきます。
適当なhtmlファイルを作成します。

<html>

<body>
    <h4>old</h4>
    <div id="oldHtml" style="border: 1px solid">
        <p>太文字になるよ</p>
    </div>
    <h4>new</h4>
    <div id="newHtml" style="border: 1px solid">
        <p><strong>太文字</strong>になったよ</p>
    </div>
    <h4>diff</h4>
    <div id="diffHtml" style="border: 1px solid"></div>
</body>
<footer>
    <script src="./build/htmldiff_generated.js"></script>
    <script>
        let oldHtml = document.getElementById('oldHtml')
        let newHtml = document.getElementById('newHtml')
        let diffHtml = document.getElementById('diffHtml')

        let tmp = window.HtmlDiff.execute(oldHtml.innerHTML, newHtml.innerHTML);
        diffHtml.innerHTML = window.HtmlDiff.execute(oldHtml.innerHTML, newHtml.innerHTML)
    </script>
</footer>

</html>

上記をブラウザで開くと添付のように表示されます。
old、newの下の枠に入っている文章を比較してdiff枠に表示するようになっています。
strongタグでマークアップした箇所に下線が引かれ、文章の変更箇所がそれぞれdelタグ、insタグでマークアップされています。

htmldiff-jsのサンプルコード実行画面

後は以下のようなスタイルを追加して追加箇所を背景緑、削除箇所を背景赤にする等見やすくすればhtml差分表示機能の完成です。

    <style>
        ins {
            background-color: oklch(92.5% 0.084 155.995);
        }

        del {
            background-color: oklch(88.5% 0.062 18.334);
        }
    </style>
cssを付与してブラウザで開いたイメージ

おわりに

非node環境でも、今回の「htmldiff-js」のように優れたnodeのライブラリを使いたいケースもあると思うので、そういう時に役に立つ備忘録でした。(もっといい方法あるかも。)
なお、全てのライブラリで同じことが出来るわけではないことはご了承ください。

ちなみに、頻出する「バンドル」という言葉は「一つに集約する」みたいな意味のようです。
今回であれば、元のライブラリであるhtmldiff-jsのコードと、そのライブラリに入ってるクラスHtmlDiffをwindow.HtmlDiffで呼び出せるようにするapp.jsのコードを一つにバンドル(集約)してhtmldiff_generated.jsに出力しているイメージになります。

参考リンク

記事の作成者のA.W.のアイコン

この記事を書いた人

A.W.
茨城県在住Webエンジニアです。 PHPなどを業務で使用しています。 趣味ではGoやNuxt、Flutterをやってます。

Comment