webpackでnpm用に独自パッケージをつくる方法

さてさて、私は以前から何度も開発が必要になる機能やコンポーネントをパッケージ化して次回から開発効率を上げるように心掛けています。

そのため、現在私のGitHubアカウントには150を超えるパッケージが存在していて、いわば「過去の私」が現在の開発を手伝ってくれている状況です😊✨

しかし、そうはいっても全てのパッケージが永遠に利用できるかといったらそうではなく、開発環境の変遷によってパッケージの一部に変更を加える必要がでてきたりしています。そしてその中で特に重要なのが、webpackへの移行です。

以前私はbowerというtwitte社が開発していたパッケージマネージャを使っていましたが、現在ではすでに非推奨となってしまったためLaravelが標準で利用しているnpmへ変更したという経緯があります。

しかし、npmを利用するとバンドル(全コードをひとつのファイルにする)する必要があり、通常の以下のようにコードを書いてしまうとundefinedとなってしまうのです。

// my-package.js

var myPackage = {
    testFunction() {

        return 'xxx';

    },
    testString: 'yyy'
};
// そして、バンドルされたファイルを読み込んでも
console.log(myPackage); // undefinedになる😅

そこで!
今回はJavaScriptの独自パッケージを webpack 向けに開発する方法をお届けします。

まずは手順から

まず独自パッケージをつくる手順を紹介します。
(すでにご存知の方は読み飛ばしてください)

  1. 元になるソースコードをつくる
  2. webpackでソースコードをブラウザに向けに統合、改変
  3. 新しいJavaScriptファイルを出力する

となります。
やはり(設定すればですが)ES6を使ってコードを書けたりするのでIE 11用に古い記述をする必要がなくなるのは大きいですね。

また、ひとつのファイルにまとめてくれたり、余分な改行や空白を除去してくれるので表示が早くなり、訪問ユーザー側へのメリットも大きいといっていいでしょう!

環境を整える

前提としてwebpackは、npmが必要ですので以下の手順でnpmが使えるようにしておいてください。

  1. node.jsをインストール(公式サイト
  2. npmをインストール(npm install npm@latest -g

さぁ、これで開発のための環境が整いました!

独自パッケージを作る

やりたいこと

独自パッケージを作るといってもいろんなゴールがあると思うので、はじめに何がしたいかをまとめておきます。

  • ES6でコードを書くけど、IE 11には対応させる
  • バンドルされたコードはファイルサイズを圧縮(余分な改行や空白を除去)する
  • 作成したパッケージをグローバルで呼び出せる(冒頭で書いた内容の解決)

実際に作ってみよう

では、ここから実際に独自パッケージをつくっていきましょう!
今回テストで作るパッケージ名はhelloです。

まずはどこでもいいので好きな場所に専用のフォルダをつくります。(Laravelの場合はテストしやすいのでpublic以下がいいかもしれません)

そして、コマンドラインでhelloフォルダへ移動して以下のコマンドを実行します。

npm init -y

するとhelloフォルダ内にpackage.jsonというファイルが作成されるので、以下のように必要な記述を追加してください。(太字が追加した部分です)

{
  "name": "hello",
  "version": "1.0.0",
  "description": "",
  "main": "hello.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack --mode development",
    "production": "webpack --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

※ ちなみに「dev」「production」はLaravelに合わせたものですが自由に決めることができます。そして、この場合npm run devnpm run productionが実行コマンドになります。

次に必要なnpmパッケージをインストールします。(今回必要になるのは、4つですが、お好みで他のパッケージを入れたい場合もここでインストールしてください)

npm i @babel/preset-env babel-loader webpack webpack-cli --save-dev

インストールが完了すると、以下のようにnode_modulesというフォルダが作成され、この中に必要なパッケージが格納されることになります。

続いてwebpackの設定ファイルwebpack.config.jsを作ってどういう風にファイルをバンドル(統合)&トランスパイル(改変)するかを決めます。

中身は以下のようになります。

const path = require('path');

module.exports = {
    entry: './src/hello.js', // このファイルが元ソースコード
    output: {
        filename: 'hello.js', // 実行後のファイル名
        path: path.resolve(__dirname, 'dist'), // 絶対パスでないとエラーが出るのでこの記述にしてます
        library: 'hello', // helloという変数でパッケージにアクセスできるようになる
        libraryTarget: 'umd' // Laravel Mixで利用するなら必要
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: [
                            "@babel/preset-env" // IEに対応させる(つまり古いコードに変換する)
                        ]
                    }
                }
            }
        ]
    }
};

つまり内容としては、

src/hello.jsをIE11に対応できるコードにし、さらに余分な改行や空白を除去してdist/hello.jsというファイルを作成する

となります。

では、srcフォルダとdistフォルダを作って元のソースコードとなるsrc/hello.jsを作っていきましょう。

今回はテストですので、次のようなシンプルなコードにします。(※ このコード自体はIE11ではエラーが発生する「ES6」形式であることに注意してください)

const hello = {
    japanese() {

        return 'おはようございます!';

    }
};

module.exports = hello;

では、この状態で以下のコマンドを実行してバンドルを実行してみましょう!

npm run dev

うまくいけば、以下のようにdistフォルダにhello.jsが作成されているはずです。

では、実行が完了しましたのでtests/index.htmlを作ってテストしてみましょう。

ファイルの中身に以下のようにします。

<!doctype html>
<html>
<body>
<script src="../dist/hello.js" charset="utf8"></script>
<script>

    console.log(hello.japanese());

</script>
</body>
</html>

そして、ブラウザで実行してみるとうまく実行されていることがわかります(上がGoogle Chrome、下がIE 11です。)

なお、現在の状態ではまだdist/hello.jsはサイズ圧縮(余分な改行や空白を除去)されていません。サイズ圧縮を実行する場合はproductionの方を使ってください。

npm run production

※ つまり、開発途中は内容を確認しやすいように「devモード」を使い、完成したら「productionモード」を使うというのが通常の流れになるでしょう。

以上になります。
お疲れ様でした!

※ なお、この間公開した記事【JavaScript】日付や都道府県、通貨など日本関連のデータを扱うwafujsを公開しました!で紹介したwafujsも今回のテクニックを使ってwebpack対応したので良かったらぜひ使ってみてくださいね。

おわりに

ということで今回は webpack で独自パッケージを作る方法を紹介しました。

ちなみに私はたくさんのパッケージを管理する必要があるので、babelなどのnpmのパッケージを-gでグローバルにインストールして実行するようにしてみましたが、パスが合っていないためうまくいきませんでした。

その後、解決策を2つほど見つけはしたものの「うーん、それだったらローカルにインストールしますわー😅」という状況になりました。なので、この部分に関しては今後ももっといい開発環境を探っていきたいと思います。(知ってたらぜひ教えてください!)

そして、最後に途中で作成したpackage.jsonの変更例をおまけとしてつけておきたいと思います。(太字が変更箇所)

{
  "name": "hello",
  "version": "1.0.0",
  "description": "A JavaScript package that allows you to try webpack.",
  "main": "hello.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack --mode development",
    "production": "webpack --mode production"
  },
  "keywords": ["test"],
  "author": "Sukohi Kuhoh",
  "license": "MIT",
  "devDependencies": {
    "@babel/preset-env": "^7.4.4",
    "babel-loader": "^8.0.5",
    "webpack": "^4.31.0",
    "webpack-cli": "^3.3.2"
  }
}

皆さんのお役にたてると嬉しいです!

ではでは〜。

この記事が役立ちましたらシェアお願いします😊✨