LoginSignup
8
7

More than 5 years have passed since last update.

npmでもファイル直接でも利用できるブラウザ用JavaScriptライブラリ開発環境構築

Last updated at Posted at 2016-03-14

npmからインストールしてbroserify/webpack経由だけでなく、ファイルを直接ダウンロードしても使って欲しいブラウザ用ライブラリを作る環境を整える。

前提条件

  • babelにてES2015(ES6)を利用する
  • npm経由でインストールできる
  • ファイルを直接ダウンロードしても利用できる
  • githubに公開する
  • テストはkarma
  • TravisCIを利用する
  • saucelabsでマルチブラウザのテストをする

以下で時々「saiji」という文字がでてくるが、これは自作のライブラリの名前である。適宜ご自分のライブラリ名に読み替えていただきたい。

ディレクトリ構成概要

ES2015のコードをsrcディレクトリに書いてbabelでlibに出力。libに出力されたものをtop直下にbrowserifyで出力する。そのファイルをダウンロードすればnpmなしでも利用できるようになる。

テストはbrowserifyされたファイルのみが対象。

git

gitではlibnode_moduleは管理対象から外す。

/lib
node_module

npm

pachake.jsonのfilesを指定して、npmにはbabelでトランスパイルされたlibのみ公開するようにする。
mainはlib以下を指定。

package.json
"main": "lib/saiji.js",
"files": [
  "lib"
]

babel

ES2015のためにbabel-cli、 babel-preset-es2015をインストールして、.babelrcファイル作成。

npm i -D babel-cli babel-preset-es2015
echo '{ "presets": ["es2015"] }' > .babelrc

npmのscriptsにbabelでsrc以下をlibに出力。、watch:babelでwatchする。

package.json
"scripts": {
  "babel": "babel src -d lib",
  "watch:babel": "babel src -d lib -w"
}

browserify

browserifyを利用して、ファイル直接読み込みでも利用できるようにする。

browserify、差分ビルドのためにwatchifyをインストール。

npm i -D browserify watchify

buildでlib/saiji.js(endpoint)をTOPディレクトリ以下に出力する。

buildでbrowserify、watch:buildでwatchifyを利用する。-sオプションをつけてグローバルを生やしておく。

package.json
"scripts": {
  "build": "browserify lib/saiji.js -o saiji.js -s saiji",
  "watch:build": "watchify lib/saiji.js -o saiji.js -s saiji -v",
}

babel&browserify

実際に開発しているときは、babel => browserify をwatchしておきたい。そのためのwatchをpackage.jsonのscriptsに登録しておく。

package.json
"scripts": {
  "babel": "babel src -d lib",
  "build": "browserify src/saiji.js -o saiji.js -s saiji",
  "watch:babel": "babel src -d lib -w",
  "watch:build": "watchify lib/saiji.js -o saiji.js -s saiji -v",
  "watch": "npm run watch:babel & npm run watch:build"
}

karma

windowdocumentを含むDOMをカジュアルにつかえるため、テストはkarmaを利用する。
フレームワークはmocha、assertはchai.assertを使う。

karmaをインストールしたらkarma initkarma.conf.jsを作成する。

npm i -D karma mocha chai karma-chai
./node_modules/.bin/karma init

karma.conf.jsのframeworksにchaiを追加する。

karmaのpreprocessorsでbabel,browserifyすると、パフォーマンス的にストレスがたまる‥‥ そのため、babel,browserify済みのTOPディレクトリのファイルをテスト対象にしてpreprocessorsは使わない。 (本当はpowerassert使いたいんだけど :cry: )

karma.conf.js
frameworks: ['mocha', 'chai'],
files: [
    'saiji.js',
    'test/*.js'
],
preprocessors: {}

npm testでkarmaが起動するようにしておく。

package.json
"scripts": {
  "test": "karma start",
  ...
},

TravisCI

TravisCIを使いたい、というかバッジが欲しい :smirk:

LTSの4系と最新の5系を使い、karmaでChrome(chromium)を使う設定をbefore_installに書く。

travis.yml
language: node_js
node_js:
  - "4"
  - "5"

before_install:
  - export CHROME_BIN=chromium-browser
  - export DISPLAY=:99.0
  - sh -e /etc/init.d/xvfb start

TravisCIでkarmaを使う場合は、singleRunをtrueにしなければならなかったりするので、karma.conf.jsを変更。

karma.conf.js
var customLaunchers = {};
var browsers = ["Chrome"];
var singleRun = false;

if (process.env.TRAVIS) {
    customLaunchers = {
        Chrome_travis_ci: {
            base: 'Chrome',
            flags: ['--no-sandbox']
        }
    };
    browsers = ["Chrome_travis_ci"];
    singleRun = true;
}
module.exports = function(config) {
    config.set({
        //関係ない部分は省略
       browsers: browsers,
       singleRun: singleRun,
    })
};

SauceLabs

マルチブラウザのテストのためにSauceLabsを使う。
karmaからSauceLabsを使うには、karma-sauce-launcherを使うので、まずはインストール。

npm i -D karma-sauce-launcher

karma側にテストするブラウザ情報を渡してやることになるのだけれど、karma.conf.jsにずらずら書くと可読性が落ちるので、ブラウザ管理部分を別ファイルにする。

customlaunchers.jsというファイルをつくり、そこにテストするブラウザを羅列。

customlaunchers.js
var version = require("./package.json").version;
// Check out https://saucelabs.com/platforms
module.exports = {
  "sl_win10_chrome": {
    "base": 'SauceLabs',
    "browserName": "chrome",
    "platform": "Windows 10",
    "version": "48",
    "build": version,
    "passed": true
  },

  "sl_win10_firefox": {
    "base": 'SauceLabs',
    "browserName": "firefox",
    "platform": "Windows 10",
    "version": "44",
    "build": version,
    "passed": true
  },

/// こんな感じで羅列

};

npm run sauceとすればSauceLabsのテストをできるようにする。

package.json
"scripts": {
  "sauce": "Sauce=true karma start"
}

karma.conf.js側で環境変数をみて作成したcustomlaunchers.jsを読み込む。
OpenSource版のSauceLabsは同時接続が5接続までなので、concurrencyの設定をする。

karma.conf.js
var customLaunchers = {};
var browsers = ["Chrome"];
var reporters = ['progress'];
var singleRun = false;
var concurrency = Infinity;

if(process.env.Sauce) {
    customLaunchers = require("./customlaunchers");
    browsers = Object.keys(customLaunchers);
    reporters = ['dots', 'saucelabs'];
    singleRun = true;
    concurrency = 5;
}

module.exports = function(config) {
    config.set({
        //関係ない部分は省略
        sauceLabs: {
            testName: "test name",
            username: "SauceLabs username",
            accessKey: "SauceLabs accessKey",
            public: "public"
        },
        customLaunchers: customLaunchers,
        browsers: browsers,
        reporters: reporters,
        singleRun: singleRun,
        concurrency: concurrency
    })
};

karma.conf.js

karma.conf.jsの最終形はこんな感じ

karma.conf.js
var customLaunchers = {};
var browsers = ["Chrome"];
var reporters = ['progress'];
var singleRun = false;
var concurrency = Infinity;


if (process.env.TRAVIS) {
    customLaunchers = {
        Chrome_travis_ci: {
            base: 'Chrome',
            flags: ['--no-sandbox']
        }
    };
    browsers = ["Chrome_travis_ci"];
    singleRun = true;
} else if(process.env.Sauce) {
    customLaunchers = require("./customlaunchers");
    browsers = Object.keys(customLaunchers);
    reporters = ['dots', 'saucelabs'];
    singleRun = true;
    concurrency = 5;
}

module.exports = function(config) {
    config.set({
        basePath: '',
        frameworks: ['mocha', 'chai'],
        files: [
            'saiji.js',
            'test/*.js'
        ],
        exclude: [],
        preprocessors: {
        },
        port: 9876,
        colors: true,
        logLevel: config.LOG_INFO,
        autoWatch: true,
        sauceLabs: {
            testName: "test name",
            username: "sauce username",
            accessKey: "sauce accessKey",
            public: "public"
        },
        customLaunchers: customLaunchers,
        browsers: browsers,
        reporters: reporters,
        singleRun: singleRun,
        concurrency: concurrency
    })
};

というわけで、npmでもファイル直接でも利用できるブラウザ用JavaScriptライブラリをつくる環境ができあがったというわけです‥‥ 

が、これ、大変すぎやしないですかね。

牧歌的な;(function(){}())で囲まれたJavaScriptをQUnitでテストしていたころが懐かしい :cry:

参考リンク

8
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7