• 02

    npmからインストールできるsassモジュールについて。

    npm install sassでインストールされるモジュールがいつの間にかdart-sassになっていた。

    dart-sassは名前からもわかるようにDartで書かれており、JavaScriptにコンパイルされたコードがモジュールとしてインストールされる。

    実行ファイルもインストールされるので、コマンドラインからsassコマンドとして使用できる。

    $ ./node_modules/.bin/sass --help
    Compile Sass to CSS.
    
    Usage: dart-sass <input>
    
        --[no-]stdin    Read the stylesheet from stdin.
    -s, --style         Output style.
                        [expanded (default)]
    
    -c, --[no-]color    Whether to emit terminal colors.
        --[no-]trace    Print full Dart stack traces for exceptions.
    -h, --help          Print this usage information.
        --version       Print the version of Dart Sass.
    
  • 01

    npmコマンドから取得できるパスについて。

    $ npm bin
    /path/to/repos/node_modules/.bin
    
    $ npm root
    /path/to/repos/node_modules
    
    $ npm prefix
    /path/to/repos
    

    いずれのサブコマンドも-gオプションを付けることによってグローバル領域のパスを取得できる。

  • 01

    Googleアラートとはてなアンテナに登録した情報をRSSフィードで読む方法について。

    Googleアラート

    Googleアラート

    アラートを作成する際にオプションを表示し、配信先を「RSS フィード」に選択してから作成するとフィードのアイコンが表示されるので、それをRSSフィードに登録する。

    はてなアンテナ

    はてなアンテナ

    URLの末尾に/rssを付加すると、RSSが配信されているので、それをRSSフィードに登録する。

    以下に詳しく記載してある。

    RSS(RDF Site Summary)の配布について

  • 01

    SPモードの契約をしていないドコモの回線でdアカウントがロックされた場合、アカウントの再発行をし既存のアカウントを上書きすることでロックを解除するのと同等のことができる。

    回線の契約やdアニメストアなどの契約は上書きされるアカウントのものを引き継げる。(引き継げた)


    アカウントの再発行をする手順は以下の通り。

    「ID/パスワード」を何度か誤って入力したら「ID/パスワードがロックされているため、ログインできません。 ロック解除の手続きを行ってください。」というメッセージが表示され、ログインできなくなりましたが、どうしたらよいですか?

    自分は上記のページの「SMSが受信できる端末をご利用のお客様」に該当したので、以下を試した。

    ドコモのお客様で、SMS(ショートメール)を受信できる端末をご利用の場合、パソコン等からdアカウントの再発行をすることでロック解除ができます。再発行をしても契約内容や設定内容は変更されません。 再発行は、「dアカウントを発行する」で開く画面の「ドコモの回線をお持ちの方」を選択し、画面の表示に従ってお手続きください。

    アカウントの再発行をする際、試しに、と思いロックされた既存のアカウントと同じアカウント名を使用したところ、同じアカウント名で再発行をすることができた。

    上書きしたアカウントはdアニメストアに正常にログインでき、視聴履歴などもそのまま残っていた。「料金の確認・お支払い」のページも開くことができ、契約している回線の情報が表示された。


    経緯としては、料金の確認をしようとdアカウントにログインしようとして、何度もログインに失敗してしまいロックされてしまった。仕方がないので以下のページを読むことに。

    ID/パスワードをお忘れの方・ロックがかかってしまった方

    上記のページに記載してある方法を試していたのだけど、埒が明かず、仕方なくドコモショップに行って確認したところ、以下の方法を紹介された。

    1. SPモードを一度契約してロックを解除する
    2. 新しくアカウントを作りそのアカウントを電話番号と紐づける

    今回の再発行は2.に近いが、複数のアカウントが存在することになる、と言っていたので今回の再発行とは異なる。また、使わなくなるとはいえログインできないアカウントが残されたままになるのは避けたかった。

    なので1.を試す他ないと思っていたが、しぶとく調べていたところ「ID/パスワード」を何度か誤って入力したら「ID/パスワードがロックされているため、ログインできません。 ロック解除の手続きを行ってください。」というメッセージが表示され、ログインできなくなりましたが、どうしたらよいですか?を見つけることができ、試してみたところ上手くいった。

  • 01

    formの中にある要素を取得する方法をよく忘れるのでメモしておく。

    <form name="form1">
      <input name="text1">
    </form>
    

    上記のようにマークアップされていた場合、form要素を取得するには以下のコードでアクセスできる。

    document.form1;
    

    input要素を取得するには以下のコードでアクセスできる。

    document.form1.elements.text1;
    

    ドキュメント内のすべてのform要素を取得したければ、以下のコードでアクセスできる。

    document.forms;
    
  • 01

    HTMLがShift_JISで配信されている環境で、JavaScriptにマルチバイトの文字を書いてUTF-8で保存し、ブラウザでアラートを表示したら文字化けしてしまった。

    素直にスクリプトをShift_JISで保存し直せばよかったのだろうが、UTF-8で保存したかったので文字列をエスケープシーケンスへ変換することにした。

    調べてみると、UglifyJSにはエスケープシーケンスに変換するオプションがあるようで、以下のIssueのコメントのようにすると変換できる。

    https://github.com/mishoo/UglifyJS2/issues/490#issuecomment-53410397

    CLI

    CLIから実行する場合は以下のようにオプションを指定する。

    $ uglifyjs index.js -b beautify=false,ascii_only=true   
    

    標準入力からスクリプトを与えると以下のような出力になった。

    $ printf -- 'alert("マルチバイト")' | uglifyjs -b beautify=false,ascii_only=true
    alert("\u30de\u30eb\u30c1\u30d0\u30a4\u30c8");
    

    webpack

    webpackの場合はUglifyJS Webpack Pluginを使用するので、以下のようにオプションを指定する。

    const webpack = require('webpack');
    
    module.exports = {
      // ...
      plugins: [
        new webpack.optimize.UglifyJSPlugin({
          output: {
            ascii_only: true,
          },
        }),
      ],
    };
    
  • 01

    昨今のJavaScript開発ではBabelESLintなどのツールがよく使われるが、これらのツールを複数使用すると.babelrc.eslintrcなどの設定ファイルがリポジトリのルートディレクトリに複数存在することとなる。

    ツールの数が増えると設定ファイルも増えるので、管理するファイルが増える。そこで、いくつかのツールはpackage.jsonに設定を記述できるので、これを利用すると個別の設定ファイルを作成せずに済む。

    Babel

    Babelはbabelという名前でフィールドを作成すると読み込まれる。

    {
      "babel": {
        "presets": [
          "es2015"
        ]
      }
    }
    

    参考ページ:Use via package.json

    ESLint

    ESLintはeslintConfigという名前でフィールドを作成すると読み込まれる。

    {
      "eslintConfig": {
        "extends": "eslint:recommended"
      }
    }
    

    参考ページ:Configuring ESLint

    PostCSS CLI

    PostCSS CLIpostcssという名前でフィールドを作成すると読み込まれる。

    PostCSS CLIが対応している(正確にはPostCSS CLIが使用しているpostcss-load-configが)のであって、PostCSS本体は対応していないようだ。

    {
      "postcss": {
        "from": "/path/to/src.css",
        "to": "/path/to/dest.css"
      }
    }
    

    参考ページ:postcss-load-config#packagejson

    stylelint

    stylelintstylelintという名前でフィールドを作成すると読み込まれる。

    {
      "stylelint": {
        "extends": "stylelint-config-standard"
      }
    }
    

    参考ページ:Loading the configuration object

    browserslist

    browserslistbrowserslistという名前でフィールドを作成すると読み込まれる。

    Autoprefixerbabel-preset-envなどのモジュールがこれを使用している。

    {
      "browserslist": [
        "last 2 Chrome versions",
        "last 2 Firefox versions"
      ]
    }
    

    参考ページ:browserslist#browserslist

    browserslistフィールドとbabel-preset-envの設定を含んだbabelフィールドはどちらが優先されるかは不明。

    設定を読み込むモジュール

    設定を読み込むモジュールには以下のようなものがある。上記のツールの多くはcosmiconfigを使用している。

  • 01

    node.jsのドキュメントを読んでいた時にfs.existsSync()が非推奨ではなくなっていたことにふと気がついた。

    調べてみるとver.6.xから非推奨ではなくなっている。

    バージョン 記述
    0.10.x 特になし
    0.12.x 非推奨になります
    4.x 非推奨
    5.x 非推奨
    6.x 非推奨ではありません
    7.x 非推奨ではありません

    調べてみると、issues/1592commit/7b5ffa46fe4d2868c1662694da06eb55ec744bdeで非推奨が取り消されているのを確認できた。

    非同期のfs.exists()は変わらず非推奨になっている。

  • 02

    webpackでJavaScriptを生成せずにHTMLやCSSを生成する方法について。Extract Text Pluginを使ったことがなかったので、試してみたかった。

    最初に必要なモジュールをインストールする。

    $ npm install css-loader extract-text-webpack-plugin glob lodash.frompairs node-sass sass-loader webpack@1
    

    次に以下のコードをwebpack.config.jsとして保存する。

    'use strict';
    
    const path = require('path');
    
    const fromPairs = require('lodash.frompairs'),
          glob = require('glob');
    
    const ExtractTextPlugin = require('extract-text-webpack-plugin');
    
    // ファイル名の先頭に`_`があるファイルを無視しつつ`*.scss`を検索する
    const files = glob.sync(`${__dirname}/src/**/!(_)*.s[ac]ss`);
    
    // 階層構造を保ちつつ出力先ディレクトリに出力させる
    const entry = fromPairs(
      files.map(filePath => [
        filePath.replace(`${__dirname}/src/`, '').replace(/\.s[ac]ss$/, ''),
        filePath,
      ])
    );
    
    module.exports = {
    
      entry,
    
      output: {
        path: path.join(__dirname, 'dest'),
        filename: '[name].css',
      },
    
      module: {
        loaders: [
          {
            test: /\.s[ac]ss$/,
            exclude: /node_modules/,
            loader: ExtractTextPlugin.extract('css!sass'),
          },
        ],
      },
    
      sassLoader: {
        outputStyle: 'expanded',
      },
    
      plugins: [
        new ExtractTextPlugin('[name].css'),
      ],
    
    };
    

    これでwebpackを実行すると、srcディレクトリに配置した*.scssのファイルが階層構造を保ったままdestディレクトリにCSSとして出力される。

    webpackの--watchオプションでファイルを監視させると、パーシャルとなるファイルが更新されたときでも、そのファイルを読み込んでいるファイルがコンパイルされる。

    以下のリポジトリにSassまたはejsをコンパイルするためのwebpackの環境が作ってある。


    そもそもなぜこんなことをはじめたかというと、gulpにSassのファイルを監視させつつコンパイルさせていたときのこと。

    パーシャルとなるファイルが更新されたときに、そのファイルを読み込んでいる親となるファイルがコンパイルされないので、その動作が気になっていたからだった。

    ファイルが更新されるたびにすべてのファイルをコンパイルしなおす、という動作でも良いけれどファイル数があまりにも多い場合は確実に遅くなるはずで避けたいと思った。

    Stack Overflowでも質問されていて、以下のモジュールを使用すれば解決できるようだ。

    でも、Sassのコンパイルをしたいだけなのにgulpfile.jsがどんどん複雑になっていきそう。


    そもそも、gulpやwebpackを使わずにnode-sass--watchオプションを付加して直接実行すれば、上記の問題は解決できる。

  • 01

    GitHub Pagesでよくページを作ることがあるのだけれど、そのページで使うSassをstylelintでチェックする方法について。

    GitHub PagesではJekyllが使用できる。JekyllにSassをコンパイルしてもらうためには、公式ドキュメントのAssetsのページにもあるように、ファイルの先頭に---を記述しないといけない。

    一方でSassの記法としては---があるのは正しくないので、そのままstylelintに渡してしまうと余計なエラーが出力されてしまう。

    このFront-matterを無視しつつSassをチェックするためのprocessorであるstylelint-processor-ignore-front-matterを作った。

    使い方

    モジュールをインストールする。

    $ npm install stylelint-processor-ignore-front-matter
    

    stylelintの設定を以下のように記述する。

    {
      "processors": "stylelint-processor-ignore-front-matter"
    }
    

    _sass/front-matter.scssとして以下のファイルを保存する。

    ---
    ---
    body {
      color: #333333;
    }
    

    stylelintでSassをチェックをする。(ここではルールとしてstylelint-config-standardを継承している)

    $ ./node_modules/.bin/stylelint ./_sass/front-matter.scss
    
    _sass/front-matter.scss
     4:10  ✖  Expected "#333333" to be "#333"   color-hex-length
    
    

    ちなみに、processorを使用せずにSassをチェックすると以下のようにFront-matterのエラーが余計に出力される。

    $ ./node_modules/.bin/stylelint ./_sass/front-matter.scss
    
    _sass/front-matter.scss
     1:1   ✖  Unexpected unknown type selector "---"   selector-type-no-unknown
     1:4   ✖  Unexpected " "                           selector-descendant-combinator-no-non-space
     2:1   ✖  Unexpected unknown type selector "---"   selector-type-no-unknown
     2:4   ✖  Unexpected " "                           selector-descendant-combinator-no-non-space
     4:10  ✖  Expected "#333333" to be "#333"          color-hex-length
    
    
  • 01

    AirbnbGoogleが自社のスタイルをESLintのルールとして公開しているけれど、自分には合わないので自分用ルールなどを作っていた。ただ、メンテナンスが面倒でそのうちESLintを使わなくなってしまった。しばらくそんな状態だったので、よくないと思い調べなおしたらESLintの推奨ルールがあるということがわかったので使うようにした。

    以下を.eslintrcに記述する。

    {
      "extends": "eslint:recommended"
    }
    

    この設定をするとList of available rules - ESLintにあるチェックマークがついているルールに関してチェックされるようになる。

    mysticatea/eslint-recommended.mdには日本語での解説がある。

  • 01

  • 02

    formから画像をBase64に変換した文字列を送信する必要があって、inputタグにその文字列を入れて送信していたのだけど、たまに失敗することがあった。

    <form action="/path/to/api" method="POST">
      <input type="hidden" name="base64" value="Base64">
    </form>
    

    調べてみると長い文字列はinputでなくtextareaに入れた方が安定して送信できるようだ。

    <form action="/path/to/api" method="POST">
      <textarea name="base64">Base64</textarea>
    </form>
    

    formは見せる必要がなかったのでvisibility: hiddenにしていたのだけど、これをdisplay: noneにしたら動作が速くなった。どのブラウザでも送信してからのページのレスポンスが明らかに速くなったと体感できるほどに。

    formの仕様上、disabled属性を付加しないと送信されない以外は、非表示になっていても送信される。なので特に表示する必要のないformならdisplay: noneをつけておいた方が良いみたいだ。

  • 01

    Circle CIを使ってデプロイするという仕組みを作る機会があった。

    デプロイは簡単なコマンドなので、デプロイ用のシェルスクリプトは別途用意せず、circle.ymlへ以下のように書いた。

    deployment:
      production:
        branch: master
        commands:
          - npm run build
          - >
            [ -n "$(git status --short)" ]
            &&
            (
            git add .
            &&
            git commit -m "built"
            &&
            git push origin master
            )
            ||
            true
    

    YAMLで>を使ってコマンドを読みやすく書いた。>を使うと改行が半角スペースに変換される。インデントは1段だけで、2段にしてしまうと別の解釈をされてしまうので揃えて書いている。

    書いた後に思ったのだけど、デプロイ用のシェルスクリプトを用意した方が良かったか。

  • 02

    requireされたか、nodeコマンドから実行されたか、というのをスクリプトから判定する方法を忘れてしまって調べ直した。

    require.mainが自身の参照ならnodeコマンドから実行された、と判定できるようだ。

    if (require.main === module) {
      // nodeコマンドから実行された
    } else {
      // requireされた
    }
    

    Accessing the main module - Node.js Documentation

    When a file is run directly from Node.js, require.main is set to its module. That means that you can determine whether a file has been run directly by testing.

  • 01

    これまでGoogle Analyticsでクリックイベントなどを計測するとき、特に深く考えずにga('send', 'event', ...);というコードでコールバックを待たずに実行していたのだけど、それなりに取りこぼしがあったらしい。

    そこで、調べていたらコールバックを待って取りこぼしを回避する方法以外に、Beacon APIを使った送信などについて知ることができた。

    コールバックを待ってから次の処理に移る

    一般的な方法であるコールバックを待ってから次の処理をする方法について。

    ga関数の最後の引数に渡すオブジェクトの中にhitCallbackという名前で関数を入れておくと、計測が済んだあとに関数が呼ばれる。

    ga('send', 'event', {
      // ...
      hitCallback: function() {
        // 計測が済んだあとに呼ばれる
      }
    });
    

    ただ、このままだと計測が完了しないと関数が呼ばれないので以下のようにして一定時間を超えたら計測を無視して進んでしまうようにすると良い。(_lodashを想定)

    var callback = _.once(function() {
      // 計測が済んだあと、もしくは一定時間後に呼ばれる
    });
    
    setTimeout(callback, 3000);
    
    ga('send', 'event', {
      // ...
      hitCallback: callback
    });
    

    ヒットが送信されたタイミングを確認する - Google Developers

    ちなみにGTMのdataLayerを使用する場合はeventCallbackという名前で関数を渡す。

    dataLayer.push({
      // ...
      eventCallback: function() {
        // 計測が済んだあとに呼ばれる
      }
    });
    

    GTMではeventTimeoutをサポートしているため、一定時間を超えたら計測を無視するといったコードを書く必要はない。

    dataLayer.push({
      // ...
      eventCallback: function() {
        // 計測が済んだあと、または計測が済んでいないが3000ミリ秒経過すると呼ばれる
      },
      eventTimeout: 3000
    });
    

    #GTMTips: Use eventTimeout With eventCallback

    Beacon APIを使用して送信する

    Beacon APIが使用できる環境でのみ計測できればよいという場合には、transportの値にbeaconを指定する。するとBeacon APIを使って計測が送られることになる。

    ga('send', 'event', {
      // ...
      transport: 'beacon'
    });
    

    あるいはsetですべての送信をbeaconを指定すれば一括で設定できる。

    ga('set', 'transport', 'beacon');
    

    transportには他にimagexhrが指定できるようだ。

    別のトランスポート メカニズムを指定する - Google Developers


    Autotrack - GitHub

    Google Analyticsのチームが製作している便利なライブラリ。似たようなものをすでに作ってしまっていたのだけど、こちらを使うようにした方がなにかと良いはず。

  • 01

    Travis-CIのドキュメントを眺めていたら、たまたまValidating .travis.yml filesというページを見つけた。

    Travis WebLintを使うとブラウザから直接YAMLファイルのlintができる。

    RubyGemsからtravisコマンドをインストールしてある場合はlintサブコマンドでlintができる。

    $ travis lint .travis.yml
    

    ただ、lintも完全ではないらしくドキュメントに書いてある方法で記述してもエラーになるなど、間違った結果が表示されることも多いようだ。

    Issues - travis-ci/travis-ci

  • 02

    100円ショップに用があったのだけど、場所をなかなか思い出せないでいたので調べてみたら100均マップというサービスを見つけた。

    開店している情報の他、閉店した情報も載っている。なので記憶を頼りに店へたどり着いたら閉店していた、ということも減らせるはず。

  • 01

    たまたまbabel-preset-es2015のコミットログを見ていたら、オプションを配下のプラグインに渡す修正が含まれたことに気がついた。

    Support passing options to presets. (#3331)

    この修正により、今までは個別のプラグインにlooseの設定を渡すように記述していたのが一括で指定できるようになった。あるいは個々のプラグインへの指定が面倒だからとbabel-preset-es2015-looseを使用する必要がなくなった。

    {
      "presets": [
        ["es2015", {"loose": true}]
      ]
    }
    

    上記の指定はbabel-preset-es2015がver.6.13.0以上のときに使用できる。

  • 01

    iOSのSafariでJavaScriptからブラウザの表示領域サイズを取得する際に、プロパティによってはサイズが異なるようだ。

    window.innerHeightで取得する場合、上にスクロールをしてアドレスバーが表示されているときと、下にスクロールしてアドレスバーが表示されていないときでは取得できる値が異なる。

    document.documentElement.clientHeightで取得する場合はアドレスバーによる影響はなく、常に一定の値が取得できる。

    このふたつのプロパティを比較することで、アドレスバーが表示されているかを判定でき、処理を切り替えることができる。

    if (window.innerHeight === document.documentElement.clientHeight) {
      // アドレスバーは表示されている
    } else {
      // アドレスバーは表示されていない
    }
    
  • 03

    VagrantDockerからLinuxを使うときには極力、ディストリビュータ公式のボックスを使いたいと思っている。

    いつも使うときに調べ直していたのでここにまとめておく。

    Ubuntu

    Ubuntuは以下にある。

    Debian

    Debianは以下にある。

    上記以外

    それ以外のものは以下にある。公式でないものが多いので、気にする場合はよく調査した方が良い。

  • 02

    JekyllOctopressなど、静的サイトジェネレーターをまとめたサイトであるStaticGenというのがあった。

    GitHubでのスター数・フォーク数・Issueの数、何の言語で開発されているか、何のライセンスが適用されているかなどを一覧で見ることができる。他に言語での絞り込みやスター数でのソートをするといった機能もある。

    このサイト自体のリポジトリはnetlify/staticgenにある。

  • 01

    GitHubのプライベートリポジトリに置いてあるモジュールを、npmでインストールする方法について。

    リポジトリのアクセストークンを作ってそれを含んだURLで指定する方法と、プロトコルをgit+sshなどにしてユーザのSSH鍵を使ってインストールする方法とあるようだ。

  • 02

  • 01

    AWS CLIのインストールについて。環境はOS X 10.10で実行した。

    pyenvのインストール

    プリインストールされたpipにインストールするのを避けたいので、初めにpyenvHomebrewからインストールする。

    $ brew install pyenv
    

    .bash_profileにpyenvがコマンドとして使用できるよう、環境変数PATHにパスを通し初期化のコマンドを実行するように記述する。

    export PATH=$HOME/.pyenv/shims:$PATH
    
    if type pyenv >/dev/null 2>&1
    then
      eval "$(pyenv init -)"
    fi
    

    Pythonのインストール

    AWS コマンドラインインターフェースには

    Python 2.6.5 以降が必要です。

    とあるので、Python 2系の最新版をインストールすることにする。

    pyenvでインストールできるバージョンの一覧は以下のコマンドで出力することができる。

    $ pyenv install -l
    

    現在の2系の最新版が2.7.11なのでこれをインストールする。

    $ pyenv install 2.7.11
    $ pyenv global 2.7.11
    

    AWS CLIのインストール

    pipからAWS CLIをインストールする。

    $ pip install awscli
    

    インストールの確認をするためバージョン情報を出力するコマンドを実行する。

    $ aws --version
    aws-cli/1.10.51 Python/2.7.11 Darwin/14.5.0 botocore/1.4.41
    
  • 03

    GitHubでホスティングされているプロジェクトページにときどき貼ってある、ロゴとリボンの素材について。

    ロゴ

    GitHub Logos and UsageでGitHubが公開しているロゴ画像がダウンロードできる。

    リボン

    GitHub RibbonsにGitHubが公開している画面の隅に付くリボンの画像がある。

    以下の2つのリボンはCSSで作られているので、上記の画像のものよりも綺麗に表示される。

    リボンジェネレータ

    コーナー

    GitHub CornersにはSVGで作られたコーナーがある。CSS3 Animationも付随していてOctocatの足が動く。

  • 01

    VirtualBoxでのホスト・ゲスト間をアクセスする方法について。

    ゲストからホストにアクセスする

    VirtualBox guest OS accessing local server on host OS

    NATのアダプタを持ったゲストからホストにアクセスする。

    特に設定は必要なくhttp://10.0.2.2にアクセスすればホストにアクセスできる。

    ホストからゲストにアクセスする

    VirtualBox ゲストOSのWebサーバに外部から接続する

    ポートフォワーディングによりホストからゲストにアクセスする。