Babelを使ってみようとしたらハマった話とドラッグで要素を動かしてみたい話
はじめに
投稿が大変遅れましたが、この記事は JavaScript Advent Calendar 2019 の13日目の記事です。
要素をドラッグして動かしたい。
せっかくなので JavaScript で書いてみよう。
と思ったら Babel ハマったという話です。
Babel と Webpack を使う
TypeScript で書いていたときは、(Promise などを除いて) IE でも動くようトランスパイルしてくれていました。
じゃあ JavaScript では?というと、いくつか方法はあると思うのですが、今回は Babel を使ってみることにしました。
このときと同じく、 Webpack も使います。
インストール
インストール、セットアップは下記ドキュメント( Build system として Webpack を選択)に従えば OK でした。
Babel 、 Webpack に加え、ドラッグで要素を移動させるときに使用する RxJs も追加しておきます。
npm install --save webpack webpack-cli rxjs babel-loader @babel/core @babel/preset-env
設定ファイル
Babel ver.7 では .babelrc というファイルを設定ファイルとして使用するようです(ググってると babel.config.js とか出てきて混乱しました)。
.babelrc
{ "presets": ["@babel/preset-env"], }
サンプルコード(失敗)
MainPage.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Hello</title> </head> <body> <button onclick="Page.doSomething()">Click</button> </body> <script src="../js/main.bundle.js"></script> </html>
mainPage.js
import { AsyncSample } from "./asyncSample"; export async function doSomething() { const s = new AsyncSample(); await s.doSomethingAsync(); }
asyncSample.js
export class AsyncSample { async doSomethingAsync() { return new Promise((resolve, reject) => { console.log('Hello World!'); resolve(); }) .catch((reason) => reject(reason)); } }
webpack.config.js
var path = require('path'); module.exports = { mode: 'development', entry: { 'main': './src/js/mainPage.js', }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" } ] }, resolve: { extensions: [ '.js' ] }, output: { filename: '[name].bundle.js', path: path.resolve(__dirname, './dist/js'), library: 'Page', libraryTarget: 'umd' } };
そしてエラー
npx webpack -w とやるとコンパイルは成功します。
で、ボタンを押すとエラー発生と。
ReferenceError: regeneratorRuntime is not defined
regeneratorRuntime ってなんぞ?というと、async/await を Babel でトランスパイルするときに使われるもののようです。
なんとかする
で、これが足りないのでどうするか。
ぐぐると @babel/polyfill の話( ver.7.4? で Deprecated )が大量に出てきてこれまた混乱するのですが、今は regenerator-runtime と core-js を使うようです。
npm install --save regenerator-runtime core-js
どう使うのか、というと、 async/await や Promise を使うところで import します。
mainPage.js
import { AsyncSample } from "./asyncSample"; import "regenerator-runtime/runtime"; export async function doSomething() { const s = new AsyncSample(); await s.doSomethingAsync(); }
asyncSample.js
import "core-js"; import "regenerator-runtime/runtime"; export class AsyncSample { async doSomethingAsync() { return new Promise((resolve, reject) => { console.log('Hello World!'); resolve(); }) .catch((reason) => reject(reason)); } }
直接使っているわけでないものをインポートするのはしっくりこない気はしますが、別途 Polyfill を入れなくても Promise などに対応してくれるのはありがたいですね。
※ここより先は後ほど追記します(..)_