はじめに
「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.js
をpackage.json
と同じ階層に作成し、設定を記述します。
htdocs
├ node_modules
├ package.json
├ gulpfile.js
└ index.html
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で書いた元のコードです。
class Test {
hello() {
console.log('test')
}
}
const onClick = elm => {
const test = new Test();
elm.on('click', () => {
test.hello();
})
}
$(() => {
onClick($('#btn'))
})
書き換え後のコード
TypeScriptに書き換えた後のコードです。
拡張子を.ts
に変更し、gulpfile.js
のsrc
で記述したディレクトリにコピペします。
型推論で自動で型判別してくれるため、必要のない方は記入していません。
必要に応じて型を設定してください。
今回はonClick
の関数に引数elm
がJQeryであることを明示しています。
JQuery
のJ
は大文字なので気をつけてください。
先程インストールしたjQeryの型定義ファイルを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フレームワークを使うときのようモジュールで分けて読み込んだ方がコンポーネントで分けて管理できるので良さそうですね。
module Module_Test {
export class Test {
hello() {
alert('Hello World')
}
}
}
/// <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'))
})