設定 babel browserify watchify babelify presets es2015

ES6 でクラス構文、及びモジュールを扱うための import 構文を書き、ブラウザで使用可能な ES6 に Babel で変換し、さらにモジュールの依存関係を Browserify で解消する。という一連の作業を npm scripts で実行する方法について書いています。

Babel, Browserify, Watchify, Babelify の関係

  • Babel は ES6(ES2015)→ES5 に変換するツール。(恐らく Babelify も内部では Babelを使用している。) 自分は class 構文、及び import, export 構文を書くために必要。
  • Browserify はモジュール機能を使うために必要。(require , export 構文を用いて読み込む JS ファイルの依存関係を解決するシステム。ES6 のimport, export 構文は ES6 に変換されると、require, export 構文になる。) transform オプション(-t)に babelify を指定することで(-t babelify) まず bable で変換した後にモジュールの処理がされる。
  • Babelify は Browserify のオプションとして指定することで(-t babelify)Babel で変換してくれる。(どのようなルールで変換するか、プリセットの設定が必須)
  • Watchify は Browserify の watch 版。つまり、ファイル更新がされたときだけ実行される。さらに、差分だけをビルドするので、ファイル更新を Browserify でウォッチするよりも、早い。 またこれは Browserify と同じ作者が作成しており、ウォッチ用途にはこちらが推薦されている。
  • Babel は実行時に presets オプションが必須。同様に Babelify にも presets が必須。.babelcr ファイルもしくは package.json に記録することが可能。
  • Browserify, Watchify は –transform (-t)オプションで Babelify を指定することで Babel の処理を間に入れることが出来る。Babel と同様に Package.json で指定可能。

npm scripts でタスクを実行する

npm scripts (package.json 内の script フィールドに記述する) でタスクを実行する。ここには CLI (コマンドラインインターフェイス、Mac ならターミナル等) で npm を実行するコマンドと同じものを基本的に書けば良い。(基本的に、といったのは、ここで実行するコマンドはシェルに依存するので、mac や win など OS に異なる場合には、コマンドも異なるため。その差を埋める方法については後述)

Grunt や Gulp といったタスクランナーを使わずに npm scripts で コマンドラインを実行する利点は、第一にタスクランナー専用のプラグインよりも、CLI から実行可能な npm の方が多く、第二にそれぞれのタスクランナー専用の設定ファイルを書く必要がないという点がある。(参照:原文翻訳) (ただし Grunt や Gulp で運営されるプロジェクトも多くあるため、これらのタスクランナーの知識は不必要ということでははない。)

実感として、初歩的なビルド、コンパイルであれば CLI での実行は簡単で、公式ドキュメントを参照すれば十分に理解できる。ただし、複雑なタスクの実行するには npm scripts への理解が必要になる。それでも公式マニュアルに情報が多いため、対応が楽だと感じている。

npm 及び package.json について

npm 及び package.json については次の記事を参照。(npm とは何か / Package と module の違い)

次のコードは package.json の中に書かれるもののサンプルで、”scripts” 内に npm scripts を書く。ここには基本的に CLI で実行するコードを書く。package.json は json なので次のルールを守って書く。

  • {“プロパティ1″:”値1″,”プロパティ2″:”値2”} と JS オブジェクトに似た全体像になる
  • {“プロパティ”:{“子プロティ1″:”値1″,”子プロティ2″:”値2”}} と階層化する際には、値にさらにオブジェクトを持つ。
  • 単に値が複数ある場合には配列を使う。{“プロパティ1”:[“値1″,”値2”]}
  • 全ての値は””で囲う。”は使用できない。そのため””内で””を使用するためには「\”」とエスケープする。
  • &を使うと、並列に実行される
  • && を使うと、実行後に実行される
  • npm scripts 内で、さらに run npm コマンド名を実行することも出来る。
{
  "name": "browserify-test",
  "version": "1.0.0",
  "main": "main.js",
  "dependencies": {
    "jquery": "^3.1.1"
  },
  "devDependencies": {
    "babel-preset-es2015": "^6.22.0",
    "browserify": "^14.1.0",
    "gulp": "^3.9.1",
    "node-sass": "^4.5.0",
    "vinyl-source-stream": "^1.1.0",
    "watchify": "^3.9.0"
  },
  "scripts": {
    "start": "npm run watch:script & npm run watch:sass",
    "watch:script": "watchify main.js -v -t babelify -d -o app.js",
    "build": "browserify main.js  -t [ babelify --presets [ es2015 ] ] -o app.js",
    "watch:sass": "node-sass --include-path src/sass --watch src/sass/screen.sass src/css/screen.css"
  }
}

実際の npm scripts

オプションを npm scripts 内に記述する

次のような npm scripts がある場合、コマンドラインで npm run build  や npm run watch:script と実行する。

-t [ babelify –presets [ es2015 ] ] はオプションで、babelify を使って ES6→Es5 に変換し、そのさいのプリセットは es2015 で実行することを指定している。(詳細は後述)

  • -0 –output の省略形。出力先のファイルの指定をするオプション
  • -v コンパイルした際に通知が入る。これを指定しないと、コンパイルしても何も教えてくれない。
  • -d –debug の省略形。ソースマップを出力する。
 "scripts": {
    "build": "browserify main.js  -t [ babelify --presets [ es2015 ] ] -o app.js",
    "watch:script": "watchify main.js -v -t [ babelify --presets [ es2015 ] ] -d -o app.js"
  }

オプションを Package.json 内に記述する

オプションはPackage.json 内に記述することも出来る。

まず Browserify の設定は Package.json に以下のように記述できることが Browserify ドキュメントに書いてある。つまり”browserify”: {“transform”: [“babelify”]}とすれば Babeliy を使うことを指定できる。ではその際のプリセットはどうすればいいか?

"scripts": {
    "watch:script": "watchify main.js -v -t babelify -d -o app.js",
    "build": "browserify main.js -o app.js"
  },
  "browserify": {
    "transform": [
      [
        "babelify",
        {
          "presets": [
            "es2015"
          ]
        }
      ]
    ]
  }

Babel の設定ファイル .babelrc

Babel の設定ファイルは .babelrc というファイルで、自動的に探して参照してくれる。しかし、同じ内容を package.json の中に書くことが出来るとマニュアルに書いてある。”babel”という項目の中に、設定を書く。

Babelify が使うプリセットの指定

Babelify が使うプリセットの指定は、.babelrc ファイルに書くように Browserify と Babelify の組み合わせで使うためのガイドラインに書いてある。さらに.babelrc は package.jsonの中に書くことが出来るわけだから、package.json 内に{“babel”:{“preset”:[ここにプリセットを書く]}とすればよい。

結果として次の様に書くことが出来る。browserify には transform に指定に babelify を指定し、babel のプリセットに関しては、babel 内に書けば良い。

  "scripts": {
    "watch:script": "watchify main.js -v -d -o app.js",
    "build": "browserify main.js -o app.js"
  },
  "babel": {
    "presets": [
      "es2015"
    ]
  },
  "browserify": {
    "transform": [
      "babelify"
    ]
  }

watchify の設定ファイル

watchify のオプションは browserify と同じだと書いてある。つまり結果として .babelrc を参照するが、なければ package.json 内を参照する。参照先はbrowserify と同じなのだと思われる。

highlighter_668843

npm scripts の完成形参照先

最終的には次のような npm scripts になると思われる。build:js と watch: js を御覧ください。私は現時点では「| exorcist」等理解できないものがあるので、これについても調べておって記事を書く。

npm-scripts で Web フロントエンド開発を管理する

次回

さしあたって JavaScript 周りのコンパイル、ビルドはできるようになったので、次はブラウザシンク、ロード、また CSS 関係のコンパイルを調べる。

npm とは何か / Package と module の違い

React-redux のコースを公開させていただきました。以下のリンクから割引価格で購入可能です。是非ご検討ください。

Udemy React Redux Course 割引適用のリンク

https://www.udemy.com/react-redux-basic/?couponCode=WEJS04

npm とは何か

例によって公式ドキュメントを勝手に日本語にします。

What is npm?

npm makes it easy for JavaScript developers to share and reuse code, and it makes it easy to update the code that you’re sharing.

npm は JavaScript 開発者がコードを共有したり、使いまわすことを簡単にしてくれます。またシェアしているコードをアップデートすることも簡単にしてくれます。

If you’ve been working with Javascript for a while, you might have heard of npm: npm makes it easy for Javascript developers to share the code that they’ve created to solve particular problems, and for other developers to reuse that code in their own applications.

JavaScript の開発をしている人であれば npm のことは聞いたことがあるはずです。npm を使えば、開発者は問題を解決するために使ったコードを多くの人と簡単に共有することが出来るので、他の開発者はそれを自分のアプリケーションで使うことができるようになります。

Once you’re depending on this code from other developers, npm makes it really easy to check to see if they’ve made any updates to it, and to download those updates when they’re made.

npm によって管理されているコードを使えば、そのコードにアップデートがある場合、すぐに確認してダウンロードすることができます。

These bits of reusable code are called packages, or sometimes modules. A package is just a directory with one or more files in it, that also has a file called “package.json” with some metadata about this package. A typical application, such as a website, will depend on dozens or hundreds of packages. These packages are often small. The general idea is that you create a small building block which solves one problem and solves it well. This makes it possible for you to compose larger, custom solutions out of these small, shared building blocks.

これらの再利用可能なコードの断片を「Packages」と呼びます。もしくはモジュールという場合もあります。パッケージは単なるディレクトリで、その中にはファイルがあります。この中には package.json というファイルもあります。これにはそのパッケージに関するメタデータが記録されています。例えばウェブサイトのような典型的なアプリケーションは、何百ものパッケージを用いています。これらのパッケージ一つ一つは大抵の場合、小さなものです。一般的な考えとして次のようなものがあります。問題一つをうまく解決してくれる小さなブロックを作るのがよい。そしてその小さなブロックをつかってより大きく、個別性の高い問題の解決策を作ることが出来ます。

There’s lots of benefits to this. It makes it possible for your team to draw on expertise outside of your organization by bringing in packages from people who have focused on particular problem areas. But even if you don’t reuse code from people outside of your organization, using this kind of module based approach can actually help your team work together better, and can also make it possible to reuse code across projects.

こういった考え方を推進するにあたって npm は大きな貢献します。パッケージを使用することで、外部のある特定の問題についての専門家の助言を採用するのと同じ利益を享受します。もちろん誰か他の人が作ったパッケージを使用しなくても、自分の組織内でうまく再利用可能なコードを作るためにも npm は役に立ちます。

You can find packages to help you build your application by browsing the npm website. When you’re browsing the website, you’ll find different kinds of packages. You’ll find lots of node modules. npm started as the node package manager, so you’ll find lots of modules which can be used on the server side. There are also lots of packages which add commands for you to use in the command line. And at this point you can find a number of packages which can be used in the browser, on the front end.

自分に役立ちそうなパッケージを探すためには npm のウェブサイト検索してください。たくさんのパッケージがありますが、npm は node 用のパッケージとしてスタートしたものなので、サーバーサイドで動くモジュールがたくさんあります。またコマンドラインで実行できるコマンドを増やすパッケージもあります。また現在ではブラウザーで動く、つまりフロントエンド用のパッケージもあります。

So now that you have an idea of what npm can do, let’s talk about how it works. When people talk about npm, they can be talking about one of three things. They could be talking about the website, which we’ve just been looking at. Or they could be talking about the registry, which is a big database of information about packages that people are sharing. Or the third thing they could be talking about is the client: when a developer decides to share their code, they use the npm client which is installed on their computer to publish that code up to the registry. And once there’s an entry for this package in the registry, then other developers can use their npm clients to install the package from the registry. The entry in the registry for this package is also reflected on the website, where there’s a page dedicated to this new package.

さあ npm がどんなことをしてくれるか概要がわかったと思うので、今度は npm がどのように機能しているのかについてお話しします。npm について誰かが話題にしていたら、これは次の3項目のうちのどれかについて話をしています。まずはウェブサイトについてです。これについては今までお話してきましたね。次に、レジストリについて話してる場合もあります。ここでいうレジストリとは、公開されたパッケージに関する膨大な情報をもったデータベースのことです。最後にクライアントについてです。開発者がコードを共有する場合に npm クライアントを用いてレジストリにコードを公開します。そして他の人が npm クライアントを用いてそのコードを使います。公開されたコードウェブサイトに使われます。

So that’s what npm is. It’s a way to reuse code from other developers, and also a way to share your code with them, and it makes it easy to manage the different versions of code.

npm がどのようなものかわかりましたね。npm は第三者が開発したコードを再利用する方法であり、開発者がコードを共有するための方法であり、そしてそれらのコードのバージョンを管理しやすくしてくれるシステムです。

Package と module の違いとは

https://docs.npmjs.com/how-npm-works/packages

One of the key steps in becoming immersed in an ecosystem is learning its vocabulary. Node.js and npm have very specific definitions of packages and modules, which are easy to mix up. We’ll discuss those definitions here, make them distinct, and explain why certain default files are named the way they are.

ある生態系について詳しくなるためには用語を学ぶことが重要です。Node.js と npm はパッケージとモジュールについてかなり詳細な定義をしています。そしてこれは混同しやすいです。これらの定義について説明しながら、明確にし、なぜ module と呼ばれるものと package と呼ばれるものがあるのかを説明します。

Quick Summary

  • A package is a file or directory that is described by a package.json. This can happen in a bunch of different ways! For more info, see “What is a package?, below.
  • A module is any file or directory that can be loaded by Node.js’ require(). Again, there are several configurations that allow this to happen. For more info, see “What is a module?”, below.
  • パッケージは package.json によって記述されるファイルもしくはディレクトリです。これは様々な方法でブランチを作ります。
  • モジュールは Node.js の require() によってロードされるファイルもしくはでょレクトリです。

What is a package?

平たくいってa)だけが重要。package.json を含んでいるということ。それを圧縮したり、url だったり色々形式はあるとのこと。

A package is any of the following:

a) a folder containing a program described by a package.json file
b) a gzipped tarball containing (a)
c) a url that resolves to (b)
d) a <name>@<version> that is published on the registry with (c)
e) a <name>@<tag> that points to (d)
f) a <name> that has a latest tag satisfying (e)
g) a git url that, when cloned, results in (a).
Noting all these package possibilities, it follows that even if you never publish your package to the public registry, you can still get a lot of benefits of using npm:

if you just want to write a node program, and/or
if you also want to be able to easily install it elsewhere after packing it up into a tarball
Git urls can be of the form:

git://github.com/user/project.git#commit-ish
git+ssh://user@hostname:project.git#commit-ish
git+http://user@hostname/project/blah.git#commit-ish
git+https://user@hostname/project/blah.git#commit-ish

The commit-ish can be any tag, sha, or branch which can be supplied as an argument to git checkout. The default is master.

What is a module?

A module is anything that can be loaded with require() in a Node.js program. The following are all examples of things that can be loaded as modules:

モジュールは Node.js の require() によってロードされるものです。次リストはモジュールとしてロードされるものの例です。

  • A folder with a package.json file containing a main field.
  • main フィールドを持つ package.json があるフォルダー
  • A folder with an index.js file in it.
  • index.js ファイルを持つフォルダー
  • A JavaScript file.
  • ただのJavaScript ファイル

Most npm packages are modules

Generally, npm packages that are used in Node.js program are loaded with require, making them modules. However, there’s no requirement that an npm package be a module!

大抵の場合 npm パッケージは Node.js の中でロードされます。ということはモジュールだということです。しかしながら、npm パッケージが必ずしも module である必要はありません。

Some packages, e.g., cli packages, only contain an executable command-line interface and don’t provide a main field for use in Node.js programs. These packages are not modules.

パッケージには、例えばCLI 用のパッケージなどは、コマンドラインで実行できるコマンドを含んでいるだけで、Node.js が使う main フィールドがないものがあります。こういったパッケージはモジュールではありません。

Almost all npm packages (at least, those that are Node programs) contain many modules within them (because every file they load with require() is a module).

ほとんどすべての npm パッケージは、(少なくともノードプログラムの場合には) たくさんのモジュールを内部に持っています。(なぜならノードの require() によってロードされるファイルはモジュールだからです。)

In the context of a Node program, the module is also the thing that was loaded from a file. For example, in the following program:

ノードのプラグラムにおいては、モジュールはファイルからロードされるものでもあります。例えば次のコードをみてください。

var req = require(‘request’)

we might say that “The variable req refers to the request module”.

このコードは「変数 rew は request モジュールを参照している」ということをいています。

File and Directory Names in the Node.js and npm Ecosystem

So, why is it the node_modules folder, but package.json file?
Why not node_packages or module.json?

なぜ node_modules フォルダーという名前で、そしてその中には package.json ファイルがあるのでしょうか。またなぜ node_package というファイルに module.json というファイルがあってはだめだったのでしょうか。

The package.json file defines the package. (See “What is a package?”, above.)

package.json ファイルはパッケージを定義しています。

The node_modules folder is the place Node.js looks for modules. (See “What is a module?”, above.)

node_modules フォルダは Node.js が「モジュールを探しに行く場所」です。

For example, if you create a file at node_modules/foo.js and then had a program that did var f = require(‘foo.js’), it would load the module. However, foo.js is not a “package” in this case because it does not have a package.json.

例えば node_modules の中に foo.js というファイルを作って、さらにそれを var f = require(‘foo.js’) とロードするプログラムを書いたとすると、これはモジュールをロードしていることになります。しかしながら、foo.js はパッケージではありません。なぜならpackage.json を持っていないからです。

Alternatively, if you create a package which does not have an index.js or a “main” field in the package.json file, then it is not a module. Even if it’s installed in node_modules, it can’t be an argument to require().

またパッケージを作ったとしても、index.js をもたないか、もしくはpackage.json に main フィールドを持たない場合、これはモジュールではありません。例え node_modules の中にあったとしても、require() の対象にはなりません。

npm script を調べる

なぜ npm script  に興味を持ったか

Sass を CSS にコンパイルしたり、ES6 を ES5 に変換したり、こまごました作業を今は Gulp で実行する人が多いと思います。Gulp は Node.js 上で動いており、Gulp で require() している対象は Node のモジュール = Node Package Module = npm  です。ということは npm のことがもっとわかれば Gulp のこともわかるはずだ、というのが npm についてもっと調べようと思った理由の一つです。

もう一つの理由は、これが直背的な理由なのですが、Gulp で Gulp 用のプラグインを使うためには、Gulp に特化した記法の学習が必要で(基本的な用途であればそこまで難しくないのですが)、それよりも CLI(コマンドラインインターフェイス、つまり Mac ならターミナルからコマンドで実行する方法など) のほうが楽だという流れがあるらしく、たしかにいくつかの作業は CLI から直接 npm を実行したほうが簡単にできました。(例えば Browserify のビルドを、対象のファイルをウォッチして、さらに差分だけをビルドする作業は、Wachify を CLI から実行すると非常に簡単です。しかし Gulp-watchify を使って Gulp のタスクを書くのは私には非常に複雑に思えました) そしてこの CLI で実行するためのコマンドは、package.json に npm script という形で記述すれば、CLI から npm start といった簡略したコマンドで実行できることもわかりました。ですので、この npm script という仕組みをより学べば、npm を実行する方法をより理解することができると思いました。

さらに具体的には、一部の npm は CLI で実行する際に明記するオプションを、どうやら package.json の中にかけるのですが、これがどういった仕組みで参照されているのかわからなかったので、npm script についての理解をもっと根本的にする必要を感じました。具体的には次のような packgage.json ファイルです。(引用元)

babel, browserify といった項目があり、これが明らかに CLI で npm を実行する際に必要なオプションの内容であるのは間違いないのですが、なぜここに書いて参照されるのか謎でした。

{
  "name": "front-end-starter",
  "version": "1.2.0",
  "description": "This is a starter kit of the Web front-end development.",
  "author": "akabeko",
  "license": "MIT",
  "main": "index.js",
  "keywords": [
    "web",
    "frontend",
    "starter"
  ],
  "repository": {
    "type": "git",
    "url": "https://github.com/akabekobeko/examples-web-app"
  },
  "babel": {
    "presets": [
      "latest"
    ],
    "env": {
      "development": {
        "presets": [
          "power-assert"
        ]
      }
    }
  },
  "browserify": {
    "transform": [
      "babelify"
    ]
  },
  "esdoc": {
    "source": "./src/js",
    "destination": "./esdoc",
    "test": {
      "type": "mocha",
      "source": "./test"
    }
  },
  "scripts": {
    "test": "mocha --compilers js:babel-register test/**/*.test.js",
    "start": "npm run watch",
    "esdoc": "esdoc",
    "build:css": "stylus -c --include-css ./src/stylus/App.styl -o ./src/assets/bundle.css -m --sourcemap-base ../stylus",
    "build:js": "browserify ./src/js/App.js -d | exorcist ./src/assets/bundle.js.map &amp;amp;amp;gt; ./src/assets/bundle.js",
    "build": "npm-run-all -p build:css build:js",
    "watch:css": "stylus -c -w --include-css ./src/stylus/App.styl -o ./src/assets/bundle.css -m --sourcemap-base ../stylus",
    "watch:js": "watchify ./src/js/App.js -v -o \"exorcist ./src/assets/bundle.js.map &amp;amp;amp;gt; ./src/assets/bundle.js\" -d",
    "watch:server": "browser-sync start --server ./ --startPath src/assets/",
    "watch": "npm-run-all -p watch:css watch:js watch:server",
    "release:css": "stylus -c --include-css ./src/stylus/App.styl -o ./dist/bundle.css",
    "release:js": "cross-env NODE_ENV=production browserify ./src/js/App.js | uglifyjs -c warnings=false -m &amp;amp;amp;gt; ./dist/bundle.js",
    "release:clean": "rimraf ./dist",
    "release:copy": "cpx \"./src/assets/**/!(*.js|*.css|*.map)\" ./dist",
    "release": "npm-run-all -s release:clean release:copy -p release:css release:js"
  },
  "dependencies": {
    "normalize.css": "^5.0.0"
  },
  "devDependencies": {
    "babel-preset-latest": "^6.16.0",
    "babel-preset-power-assert": "^1.0.0",
    "babel-register": "^6.18.0",
    "babelify": "^7.3.0",
    "browser-sync": "^2.18.6",
    "browserify": "^13.3.0",
    "cpx": "^1.5.0",
    "cross-env": "^3.1.4",
    "esdoc": "^0.5.2",
    "exorcist": "^0.4.0",
    "mocha": "^3.2.0",
    "npm-run-all": "^4.0.0",
    "power-assert": "^1.4.2",
    "rimraf": "^2.5.4",
    "stylus": "^0.54.5",
    "uglify-js": "^2.7.5",
    "watchify": "^3.8.0"
  }
}

例えば CLI で Browserify を実行するためには、次のように transform オプションを入力しますが、上記の npm script “build:js”には全く書いておらず、そのかわりにそれに相当する文言は繰り返しになりますが package.json に書かれています。

$ browserify main.js -o app.js -transform [ babelify --presets [ es2015 ] ] --debug

ということで、npm と npm script への理解を深めれば、環境構築のための基礎知識が深まり、根本的な理解をすることができるようになる、というのが今回の動機です。

npm とは

例によって公式ドキュメントを勝手に日本語にします。(もちろん日本語で npm を詳細に解説しているサイトは無限にあるのですが、最終的には自分で公式ドキュメントを読まなくてはいけないフェーズが必ずくるので、なるべくは公式を読むようにしています)

What is npm?

npm makes it easy for JavaScript developers to share and reuse code, and it makes it easy to update the code that you’re sharing.

npm は JavaScript 開発者がコードを共有したり、使いまわすことを簡単にしてくれます。またシェアしているコードをアップデートすることも簡単にしてくれます。

If you’ve been working with Javascript for a while, you might have heard of npm: npm makes it easy for Javascript developers to share the code that they’ve created to solve particular problems, and for other developers to reuse that code in their own applications.

JavaScript の開発をしている人であれば npm のことは聞いたことがあるはずです。npm を使えば、開発者は問題を解決するために使ったコードを多くの人と簡単に共有することが出来るので、他の開発者はそれを自分のアプリケーションで使うことができるようになります。

Once you’re depending on this code from other developers, npm makes it really easy to check to see if they’ve made any updates to it, and to download those updates when they’re made.

npm によって管理されているコードを使えば、そのコードにアップデートがある場合、すぐに確認してダウンロードすることができます。

These bits of reusable code are called packages, or sometimes modules. A package is just a directory with one or more files in it, that also has a file called “package.json” with some metadata about this package. A typical application, such as a website, will depend on dozens or hundreds of packages. These packages are often small. The general idea is that you create a small building block which solves one problem and solves it well. This makes it possible for you to compose larger, custom solutions out of these small, shared building blocks.

これらの再利用可能なコードの断片を「Packages」と呼びます。もしくはモジュールという場合もあります。パッケージは単なるディレクトリで、その中にはファイルがあります。この中には package.json というファイルもあります。これにはそのパッケージに関するメタデータが記録されています。例えばウェブサイトのような典型的なアプリケーションは、何百ものパッケージを用いています。これらのパッケージ一つ一つは大抵の場合、小さなものです。一般的な考えとして次のようなものがあります。問題一つをうまく解決してくれる小さなブロックを作るのがよい。そしてその小さなブロックをつかってより大きく、個別性の高い問題の解決策を作ることが出来ます。

There’s lots of benefits to this. It makes it possible for your team to draw on expertise outside of your organization by bringing in packages from people who have focused on particular problem areas. But even if you don’t reuse code from people outside of your organization, using this kind of module based approach can actually help your team work together better, and can also make it possible to reuse code across projects.

こういった考え方を推進するにあたって npm は大きな貢献します。パッケージを使用することで、外部のある特定の問題についての専門家の助言を採用するのと同じ利益を享受します。もちろん誰か他の人が作ったパッケージを使用しなくても、自分の組織内でうまく再利用可能なコードを作るためにも npm は役に立ちます。

You can find packages to help you build your application by browsing the npm website. When you’re browsing the website, you’ll find different kinds of packages. You’ll find lots of node modules. npm started as the node package manager, so you’ll find lots of modules which can be used on the server side. There are also lots of packages which add commands for you to use in the command line. And at this point you can find a number of packages which can be used in the browser, on the front end.

自分に役立ちそうなパッケージを探すためには npm のウェブサイト検索してください。たくさんのパッケージがありますが、npm は node 用のパッケージとしてスタートしたものなので、サーバーサイドで動くモジュールがたくさんあります。またコマンドラインで実行できるコマンドを増やすパッケージもあります。また現在ではブラウザーで動く、つまりフロントエンド用のパッケージもあります。

So now that you have an idea of what npm can do, let’s talk about how it works. When people talk about npm, they can be talking about one of three things. They could be talking about the website, which we’ve just been looking at. Or they could be talking about the registry, which is a big database of information about packages that people are sharing. Or the third thing they could be talking about is the client: when a developer decides to share their code, they use the npm client which is installed on their computer to publish that code up to the registry. And once there’s an entry for this package in the registry, then other developers can use their npm clients to install the package from the registry. The entry in the registry for this package is also reflected on the website, where there’s a page dedicated to this new package.

さあ npm がどんなことをしてくれるか概要がわかったと思うので、今度は npm がどのように機能しているのかについてお話しします。npm について誰かが話題にしていたら、これは次の3項目のうちのどれかについて話をしています。まずはウェブサイトについてです。これについては今までお話してきましたね。次に、レジストリについて話してる場合もあります。ここでいうレジストリとは、公開されたパッケージに関する膨大な情報をもったデータベースのことです。最後にクライアントについてです。開発者がコードを共有する場合に npm クライアントを用いてレジストリにコードを公開します。そして他の人が npm クライアントを用いてそのコードを使います。公開されたコードウェブサイトに使われます。

So that’s what npm is. It’s a way to reuse code from other developers, and also a way to share your code with them, and it makes it easy to manage the different versions of code.

npm がどのようなものかわかりましたね。npm は第三者が開発したコードを再利用する方法であり、開発者がコードを共有するための方法であり、そしてそれらのコードのバージョンを管理しやすくしてくれるシステムです。

Package と module の違いとは

https://docs.npmjs.com/how-npm-works/packages

One of the key steps in becoming immersed in an ecosystem is learning its vocabulary. Node.js and npm have very specific definitions of packages and modules, which are easy to mix up. We’ll discuss those definitions here, make them distinct, and explain why certain default files are named the way they are.

ある生態系について詳しくなるためには用語を学ぶことが重要です。Node.js と npm はパッケージとモジュールについてかなり詳細な定義をしています。そしてこれは混同しやすいです。これらの定義について説明しながら、明確にし、なぜ module と呼ばれるものと package と呼ばれるものがあるのかを説明します。

Quick Summary

  • A package is a file or directory that is described by a package.json. This can happen in a bunch of different ways! For more info, see “What is a package?, below.
  • A module is any file or directory that can be loaded by Node.js’ require(). Again, there are several configurations that allow this to happen. For more info, see “What is a module?”, below.
  • パッケージは package.json によって記述されるファイルもしくはディレクトリです。これは様々な方法でブランチを作ります。
  • モジュールは Node.js の require() によってロードされるファイルもしくはでょレクトリです。

What is a package?

平たくいってa)だけが重要。package.json を含んでいるということ。それを圧縮したり、url だったり色々形式はあるとのこと。

A package is any of the following:

a) a folder containing a program described by a package.json file
b) a gzipped tarball containing (a)
c) a url that resolves to (b)
d) a <name>@<version> that is published on the registry with (c)
e) a <name>@<tag> that points to (d)
f) a <name> that has a latest tag satisfying (e)
g) a git url that, when cloned, results in (a).
Noting all these package possibilities, it follows that even if you never publish your package to the public registry, you can still get a lot of benefits of using npm:

if you just want to write a node program, and/or
if you also want to be able to easily install it elsewhere after packing it up into a tarball
Git urls can be of the form:

git://github.com/user/project.git#commit-ish
git+ssh://user@hostname:project.git#commit-ish
git+http://user@hostname/project/blah.git#commit-ish
git+https://user@hostname/project/blah.git#commit-ish

The commit-ish can be any tag, sha, or branch which can be supplied as an argument to git checkout. The default is master.

What is a module?

A module is anything that can be loaded with require() in a Node.js program. The following are all examples of things that can be loaded as modules:

モジュールは Node.js の require() によってロードされるものです。次リストはモジュールとしてロードされるものの例です。

  • A folder with a package.json file containing a main field.
  • main フィールドを持つ package.json があるフォルダー
  • A folder with an index.js file in it.
  • index.js ファイルを持つフォルダー
  • A JavaScript file.
  • ただのJavaScript ファイル

Most npm packages are modules

Generally, npm packages that are used in Node.js program are loaded with require, making them modules. However, there’s no requirement that an npm package be a module!

大抵の場合 npm パッケージは Node.js の中でロードされます。ということはモジュールだということです。しかしながら、npm パッケージが必ずしも module である必要はありません。

Some packages, e.g., cli packages, only contain an executable command-line interface and don’t provide a main field for use in Node.js programs. These packages are not modules.

パッケージには、例えばCLI 用のパッケージなどは、コマンドラインで実行できるコマンドを含んでいるだけで、Node.js が使う main フィールドがないものがあります。こういったパッケージはモジュールではありません。

Almost all npm packages (at least, those that are Node programs) contain many modules within them (because every file they load with require() is a module).

ほとんどすべての npm パッケージは、(少なくともノードプログラムの場合には) たくさんのモジュールを内部に持っています。(なぜならノードの require() によってロードされるファイルはモジュールだからです。)

In the context of a Node program, the module is also the thing that was loaded from a file. For example, in the following program:

ノードのプラグラムにおいては、モジュールはファイルからロードされるものでもあります。例えば次のコードをみてください。

var req = require(‘request’)

we might say that “The variable req refers to the request module”.

このコードは「変数 rew は request モジュールを参照している」ということをいています。

File and Directory Names in the Node.js and npm Ecosystem

So, why is it the node_modules folder, but package.json file?
Why not node_packages or module.json?

なぜ node_modules フォルダーという名前で、そしてその中には package.json ファイルがあるのでしょうか。またなぜ node_package というファイルに module.json というファイルがあってはだめだったのでしょうか。

The package.json file defines the package. (See “What is a package?”, above.)

package.json ファイルはパッケージを定義しています。

The node_modules folder is the place Node.js looks for modules. (See “What is a module?”, above.)

node_modules フォルダは Node.js が「モジュールを探しに行く場所」です。

For example, if you create a file at node_modules/foo.js and then had a program that did var f = require(‘foo.js’), it would load the module. However, foo.js is not a “package” in this case because it does not have a package.json.

例えば node_modules の中に foo.js というファイルを作って、さらにそれを var f = require(‘foo.js’) とロードするプログラムを書いたとすると、これはモジュールをロードしていることになります。しかしながら、foo.js はパッケージではありません。なぜならpackage.json を持っていないからです。

Alternatively, if you create a package which does not have an index.js or a “main” field in the package.json file, then it is not a module. Even if it’s installed in node_modules, it can’t be an argument to require().

またパッケージを作ったとしても、index.js をもたないか、もしくはpackage.json に main フィールドを持たない場合、これはモジュールではありません。例え node_modules の中にあったとしても、require() の対象にはなりません。

 

代表的なNode Module

  • Babel
  • Node-Sass
  • Browserify

ES5のクラス class もどき prototype

See the Pen used class js by nakanishi (@nakanishi) on CodePen.

ES5 にクラスはない。コンストラクタでインスタンスを作成するが、このコンストラクタも実態は単なる関数。関数を実行してオブジェクトを作っているだけ。

作成されるインスタンスは、プロパティをコンストラクタで定義され、メソッドはそのコンストラクタ.prototypeにあるものを「参照」する。

クラスを extend するためには、プロトタイプチェーンを使って継承する。

メソッドを継承するのは簡単だが、コンストラクタを継承するには少し細かく書く。callで元のコンストラクタを、新しいコンストラクタで初期化する内容を書く部分で実行する。

var Human4 = function (name){
 //プロパティ
 this.name = name;
 //メソッド 
};

//prototypeが大事
Human4.prototype.callOwnName = function(){
 console.log("Human4: my name is " + this.name ); 
 };
//あらたにManクラスを作成
var Man = function(name,job){
	//受けうつぐuman4つまりコンストラクタを、このコンテキストのthisで実行。引数はname
	Human4.call(this,name);
	this.job = job;
};
//Humanを継承
Man.prototype = new Human4();
//Manだけのメソッドを追加
Man.prototype.myJob = function(){console.log("my job is "+ this.job);};

//インスタンスを作成
var nakanishiMan = new Man("nakanishiMan","Web Developper");
nakanishiMan.bark();
console.log(nakanishiMan.job);
nakanishiMan.myJob();

Browserify, WebPack あたりの学習

JavaScriptのモジュール管理(CommonJSとかAMDとかBrowserifyとかwebpack)

JS以外のプログラミング言語で一般的に使われている規格・仕組みがJSにはないので、それを実装するために生まれたのがCommonJS(前身はServerJSという名前でサーバーサイドで動くJSのAPIを標準化するのが目的だった。Node.jsなどにもつながっていく) そのなかでモジュールを扱う方法が今回のテーマ。

元々 CommonJS AMD = Asynchronous Module Definition Webpack
ブラウザでの実装のため Browserify RequireJS
方式 そのまま実行するのではなく、ビルドしておく 実行時に非同期でロードして、依存関係を解消する モジュールをサポートする点は他の2つと同じ。加えてCSSや読み込む画像ファイルなども含めて、単一のファイルに書き出してくれる。ばべr

選択肢は Browserify を gulp に仕込んで使うか、Webpack を使うか。まずは歴史の古い Browserify から学習する。

Browserify

Node モジュール。そのため npm で管理する。まずは npm でインストール。

npm install -g browserify

以下のコマンドでビルド

browserify 元のファイル > 出力先のファイル

Transform

例えば ES6 をbabelを使って変換した後に、Browserify でビルドしてくれる機能。

リスト

https://github.com/substack/node-browserify/wiki/list-of-transforms

Babelify

Browserify で Babel を使って transform するための npm ライブラリ。

https://github.com/babel/babelify

インストール

これをするまえに npm init しておく

$ npm install --save-dev babelify

コマンドラインで実行

  • -o output 先
  • -t transform の設定
  • babelify を使って、babelify の preset の es2015 と react でtransform する
  $ browserify script.js -o bundle.js -t [ babelify --presets [ es2015 react ] ] --debug
 $ browserify main.js -o app.js -t babelify

これだけだとimport exportができない。babelify のプリセットを入れる。

npm install –save-dev babel-preset-es2015

でオプションを入れて実行

$ browserify main.js -o app.js -t [ babelify --presets [ es2015 ] ] --debug

次のようなファイルをエクスポート・インポートしている

//module1.js
export class Module1{
    constructor() {
        //自身のメソッドを実行
        this.callStart();
    }

    //メソッド
    callStart() {
        alert("heaeaaaaa");
    }
}



//main.js
"use strict";
import { Module1 } from './module1.js';
new Module1();

ここまではできた

npm にあるライブラリをブラウザで使う

npm install jquery --save

使うところで次のコードを書く

import $ from 'jquery';
もしくは以下のコード
import jquery from 'jquery';
window.jQuery = jquery;
window.$ = jquery;

import できていないと思っていたが…

普通にできており、問題は単純にready前に実行していたから。以下のように書いて準備ができてから実行すること。

$(function(){
    // 実行する処理
    new Module1();
    $(".target").html("ffsdfsdfsdfsdfsdfsdfsdfsdfsdfsdfsdfsdfs");
    let jQueryValue = $(".target").html();
    console.log(jQueryValue);
});

Gulpで実行する

まずはインストール

$ npm install -g gulp //全く使ったこと無いときだけこれを
$ npm install --save-dev gulp

タスクを書くための gulpfile.js を作成、これはルートに置けばいいのだろうか…→さしあたってOK

//まずはnpmをインポートする
const gulp = require('gulp');

//タスクを登録'hello'という名前
gulp.task('hello', function() {
    console.log('Hello gulp!');
});

//デフォルトで実行されるタスクに'hello'タスクを登録
//gulp で実行すると使える
gulp.task('default', ['hello']);

色々入れる

Browserifyが出力する形式をgulpで扱うためのvinyl(ビニール)という形式に変換するために以下のモジュールを入れる。

$ npm install vinyl-source-stream –save-dev

//まずはnpmをインポートする
const gulp = require('gulp');
const browserify = require("browserify");
const babelify = require("babelify");
const source = require("vinyl-source-stream"); //gulpで使うストリーム形式に変換


//Browserify + babelify
gulp.task('build:scripts', function() {
    return browserify('./main.js') //対象のファイル
        .transform("babelify", {presets: ["es2015"]}) オプション
        .bundle()
        .pipe(source('app.js')) 変換かつ出力するファイル名も指定
        .pipe(gulp.dest('./')); 出力先。これは同じところに。
});

watchify で browserify を差分だけ実行してくれる

Watchify は Browserify の開発者が作っているもので、差分だけをコンパイルすることでかなり早い。これも本当は Gulp から実行できるのだが、ちょっと難しかった。

色々検索した所、package.json の script に書いてしまえば、普通に CLI で実行するのと同じように実行できるとのこと。npm script という名前。

//package.json
{
  "name": "browserify-test",
  "version": "1.0.0",
  "main": "main.js",
  "dependencies": {
    "jquery": "^3.1.1"
  },
  "devDependencies": {
    "babel-preset-es2015": "^6.22.0",
    "browserify": "^14.1.0",
    "gulp": "^3.9.1",
    "vinyl-source-stream": "^1.1.0",
    "watchify": "^3.9.0"
  },
  "scripts": {
    "watch": "watchify main.js -v -t babelify -d -o app.js",
  },
  "browserify": {//いまいち謎だが、内容的には当然browserifyのoptiion
    "transform": [["babelify", {"presets": ["es2015"]}]]
  }
}

npm run スクリプト名で実行できるので、npm run watch で実行できる。できた早い!!

さらにブラウザシンクもする

http://ceblog.mediba.jp/post/154522336717/npm-scripts

こちらのほうがわかりやすいかsass

Node.jsユーザーなら押さえておきたいnpm-scriptsのタスク実行方法まとめ

node-sass が良さそうなので入れる

npm install node-sass –save-dev

"sass": "node-sass --include-path src/sass --watch src/sass/screen.sass src/css/screen.css"

include pass は @import するファイルのある位置のはず。 –watch オプションを与えることで監視。どうやらこれだけで、import しているファイルが変化しただけでも更新してくれる模様。

次のようにすれば、同時に実行してくれる。

"start": "npm run watch:script & npm run watch:sass",

Intro to Vue.js: Vue-cli and Lifecycle Hooks 日本語へ翻訳

Intro to Vue.js: Vue-cli and Lifecycle Hooks

Vue-cli and build processes

If you haven’t yet read the last section on Vue.js components and props, I highly suggest you do so before reading this section, otherwise, some things we’ll cover will lack context.

まだ前回の コンポーネントと props についての記事を読んでいなければ、そちらを読んでからこの記事を読むよう強く推奨します。そうでないと理解できないところがあるかもしれません。

Vue offers a really nice cli that gets you up and running with your choice of a few build tools, and really nice simple starter boilerplate. It’s a lovely tool. Before installing vue-cli, you might want to check that your versions of node, and npm or yarn are up-to-date. You’d first want to install vue-cli (the -g helps you install it globally)

Vue.js は素晴らしい CLI を提供しており、これをつかえば素早く作業ができ、しかも少ないツールで済みます。また非常にシンプルなスタート用のテンプレートも用意されています。本当に素晴らしいツールです。vue-cli をインストールする前に、ノードと npm もしくは yarn のバージョンが最新のものになっているか確認しましょう。その後にインストールします。 (訳注:npm が2系だと動かなかったので、私は node を 7系、npm を3系にしたところ動いた)

$ npm install -g vue-cli

There are many builds available to you, but in our example, we’ll use webpack:

ビルドの方法がたくさんありますが、ここでは webpack を使うことにしましょう。

$ vue init webpack <project-name>

You can go through the commands that the output will give you, which will help you cd into the directory, install everything, set up your `package.json` file, and then finally serve up a local dev server at localhost:8080 with the command:

このコマンドを実行すると、Vue.js は必要なもの一式を作成し、そのディレクトリに移動し、必要なものをインストールして、package.json ファイルも生成してくれます。そして次のコマンドを実行すると、ローカル開発サーバーを立ち上げてくれます。(訳注:と書いてあるが、ディレクトリに自分で移動し、インストールも自分でnpm init でしなくてはいけない。vue-cli のバージョン2.8.1の場合)

$ npm run dev

You’re up and running! I love that the setup is so clean. You’ll start off with an App file in your `/src/` directory with a `Hello.vue` file in the `/components/` directory. This is really nice because you can see already how you’d set up these files, and how imports and exports might work.

さあ走り出しました。非常に簡潔なこのセットアップ手順を愛しています。では手始めに/src/ディレクトリの中の/components/ディレクトリ内のHello.vue ファイルを見てみましょう。これをみればファイルをどうセットアップして、インポートやエクスポートをすればいいかわかるので便利ですね。

Let’s go over this new `.vue` file extension for a moment, because if you haven’t worked with vue, you won’t have come across it before.

「.vue」拡張子がついたファイルについて少し説明をします。Vue.js に取り組んだことがない人は初めてみるファイルだと思いますので。

In your `.vue` file, you can place everything you need for your component. We no longer have to wrap our templates in <script type=”text/x-template”>, now we’ll more semantically create files that follow this logic:

.vue ファイルにはコンポーネントを作成するために必要なものを配置します。今回はもう面倒な<script type=”text/x-template”>を書く必要はなく、次のようにより見通しのいい書き方ができます。

I’ve made a repo of Vue snippets for Sublime Text to quickly spin up boilerplate like this for `.vue` files (this is what the snippet vbasewould output). There’s also this one for atom, (though it specifies version 1+, and Vue is at v2), and this for vscode.

A few things to note here: just like in React, you have to return exactly one enclosing tag, here I’ve used a div. I’ve also used <g>elements in SVG. It can be anything, but the entire template must be wrapped in the one tag.

You’ll see that we’ll use export default here to write our scripts such as the data function or methods we used previously, but if we were to use components as children in this `.vue` document, we would also have to import them (more on this in a minute).

Intro to Vue.js: Components, Props, and Slots

なるべくもとの文章に忠実に翻訳するようにしましたが、原文だけでは自分が理解できない箇所に関しては、大幅に文言を追加しています。

元の記事

Intro to Vue.js: Components, Props, and Slots

Components and Passing Data

コンポーネントとコンポーネントにデータを渡す方法

If you’re familiar with React or Angular2, the idea of components and passing state won’t be new to you. In case you’re not, let’s go through some of the main concepts.

React や Angular2 に馴染みがある人であれば、コンポーネントという概念をご存知でしょうし、状態をコンポーネントに渡すというのも、目新しいものではないとおもいます。しかし、今回はあまり馴染みがない人のために、コンポーネントの主要な機能について体験していこうと思います。

Websites large and small are usually composed of different pieces, and abstracting them into smaller pieces makes them easy to structure, reason about, reuse, and makes our code more legible. Instead of digging through all of the markup in long, multi-faceted page, we could comprise it of components like this:

ウェブサイトは大きなものであれ小さなものであれ、様々な断片によって構成されていますが、これらの断片を抽象化することによって、構造化することも、理解することも、使いまわすことも、簡単になりますし、そしてなによりもコードの可読性を上げてくれます。何ページにもわたる非常に長いコードを書くのではなく、次のようにコンポーネントで構成することができます。

This is a simplified example, but you can see how useful this type of composition can be as you start to build out the structure of your site. If you were to dive into this code as a maintainer, it wouldn’t take much to understand how the application is structured or where to look for each piece.

これは単純化された例であって実際に機能するものではありませんが、このように構成することができればどんなに便利なことか、御理解いただけるはずです。もちろん一からウェブサイトの構成を作り上げるときにも便利ですし、また他人が作ったコードをメンテナンスする際にも、どのような構造になっているのか理解するための時間を減らすことになりますし、どこに何があるのか探すのも簡単です。

Vue lets us create components in a few different ways. Let’s work from simple to complex, keeping in mind that the complex example is truest to form for what an average Vue application would look like.

Vue.js でコンポーネントを作る方法はいくつかあります。簡単なものから初めて複雑なものにも一緒にチャレンジしていきましょう。?次の一文わからず

This works, but isn’t terribly useful as it can only be used once and we’re not yet passing the information to different components. One way to pass data from a parent to a child is called props.

これでも機能はしますが、そこまで便利というわけではありません。なぜなら使いまわすことができませんし、情報を異なるコンポーネントに渡してもいません。情報を親から子へ渡す方法として「Props」という機能があります。

This is as simple an example as I could make, so that it’s super clear. Remember that the :text in the HTML is a shortcut for Vue binding. We covered this last time in the section on directives. Binding can be used for all kinds of things but in this instance, it keeps us from having to place the state in a mustache template, like this {{ message }}.

次の例はできるだけ簡単になるように努力しましたので、非常にわかりやすいはずです。「:text」は v-bind の省略形です。(詳しくは前回を見てください) Vue.js におけるバインディングは様々な用途に用いられますが、今回は口ひげ構文({{ message}})と書くことなく状態 = state を配置するために使用しています。

訳者解説:次のcodepenを参照してください。v-bind:text=””と:text=””は同じ効果を発揮します。そしてその効果は、コンポーネントの props に””内の値を渡すことです。ただし、v-bind 等のディレクティブを付けた場合、””内は JS として理解されますので、”message”は単なる文字列ではなく、Vue.message、つまりVueインスタンス内のデータの message プロパティの値を参照します。 また、単に文字列を渡すだけであれば、v-bind を用いずに、text=””とし、 props に渡すこともできます。同様に text=”message” のように、v-bind は用いずに、しかしVue インスタンスを参照した場合には、アップデートはされず、DOM が生成された時に一度だけ参照することになります。

See the Pen used vue.jscomponent by nakanishi (@nakanishi) on CodePen.

In the code below, Vue.component is the component, and new Vue is called the instance. You can have more than one instance in an application. Typically, we’ll have one instance and several components, as the instance is the main app.

下記のコードでは、「Vue.component」はコンポーネントを作成しており、「new Vue」はインスタンスを作成しています。アプリケーション中でいくつものVuie インスタンスを作ることができますが、通常は 1つだけのインスタンスに、複数のコンポーネントを関連付けて使用します。

Now we can reuse this component as many times as we like through our application:

上記のようにすれば、コンポーネントを好きなだけ何回でも使いまわすことができます。

We can also add validation to our props, which is similar to PropTypes in React. This is nice because it’s self-documenting, and will return an error if it’s not what we expected, but only in development mode:

validation (訳注:データの型やデータの有無をチェックする仕組み) を加えることもできます。これは React のPropTypes とよく似た機能です。これによってどんな値が入るべきなのか、コード自体が自分自身を説明してくれますし、制限外の値が入ってきた場合には、開発モードであればエラーを返します。

In the example below, I’m loading Vue in development mode, and purposefully passing an invalid type into our prop validation. You can see the error in the console. (It also helpful lets you know you can use Vue’s devtools and where to find them).

下記の例では、開発モードで意図的に誤った値を validation を与えた prop に代入してみました。すると、エラーがコンソールに表示されます。

Objects should be returned as a factory function and you can even pass as a custom validator function, which is really nice because you can check values against business, input, or other logic. There’s a nice write-up of how you’d use each type in the guide here.

(訳に自信なし、というか英文ではなくて挙動をもとに書いてます、ここ) コンポーネントの props に値を渡すためには、Vue インスタンスの data の中身は、factory function によって作られたオブジェクトが return されるようにしましょう。またこうすれば validation をも与えることができます。 (つまりdata(){return {message:”hello”, count:0} }というような形で書かれる必要がある。このdata関数は、実行されると新しいオブジェクトを作成する。このあたらしくオブジェクトを作成する性質=ファクトリーだと思われる。こうしなくてはいけない理由は次にカウントアップのコードをみるとわかる。毎回別のオブジェクトがつくられないと、データーの中身を共有することになるので、同一のコンポーネントから作られたものは、全てデーターがおなじになってしまう。それを避けるためには、コンポーネントが作成された際に、data関数が実行されて、新しいオブジェクトが返されるようにすればいい、ということだろうか…)

You don’t need to necessarily pass the data in props to the child, either, you have the option of using state or a static value as you see fit:

コンポーネントに props を介してデータを、必ず与えなくてはいけないわけではありませんし、渡す場合にも Vue インスタンスの 状態=state を渡す選択肢と、固定値 = static value を渡す選択肢の2つがあります。これは自分の必要とする機能に応じておこなえばよいでしょう。

The difference is whether or not you’re passing a property and binding it:

Vue インスタンスのプロパティを渡してバインディングするか、しないかの違いについて説明します。

Not using the state
<child count=”1″></child>

上記の例は Vue インスタンスのプロパティを渡していませんし、またバインディングもしていません。つまり単に定数の 1 を渡しているだけです。

vs

Using the state
<child :count=”count”></child>

上記の例は「:」によってバインディングをしているし、Vue インスタンスの値、つまり状態 = state である「count」を props を通して渡しています。

Up until now, we’ve been creating content in our child component with a string, and of course if you’re using babel so that you can process ES6 in all browsers (which I highly suggest), you could use a template literal to avoid potentially hard-to-read string concatenation:

バベルを使って ES6 を使えば、面倒な文字連結が簡単になるよ。

This is a little more useful, but there’s still a limit to how much content we probably want to put in that string, even with the help of template literals. Eventually in this comment form we’d want to have photos and the names of the authors, and you can already probably guess how crowded it would get with all that information. We also won’t have any useful syntax highlighting within that string.

上記のコードのように、コンポーネントにテンプレートを与えると便利なことは確かなのですが、文字列を延々書いていくことになるので、限界があります。最終的にはこのコメントフォームにコメントした人の画像と、名前を入れたいと思っているのですが、そうするとかなりソースがごちゃごちゃしそうですよね。しかし、残念なことに、コンポーネントにテンプレートを与えて、その中に文字列を書いていく方法では、これ以上うまく書く構文はありません。

With all those things in mind, let’s create a template. We’ll wrap some regular HTML in special script tags and use an id to reference it to create a component. You can see that this is a lot more legible when we have a lot of text and elements:

こういった問題を念頭において、テンプレートをつくってみましょう。普通の  HTML を特別なスクリプト・タグで包み込み、これをidで参照することでコンポーネントを作ります。こうすることで可読性がさらに高まり、テンプレートの中に沢山の要素を配置して文字列が長くなっても理解できます。

See the Pen Photo App post with Vue.js by Sarah Drasner (@sdras) on CodePen.

ここまでの訳者の個人的なまとめ

props と template をコンポーネントに与える書き方。

See the Pen used vue.js matome1 by nakanishi (@nakanishi) on CodePen.

HTML 内に script としてテンプレートを規定して、コンポーネントから ID でそれを参照する記法。

See the Pen used vue.js matome2 by nakanishi (@nakanishi) on CodePen.

コンポーネントにそれぞれ個別の値を持たせるためには、コンポーネントの定義にfunction(){return{オブジェクト}}を与える。そうすれば、コンポーネントが作成された時に、そのインスタンスにこの値が与えられる。factory 関数。

See the Pen used vue.js matome3 by nakanishi (@nakanishi) on CodePen.

Slots

This is a lot better. But what happens when we have two components with slight variations, either content or style deviations? We could pass all the different content and styles down into the component with props, and switch everything out each time, or we could fork the components themselves and create different versions of them. But it would be really nice if we could reuse the components, and populate them with the same data or functionality. This is where slots come in really handy.

上記のサンプルはかなりよくなりました。でも、微妙に異なる2つのコンポーネントを使用したい場合、どうすればいいでしょうか?コンテンツやスタイルが少し異なる場合です。今のところ props を使って、それぞれ微妙に異なるコンテンツやスタイルを渡すことで実現してきました。しかしもっと簡単にそれを実現する方法があります。それが slot です。

Let’s say we have a main app instance using the same <app-child> component twice. Inside each child we want some of the same content, and some different content. For the content we want to stay consistent, we would use a standard p tag, and for the content we want to switch out, we’ll put an empty <slot></slot> tag.

同じコンポーネントを二回使いながら、しかしそれぞれに異なるコンテンツと、それからもちろん共通するコンテンツを含むようにしていきましょう。次のコード例では、変化しない共通部分を通常の p タグで記述し、入れ替えたい部分を slot タグで記述しました。

Then, in the app instance, we can pass content inside the <app-child> component tags and it will automatically fill up the slots:

そうすることで、<app-child>コンポーネントの中に記述したコンテンツを(訳注:例えば<h3>this is slot..</h3>や<small>I can put more ..</small>など)自動的にスロットの中に挿入してくれるのです。

You can have default content within slots as well. If, in the slot itself, rather than writing <slot></slot>, you can populate it with:

slot に対してデフォルトのコンテンツを設定することもできます。次のように記述してください。

<slot>I am some default text</slot>

That default text will be used until you fill the slot with other material, which is so useful! High fives all around.

デフォルトテキストは、slotに何もないときにだけ使用されます。便利ですね!やった!

You can also have named slots. If you were to have two slots in a component, you could differentiate between them by adding a name attribute <slot name=”headerinfo”></slot> and we could access that particular slot by writing <h1 slot=”headerinfo”>I will populate the headerinfo slot!</h1>. This is extremely useful. If you have multiple slots that are named and one that isn’t, Vue will put the named content into the named slots, and whatever is left will be used to fill the remaining unnamed slots.

名前を slot につけることもできます。コンポーネント内に2つのスロットがあるとすれば、名前をつけることで識別することができます。<slot name=”headerinfo”></slot>と名前を付けたのならば、<h1 slot=”headerinfo”>とすることで、そのスロットにアクセスできます。これはとても便利です。名前が付けられたスロットとそうではないものがある場合、名前を指定したコンテンツは対応する名前付きのスロットに配置され、なにも指定しなかったコンテンツは、名前がついていないスロットに配置されます。

Here’s an example of what I mean:

Personally, if I am using more than one slot at a time, I will name all of so that it’s super clear what is going where for other maintainers, but it’s nice that Vue provides such a flexible API.

個人的には複数のスロットをコンポーネントに使う場合には全てのスロットに名前を付けます。そうしたほうが、他の誰かがメンテナンスをする時にわかりやすいからです。でも、Vue.js が柔軟な API を用意してくれているのもとてもいいと思います。

Slots example

Alternatively, we can have particular styles assigned for different components, and keep all of the content inside the same, therefore quickly and easily changing out the appearance of something. In the wine label maker below, one of the buttons will toggle the component and color based on what the user selects, and the background of the bottle and label and text will all switch, while keeping the content within stable.

ほかのアプリケーションをつくってみましょう。今度は、コンテンツは全てキープしたまま、異なるコンポーネントに切り替えてみます。つまり見た目などだけを簡単に切り替えれるようなアプリケーションです。次のコードは、ワインのラベルを作るアプリケーションで、ボタンを押すとコンポーネントが切り替わります。ユーザーが選んだ色にバックグランドが変わって、ラベルやテキストのスタイルもユーザーがボタンで選んだ内容によって切り替わります。しかし、その中のコンテンツは一定のままにしたいとしましょう。

Now, we’re putting all of the SVG image data in the main app, but it’s actually placed inside the <slot> in each component. This allows us to switch out pieces of content, or style things differently based on the usage, which is a really nice feature. You can see that we’ve allowed the user to decide which component they’ll be using by creating a button that changes the “selected” value of the component.

SVG 画像のデータは全てメインの HTML ファイルに書いてあります。これはスロットを介して渡されています。こうすることで見た目や一部のコンテンツを切り替えることができます。素晴らしい機能です。このアプリケーションはユーザーにどのコンポーネントを使うのか、ボタンで選ばせています。このボタンはコンポーネント選択のために参照している”selected”の値変更します。

Right now we have everything in one slot but we could also use multiple slots, and differentiate them through naming if we’d like:

いまはスロットは一つだけですが、もちろん名前をつけて複数のスロットを使うこともできます。

We can switch between different components with the same referenced slots easily, but what happens when we want to be able to switch back and forth, but hold on to the individual state of each component? Currently, when we switch between black and white the templates switch out and the content stays the same. But maybe we have a situation where we want the black label to be completely different than the white label. There’s a special component you can wrap it in called <keep-alive></keep-alive> that will retain the state as you switch.

違うコンポーネントに切り替える場合、スロットの中身を同じものにするのは簡単です。しかし「それぞれ」のコンポーネントの状態を残したまま、コンポーネントを切り替えるにはどうしたらいいでしょうか。今のコードだと、コンポーネントを黒から白に切り替えた場合、テンプレートが切り替わりますが、コンテンツはそのままです。しかし黒のラベルのコンテンツと白のラベルのコンテンツをそれぞれ完全に分けたいこともあるはずです。そんな場合には<keep-alive><keep-alive>でラップすることで、コンポーネントを切り替えても、コンテンツをそれぞれキープしてくれます。

Check out this deviation of the example above- create a black label, and then a different white label, and switch between them. You will see that the state of each is preserved, and are different from one another:

下記のコードと上記のコードの挙動の違いを確認しましょう。黒いラベルを作成した後に、白いラベルにいって違う内容を作ります。そして両者を切り替えてください。それぞれの状態が保存されているのが確認できるはずです。それぞれの状態は異なっていますね。

See the Pen used simpler Vue Wine Label Maker by nakanishi (@nakanishi) on CodePen.

I love this feature of the API.

This is all nice, but for simplicity’s sake, we’ve been sticking everything in one or two files. It would be much better organized while we build out our site if we could separate the components out into different files, and import them as we need them, and truly that’s how real development in Vue is typically done, so let’s run through that next. Tune in for the next part when we talk about Vue-cli, build processes, and Vuex for state management!

私はこの API を愛しています。これでもとても素晴らしいのですが、問題を簡単にするために1つか2つのファイルの中に全てを詰め込んでしまいました。しかし、そうするよりもさらに整頓できる方法があります。コンポーネントを別のファイルに分けて、それを必要な時にインポートするという方法です。これが実際の開発現場で Vue を使う方法です。次回はこれをやってみましょう。次回は Vue-cli、ビルド、Vuex による状態管理を扱います。

ここまでの訳者の個人的なまとめ

<component :is=”状態を参照”>で、動的にコンポーネントを変えることが出来る。参照している状態が変われば、コンポーネントが変わる。

コンポーネントの中でスロットを使ってコンテンツを挿入する場合、状態とバインドした値を使っていれば、コンポーネントが変わっても、バインドされているので残される。

See the Pen used simpler dynamic component by nakanishi (@nakanishi) on CodePen.

さらに変化するコンポーネントをキープアライブで囲っておくと、コンポーネントごとに値を保ってくれる?ので、白から黒にコンポーネントを変えても、白のコンポーネントの中身は保存されており、黒から白へ戻した時に、フォントカラーや文字の内容が戻る。

See the Pen used simpler dynamic component keep-alive by nakanishi (@nakanishi) on CodePen.

名前について

キャメルケース(superMan)とケバブケース(super-man)を使い分ける必要性について。HTMLは大文字小文字を区別しないので、HTMLの中で、属性を記述するときにはケバブケースで書くこと。

  • コンポーネント名はキャメルケースで書き(childFood)、HTMLの中でカスタム要素のように書く場合にはケバブケースで書けば(child-food)、何故か対応するようにしてくれる。
  • propsについても同様で、コンポーネントの中ではhelloWorldと書いて、HTMLの中では:hellow-world=””と書けば対応する。なお、{{}}の仲やv-bind=””の中はJSになるので、キャメルケースで書いて良い。むしろキャメルケースじゃないと正確に認識しない。

See the Pen used vue.js camel by nakanishi (@nakanishi) on CodePen.

vue.js のドキュメントを日本語にする

勝手にドキュメントを日本語にするシリーズ、第二弾。先日行われたウェブ勉強会、Dist #14 のテーマでもあった Vue.js のドキュメントを勝手に日本語にします。既に日本語版のドキュメントは作られているのですが、自分の勉強のために車輪の再発明をします。

Introduction

Continue reading “vue.js のドキュメントを日本語にする”

ブラウザ位置を読み取る、動かす with scroll scrollTop

See the Pen used scroll scrollTop by nakanishi (@nakanishi) on CodePen.

ウィンドウがスクロールした時に実行するにはこれ

$(window).scroll(function(){ここに実行することをかく});

ウィンドウ=今見えてる範囲、の上端が、サイト全体からどれだけオフセットしているかを知るには、これ

let scrollTop = $(window).scrollTop();

ヴェロシティを使って、ウィンドウを1000px下にずらしたいときはこれ

$(“html”).velocity(“scroll”,{offset:1000});

対象の要素までスクロールしたいときはこれ

$(“.scrollTarget”).velocity(“scroll”,{duration: 10000});

アニメーションしてる時に、さらにアニメーションを足すとひどいことになるので、動いているものを止める

$(“html”).velocity(“stop”);

See the Pen used scroll scrollTop by nakanishi (@nakanishi) on CodePen.

offset().topで位置を取る

◯.top ☓.top()