0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

自作ライブラリ内の冗長なバリデートや console などを、アプリ開発時には生かしておいて本番ビルド時に除去したいなーと思っていたところ、React の __DEV__ 疑似グローバル変数がヒントになりました。
Rollup でバンドル時に NODE_ENV 環境変数を見て development / production で切り替える仕組みを考えました。
サイズリミットのあるコンペに参加しているので少しでも小さくしたいです)

パッケージ構成

├── dist/
│   └── bundle.js              // ビルド成果物
├── src/
│   ├── lib/
│   │   └── someTool.js        // ライブラリ
│   ├── validators/
│   │   └── inputCheck.js      // バリデータ
│   └── app.js                 // 開発対象アプリ
├── test/
│   ├── lib/
│   │   └── someTool.test.js   // ライブラリのテスト
│   └── validators/
│       └── inputCheck.test.js // バリデータのテスト
├── package.json               // npm スクリプト設定
└── rollup.config.js           // replace・terser プラグイン設定

devDependencies

npm i -D rollup @rollup/plugin-replace cross-env
  • rollup:モジュールバンドラ
  • @rollup/plugin-replace:バンドル時に文字列置換してくれる
  • cross-env:npm スクリプト実行時に環境変数を設定( OS の差を吸収)

package.json

script を追加。( Mac や Linux は cross-env が無くても動く)

{
    "type": "module",
    "devDependencies": {
        "@rollup/plugin-replace": "^6.0.3",
        "cross-env": "^10.1.0",
        "rollup": "^4.62.2"
    },
    "scripts": {
        "_build": "rollup -c ./rollup.config.js",
        "debug": "cross-env NODE_ENV=development npm run _build",
        "release": "cross-env NODE_ENV=production npm run _build",
        "test": "node --test"
    }
}

rollup.config.js

バンドル時に replace プラグインが __DEV__true / false に文字列置換する。
NODE_ENV 環境変数 が development なら true 、それ以外は false に。

import replace from '@rollup/plugin-replace';

export default () => {
    return {
        input: './src/app.js',
        output: [
            {
                file: './dist/bundle.js',
                format: 'esm',
                sourcemap: true,
            },
        ],
        plugins: [
            replace({
                __DEV__: String(process.env.NODE_ENV === 'development'),
            }),
        ],
    };
};

サンプルコード

ライブラリ( someTool.js )

除去したい箇所に __DEV__ 判定を入れる。

import { inputCheck } from '../validators/inputCheck.js';

export function someTool(param) {
    // 1行の場合
    if (__DEV__) inputCheck(param);

    // ブロックの場合
    if (__DEV__) {
        console.log('param = ' + param);
    }

    return 'some ' + param;
}

バリデータ( inputCheck.js )

アプリの開発時ビルド時に生かして、リリースビルド時に除去する。

export function inputCheck(param) {
    if (param === undefined) throw new Error('param is a required');
}

開発対象アプリ( app.js )

こちらは特に意識せずライブラリを使用。

import { someTool } from './lib/someTool.js';

const someInput = document.querySelector('#someInput');

let result = someTool(someInput.value);

someInput.value = result;

ビルドする

アプリ開発時

npm run debug

バリデータや console が残っている。
無駄な if (true) は消してくれる。ブロックは残る。

function inputCheck(param) {
    if (param === undefined) throw new Error('param is a required');
}

function someTool(param) {
    // 1行の場合
    inputCheck(param);

    // ブロックの場合
    {
        console.log('param = ' + param);
    }

    return 'some ' + param;
}

const someInput = document.querySelector('#someInput');

let result = someTool(someInput.value);

someInput.value = result;
//# sourceMappingURL=bundle.js.map

本番ビルド時

npm run release

バリデータや console が除去される。
function inputCheck は使われないのでツリーシェイクされる。

function someTool(param) {

    return 'some ' + param;
}

const someInput = document.querySelector('#someInput');

let result = someTool(someInput.value);

someInput.value = result;
//# sourceMappingURL=bundle.js.map

テスト

テスト時は __DEV__ をグローバル変数として扱い、常に true を設定

ライブラリのテスト( someTool.test.js )

import test from 'node:test';
import assert from 'node:assert/strict';
import { someTool } from '../../src/lib/someTool.js';

global.__DEV__ = true; // __DEV__ をグローバル変数として扱う

test('Some kind of test', () => {
    assert.strictEqual(someTool('one'), 'some one');
});

バリデータのテスト( inputCheck.test.js )

import test from 'node:test';
import assert from 'node:assert/strict';
import { inputCheck } from '../../src/validators/inputCheck.js';

global.__DEV__ = true; // __DEV__ をグローバル変数として扱う

test('Positive test', () => {
    assert.doesNotThrow(() => inputCheck('one'));
});

test('Undefined is illegal', () => {
    assert.throws(() => inputCheck());
});

参考

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?