LoginSignup
2

More than 3 years have passed since last update.

JQuery(ES6)をGulp+TypeScriptでIE対応する

Last updated at Posted at 2020-03-18

はじめに

「JSでClass使えるんや、使ってみよー」
って言ってIEで動かなくて泣いた人は私です。(今更なんですけどね)

jQuery(ES6)をTypeScriptにゆるく書き換えて静的型付けを行い、
かつES5の形式でコンパイルする、ということをしたので、その備忘録です。

環境

OS

Window 10

Node

11.13.0

npm

6.4.1

Gulp

4.0.2

必要なパッケージのインストール

必要なパッケージをプロジェクト内にインストールします、

インストールするパッケージ一覧

  • typescript
  • gulp
  • gulp-typescript
  • gulp-sourcemaps
  • del
  • gulp-load-plugins
  • gulp-notify
  • gulp-plumber
npm i -D typescript gulp gulp-typescript gulp-sourcemaps del gulp-load-plugins

Gulpタスクの追加

gulpの設定ファイルgulpfile.jspackage.jsonと同じ階層に作成し、設定を記述します。

htdocs
 ├ node_modules
 ├ package.json
 ├ gulpfile.js
 └ index.html

gulpfile.jsに以下の内容を記述します。
(バージョンにより書き方が異なる場合があります。)

gulpfile.js
const gulp        = require('gulp'),
      $           = require('gulp-load-plugins')(),
      typescript  = require('gulp-typescript'),
      sourcemaps  = require('gulp-sourcemaps'),
      del = require('del'),
      setting = {
        ts: {
          path: {
            src: 'ts/**/*.ts',
            dest: 'js/'
          },
          options: {
            target: 'ES5',
            out: 'main.js',
            lib: ['ES5', 'dom']
          }
        }
      };

// TypeScript
const ts = done => {
  gulp.src(setting.ts.path.src)
    .pipe($.plumber({
      errorHandler: $.notify.onError("Error: <%= error.message %>") //<-
    }))
    .pipe(sourcemaps.init())
    .pipe(typescript(setting.ts.options))
    .pipe(sourcemaps.write('./'))
    .pipe(gulp.dest(setting.ts.path.dest));

  // DONE
  done();
}

// Clean
const clean = done => {
  del([
      // assets/js/app.jsを削除
      setting.ts.path.dest+setting.ts.options.out,

      // assets/js/app.js.mapを削除
      setting.ts.path.dest+setting.ts.options.out+".map",
  ]);

  // DONE
  done();
}

// Build
gulp.task('build', gulp.series(
  gulp.parallel(
    clean,
    ts
  ),
  done => {
    done();
  }
 )
);

// Watch
gulp.task('watch', () => {
  gulp.watch([setting.ts.path.src], ts);
});

gulp.task('default', gulp.task('watch'));

jQueryを使えるようにする

このままだと$をjQueryと認識してもらえなかったり、jQueryで取得したDOMがすべてany型に判別されたりしてしまうため、TypeScript内でもjQueryを使用できるよう、型定義ファイルをインストールします。

型定義ファイルの管理を行うパッケージ、typingsをインストールします。

npm i -g typings

jQueryの型定義ファイルのインストールをします。

typings install jquery --save --global

すると/typing/のディレクトリが生成されます。
この中のファイルはこのあとTypeScriptの記述部分で使用します。

コードの書き換え

HTML

検証のため、以下のようなHTMLを用意します。
jQueryのライブラリ自体はサイト側で読み込む必要があるため、HTMLの<head>内で読み込みます。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>ts test</title>

    <!-- jQueryの読み込み -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

    <!-- コンパイルされたJSファイルの読み込み -->
    <script src="./js/main.js"></script>
</head>
<body>
    <button type="button" id="btn">ボタン</button>
</body>
</html>

書き換え前のコード

jQueryで書いた元のコードです。

/js/main.js
class Test {
    hello() {
        console.log('test')
    }
}

const onClick = elm => {
    const test = new Test();

    elm.on('click', () => {
        test.hello();
    })
}

$(() => {
    onClick($('#btn'))
})

書き換え後のコード

TypeScriptに書き換えた後のコードです。
拡張子を.tsに変更し、gulpfile.jssrcで記述したディレクトリにコピペします。

型推論で自動で型判別してくれるため、必要のない方は記入していません。
必要に応じて型を設定してください。
今回はonClickの関数に引数elmがJQeryであることを明示しています。
JQueryJは大文字なので気をつけてください。

先程インストールしたjQeryの型定義ファイルをtsファイルの先頭で読み込みます。

main.ts
// jQueryの型定義ファイルの読み込み
/// <reference path="../typings/globals/jquery/index.d.ts" />

class Test {
    hello() {
        alert("Hello World")
    }
}

// TypeScriptの型定義を行っている↓
const clickFunc = (elm: JQuery) => {
    const test = new Test()

    elm.on('click', () => {
        test.hello()
    })
}

// jQueryもコンパイルを通すことができる
$(() => {
    clickFunc($('#btn'))
})

gulpの実行

gulp buildでdistファイルの削除、TypeScriptのコンパイルができるように設定しているため、それを実行します。

gulp build

/js/main.js/js/main.js.mapが生成されます。
.mapの方は、書き出されたJavaScriptの記述はTypeScriptでいうと何行目にあたる、というような情報を持っているファイルでブラウザ側で勝手に解釈してくれるため、見る必要はないです。

ファイルを監視し、保存のたびにコンパイルを行うには、以下のコマンドを実行してください。

gulp

書き出されたJSファイル

Classなどの記述がTypeScriptのオプションで設定したES5に合わせて書き出されています。

/// <reference path="../typings/globals/jquery/index.d.ts" />
var Test = /** @class */ (function () {
    function Test() {
    }
    Test.prototype.hello = function () {
        alert("Hello World");
    };
    return Test;
}());
var onClick = function (elm) {
    var test = new Test();
    elm.on('click', function () {
        test.hello();
        console.log("test");
    });
};
$(function () {
    onClick($('#btn'));
});

//# sourceMappingURL=main.js.map

これでjQueryを残したまま、レガシーなブラウザも気にせずにコーディングをすることができるようになりました。

余談

JSフレームワークを使うときのようモジュールで分けて読み込んだ方がコンポーネントで分けて管理できるので良さそうですね。

test.js
module Module_Test {
    export class Test {
        hello() {
            alert('Hello World')
        }
    }
}
main.js
/// <reference path="../typings/globals/jquery/index.d.ts" />
/// <reference path="./test.ts" />

import Test = Module_Test.Test;

module clickFunc {
    export function run(elm: JQuery) {
        const test = new Test()

        elm.on('click', () => {
            test.hello()
        })
    }
}

$(() => {
    clickFunc.run($('#btn'))
})

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
2