技術探し

JavaScriptを中心に記事を書いていきます :;(∩´﹏`∩);:

Nodeへutil.promisify()の追加

ということで久しぶりに記事を書くことにした。

4/24のNode学園でも少し話したが、自分がとても注目している追加です。
Node8への変更点を見たい方はスライド見てください。

abouthiroppy.github.io

本題

github.com github.com

簡単に話すと、今までコールバックだったのがこのutil.promisify()を使うことによりPromiseと同じように扱えるということ。

これだけでかなりすごい。今までコールバック内でresolveしていたのだからそこのPromise用の関数を作らなくてもよくなるのはとても楽だ。 child_process, dns, fs, timers に対応している。

util.promisify()のリファレンス
node/util.md at aab71bd565662446622f36a011ce956a451b7be5 · addaleax/node · GitHub
まだマージされていないのでmasterではなく個人へ向けられています

さて、このPRは承認規定数を越したのでそろそろ着陸され、次の8.0.0への凍結前(5/9)にmasterへ入ると思われる。

const util = require('util');
const exec = require('child_process').exec;

/**
 * CallBack
 */
exec('ls', (err, stdout, stderr) => {
  if (err) console.error(err);
  console.log('stdout:', stdout);
  console.log('stderr:', stderr);
});

/**
 * Promise
 */
function execLS() {
  return new Promise((resolve, reject) => {
    exec('ls', (err, stdout, stderr) =>
      !err ? resolve(stdout, stderr) : reject(err)
    );
  })
}

execLS().then((stdout, stderr) => {
    console.log('stdout:', stdout);
    console.log('stderr:', stderr);
  }).catch((err) => {
    console.error(err);
  });

/**
 * util.promisify()
 */
const execPromise = util.promisify(exec); // ここでexecをPromiseにする

// async/await Node7.6.0 ~
(async () => {
  const {
    stdout,
    stderr
  } = await execPromise('ls');

  console.log('stdout:', stdout);
  console.log('stderr:', stderr);
})();

const setImmediatePromise = util.promisify(setImmediate);

setImmediatePromise('foobar').then((value) => {
  console.log(value)
});

このようにPromiseになるので、async/awaitのようにも使えるし今までのようにthen()でつなげることもできるようになった。

また今、whatwg-consoleの実装が着実に進んでいるのでこちらも注目すると良さそう。
6時間前に console.count(), console.clear() の実装がでた。
github.com github.com

bespokeを使ってスライドを作る環境を構築した

今朝からなんとなく自分用のスライド作成環境がほしくなってしまい作成しました。 再来週にLTがあるためそれの準備です。 最近のスライド作るフレームワークは何があるのかわからないのとbespokeで満足しているので今回はbespokeで作ることにしました。

また、個人的にreveal.jsは作るまでが難しいと思っています。
bespoke.js自体も前に少し使っていたのですが、環境構築まではしていなかったので今回は、せっかくだしと思いwebpackやらpostcssやらbabelやらのセットを入れたすぐに新規スライドが作れる環境を構築しました。

リポジトリ

サンプルスライド

abouthiroppy/hello

基本的には上のスライドに使っているライブラリとかは書いてあります。

目的

手早くスライドを作れるようにする というのは第一目的でした。
しかし、自己紹介のスライド部分とかを毎回書くのだるいなってよく思っているので、それも理由の一つです。
あと、自分の好きな色とかも共有して使えるのは楽になりそう。

bespoke

github.com

スライドを作るためのフレームワーク。 他のスライドを作るフレームワークと同じ感じですが、軽量でプラグインを使いカスタマイズしていきます。
公式のプラグイン

https://github.com/bespokejs/bespoke#official-plugins

個人的に結構テーマが好きで、nebulaが特に好きです。(サンプルのスライドのテーマです)

スライドの作り方

bespokeはHTMLを読み込むのですが、嫌だったのでwebpackを使いmarkdownからHTMLへ置換させています。 その後、require.contextを使いreactへ流し込んでいます。
lib/fetch-slides#L19
hello/main.js#L26
require.contextの第一(directory)には変数やpathがおそらく使えないので、一旦全件取得になっています。

背景の変更

背景の変更にはbackdropを使います。

github.com

今回はmarkdownへの特定のコメントにフックさせ背景を変えるようにしました。
hello/main.js#L25へ流し込めばclassとして名前が入るのでcssを設定すれば背景が変わるようになります。

詰まった点

webpackでarrayとして設定を返す(ココ)とhtml-webpack-pluginがバンドルされたjsを読み込みにいけないっぽい。
これはpublichPahでも解決できなかったので少し調べないとダメそう。 まぁ開発中に同時に別のスライドもデバッグしたいということは普通無いので、一旦webpack.config.jsへの引数としてファイル名を渡し長さ1の配列を返すようにした。

気になる点

上のスライドを見てもらえばわかるのですが、ページ読み込み時にすべてのスライドが見えてしまうのでどうにかしないと汚いなぁって思っている。
同じこと考えている人おおそうなので多分探せば出そう。

おわり

詳しくはリポジトリみてください。
当分はkeynoteではなく、markdownでスライドを作っていこうかなと思っています。

webpack2へ移行する軽いメモ

npmの方もbetaが取れて、2.2.1が公式に配布となりました。

www.npmjs.com

公式サイト

webpackのversion:2のために公式サイトが作られました。 webpack

移行の手順

詳しくはこちらを確認してください。
Migrating from v1 to v2

Medium

medium.com medium.com

移行における変更点

フィールドバリデータ

設定ファイルのフィールドを検証します。
v1ではwebpack-validatorが必要でしたが、v2ではデフォルトで入っています。

ローダー

リネーム

  • module.loaders -> module.rules
  • loaders -> use
  • query -> options
{
  rules: [
    {
      test: /\.js$/,
      use: ['babel-loader'],
      options: {
      }
    }
  ]
}

module-loaders-is-now-module-rules

preLoadersとpostLoaders

ローダーを呼び出すタイミングを設定するpreとpostのキーがなくなります。
v1ではmodule.preLoaders, module.postLoadersの中に各ローダーの設定を書いていましたが、v2ではすべてのローダーがrulesに入りキーでの区別がなくなります。
その代わりに、enforceを各ルール内に設定します。

{
  rules: [
    {
      test: /\.js$/,
      use: ['eslint-loader'],
      enforce: 'pre' // or 'post'
    }
  ]
}

module-preloaders-and-module-postloaders-was-removed

ローダーチェイン

style-loader!css-loader!less-loader のようなv1の書き方はuseではサポートされません。
module.loadersの場合のみサポートされます。
useを使ったときの上記の書き方だと以下のようになります。

rules: {
  use: [
    'style-loader',
    'css-loader',
    'less-loader'
  ]
}

chaining-loaders

-loaderのサフィックスについて

-loaderを設定なしで省略することはできなくなります。
もし省略したい場合は、resolveLoader.moduleExtensions = ['-loader'] を設定する必要があります。
できなくなった理由として、エラーが理解しづらくなるからです。
Remove automatic -loader module name extension · Issue #2986 · webpack/webpack · GitHub
automatic-loader-module-name-extension-removed

jsonのロードについて

今まではjson-loaderが必要でしたが、設定の必要がなくなります。
v2以降は自動的にwebpack側が内部で呼び出します。
Support JSON out of the box · Issue #3363 · webpack/webpack · GitHub
json-loader-is-not-required-anymore

プラグイン

名前の変更が必要(デプリケートなものも含む)

  • OccurenceOrderPlugin -> OccurrenceOrderPlugin
  • NoErrorsPlugin -> NoEmitOnErrorsPlugin

消されたもの

  • DedupePlugin
  • ResolverPlugin
  • OldWatchingPlugin

extract-text-webpack-plugin

今現在、v2.0.0-rc.2となっています。 なので、何も指定無しでnpmからinstallすると1.0.1がダウンロードされるので注意が必要です。
引数のとり方が変わりました。今まではファイル名とオプションが別々だったのが、すべてオブジェクトで包みます。
今現在、急ぎで開発を行っています。

new ExtractTextPlugin({
  filename: 'bundle.css',
  disable: false,
  allChunks: true
})

https://github.com/webpack-contrib/extract-text-webpack-plugin/milestone/1github.com
extracttextwebpackplugin-breaking-change

resolve

resolveの書き方が変わります。
rootmodules にリネームされました。
ここにbower_componentsを書き、descriptionFilesbower.json書くとnode_modulesと同じように引けます。
今まではresolverPluginで引いていたのですが、この書き方でいけるようになりました。
Resolve

webpack以外での変更するべき設定

Babel

tree shakingのため、es6 modulesからcommonJS modulesへの変換を停止させます。

{
  "presets": [
    ["es2015", {"modules": false}]
  ]
}

mixing-es2015-with-amd-and-commonjs

react-hot-loader

github.com

まだ、npmの方は1.3.1系ですが、3系にそろそろ(?)上がりそうなので追加します。 1系から3系への変更はこちらを参照
1系では以下の用に書いてたのですが、

if (module.hot) {
  module.hot.accept('./App', () => {
    const NextApp = require('./App').default;
    ReactDOM.render(
      <AppContainer>
         <NextApp />
      </AppContainer>,
      rootEl
    );
  });
}

3系では上記のNextAppの部分が必要なくなり、共通化することが可能になりました。

詳しい構成等は以下を参照してください。nextブランチが3.0.0向けになっています。 github.com

Document React Hot Loader 3 · Issue #243 · gaearon/react-hot-loader · GitHub React Hot Loader 3 by gaearon · Pull Request #240 · gaearon/react-hot-loader · GitHub

Jest

.babelrcの方でmodules: falseしますが、JestはNodeで動くため、commonJS modulesにする必要があります。
テストのときだけcommonJS modulesへ変換します。

{
  "presets": [
    ["es2015", {"modules": false}]
  ],

  "env": {
    "test": {
      "plugins": ["transform-es2015-modules-commonjs"]
    }
  }
}

https://facebook.github.io/jest/docs/webpack.html#using-with-webpack-2facebook.github.io

ローダの設定を書く場所

フィールドのバリデータが入り、今までルートに設定を書いていたものは使えなくなりました。(e.g. postcss)
書き方は2種類(設定ファイルの書けるもの(babel, postcss, etc…)については3種類)あります。
各種ローダのoptionsを使う方法、LoaderOptionsPluginを使う方法です。
基本的に自分は、LoaderOptionsPluginの方では書かず、 外部設定ファイルかoptionsのどちらかで定義します。 理由として、LoaderOptionsPluginの場合はグローバル(1つしか宣言できない)と同じ扱いになるので同じローダでも個別に適応することをわけるのが難しくなるからです。
(これにおいては設定ファイルでもグローバルになるのでダメですが。。)