Polymer 3.0 を始めよう🔰

この記事は、以下の意訳です。

> Hands-on with the Polymer 3.0 preview
> https://www.polymer-project.org/blog/2017-08-23-hands-on-30-preview

以下のドキュメントをお読みになる際は、最新の公式ドキュメントの不整合に注意してください。

現在、実験的にPolymer 3.0 プレビューが利用できます。しかし、"実験的"というところに注意してくさい。これは、早期プレビュー版です。間違えなく雑な部分があります。

幸運や成功というものは、何事も恐れずに大胆に行動する人に訪れます。今日も一日がんばるぞい!!

# ツールを入手

始める前に、Polymer CLIを最新にアップデートする必要があります。

```bash
npm install -g polymer-cli
```

以前、説明したように、コンポーネントをインストールするために **Yarn** パッケージマネージャをインストールする必要があります。
手順については、 [Yarn installation page](https://yarnpkg.com/en/docs/install) を参照してください。

最後に、プレビューコードを実行するには、Chrome 61以降またはSafari 10.1がインストールされている必要があります。

# Yarn で依存パッケージをインストール

[Polymerコンポーネント](https://www.npmjs.com/~polymer)は、 `@polymer` 名前空間のnpmレジストリに公開されています。Yarnを使ってコンポーネントをインストールします。

## 新しいPolymer 3.0プレビュープロジェクトを開始するには

### 1 プロジェクトの初期設定をする。

```bash
yarn init
```
実行すると対話形式で項目を入力して、package.jsonを生成します。(ほとんどの場合、全部デフォルトの設定で大丈夫だと思います。)

### 2 生成した `package.json` ファイルを編集して、 `"flat": true` プロパティを追加します。

```json
{
  "name": "my-app",
  "flat": true,
  ...
```

### 3 `yarn add` を使ってコンポーネントをインストールします。

`bower install --save` を実行するのと同じです。

例えば、

```bash
yarn add @polymer/polymer@next
yarn add @webcomponents/webcomponentsjs
```

Bowerを使用して `Polymer` または `PolymerElements` organization から以前にインストールしたコンポーネントは、 `@polymer` 名前空間からインストールできます。 **3.0プレビューパッケージを入手するには、必ず `@next` バージョンを含めてください。** `@wecomponents/webcomponentsjs` からポリフィルをインストールできます。(リリースされたバージョンのポリフィルを使用しているため、ここでは `@next` は必要ありません)

# モジュールを使う

`ES6 Modules` に熟知していない場合、 `ES6 Modules` について学ぶべきことがたくさんあります。この記事では、いくつかの重要な機能に触れます。

`ES6 Modules` についてもっと知りたいなら、Axel Rauschmayer氏のES6に関する [この章](http://exploringjs.com/es6/ch_modules.html) をお読みください。

# 依存性をインポート

`<script type="module">` を使って、HTML内でモジュールをインポートできます。例えば、 `index.html` は以下のようになります。

```html
<!doctype html>
<html>
  <head>
    <!-- ポリフィルを読み込む。 パス以外は2.x系と同じです。 -->
    <script
        src="node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js">
    </script>

    <!-- my-app 要素のモジュールをインポート -->
    <script type="module" src="src/my-app.js"></script>
  </head>
  <body>
    <my-app></my-app>
  </body>
</html>
```

モジュール内で、 `import` 文でモジュールをインポートできます。

```js
import {Element as PolymerElement}
    from "../node_modules/@polymer/polymer/polymer-element.js"
```

Bowerの依存関係と同様に、再利用可能な要素は、パスに `node_modules` を含めてはいけません。(e.g. `../@polymer/polymer/polymer-element.js`)

モジュールと `import` 文に関する重要な点がいくつかあります。

- `HTML imports` と同様に、モジュールを読み込むには、モジュール名ではなくパスを使用する必要があります。
- 読み込まれるパスは、 " `./` "、 " `../` "、または " `/` "で始めなければなりません。
- import文はモジュール内でのみ使用できます。(つまり、 `<script type = "module">` でロードされた外部ファイルまたはインラインスクリプトのことです。)
- モジュールは常に `strict mode` で実行されます。

import文にはいくつかの仕様があります。
### ほとんどの場合、要素モジュールは要素を登録しますが、シンボルをエクスポートしないので、この単純なimport文を使用できます。

```js
import "../@polymer/paper-button/paper-button.js"
```

### 振る舞い(Behavior)については、通常、振る舞いを明示的にインポートします。

```js
import {IronResizableBehavior}
    from "../@polymer/iron-resizable-behavior/iron-resizable-behavior.js"
```

### いくつかのメンバをエクスポートする `Async` のようなユーティリティモジュールでは、個々のメンバを読み込むことも、モジュール全体を読み込むこともできます。

```js
import * as Async from "../@polymer/polymer/lib/utils/async.js"

Async.microTask.run(callback);
```

3.0用のAPIドキュメントがあるまでは、ソースコードを見て、特定のモジュールがどのようなものをエクスポートするかを調べる必要があります。

## 動的インポート: まだ早い

`import（）` 演算子を使用した動的インポートの仕様はありますが、まだ実装されていません。ﾟ(T_T)![ttt.png](https://qiita-image-store.s3.amazonaws.com/0/163401/f0802774-d6e9-a301-3ca5-7c55f2486185.png)

### import演算子は関数のように動作し、 `Promise` を返します。


```js
import('my-view1.js').then((MyView1) => {
  console.log("MyView1 loaded");
}).catch((reason) => {
  console.log("MyView1 failed to load", reason);
});
```

**現在のPolymer CLIツールは、動的インポートの変換をサポートしていません。** なので、3.0ではPRPLのような遅延読み込みパターンを使用することはできません。プロダクションリリースの前に、Polymer CLIおよび関連ツールへの動的インポートのサポートを追加する予定です。

Webpackのようなツールを使用してカスタムビルド設定を使用している場合は、このの動的インポートを使用できるかもしれませんが、それはこの投稿の範疇ではありません。

# 要素の定義

HTML Importsで要素を定義する代わりに、ES6 Modulesで要素を定義します。HTMLファイルの代わりにJavaScriptファイルを作成する自明な違いを以外に、新しい仕様には3つの大きな違いがあります。

- インポートでは、 `<link rel = "import">` ではなく、ES6インポート文を使用します。
- テンプレートは、 `<dom-module>` 要素と `<template>` 要素ではなく、文字列を返す `template` ゲッター(static get template() {})で定義されます。
- グローバルを定義する(例えば、振る舞いまたはミックスインを定義する場合)代わりに、モジュールからシンボルをエクスポートするために、`export` 文を使用します。

## こんな感じ

```js:my-app.js
// Element is the same as Polymer.Element in 2.x
// Modules give you the freedom to rename the members that you import
import {Element as PolymerElement}
    from '../node_modules/@polymer/polymer/polymer-element.js';

// Added "export" to export the MyApp symbol from the module
export class MyApp extends PolymerElement {

  // Define a string template instead of a `<template>` element.
  static get template() {
    return `<div>This is my [[name]] app.</div>`
  }

  constructor() {
    super();
    this.name = '3.0 preview';
  }

  // properties, observers, etc. are identical to 2.x
  static get properties() {
    name: {
      Type: String
    }
  }
}

customElements.define('my-app', MyApp);
```

上記のように、3.0の変更以外に、要素の定義方法は2.x系と同じ感じです。
現在、2.x系 APIにはいくつかの変更が加えられており、すべて動的インポートに関連していました。特に、 `Polymer.importHref` 関数はサポートされなくなりました。これは動的ES6インポートに置き換えられる予定です。

再利用可能な要素の場合、Polymer `Element` クラスのインポートでは、 `node_modules` フォルダは省略されます。

```js
import {Element as PolymerElement}
    from '../@polymer/polymer/polymer-element.js';
```

# プロジェクトのプレビュー

プロジェクトをプレビューまたはテストするときは、新しい `--npm` フラグを使用します。

```bash
polymer serve --npm
polymer test --npm
```

このフラグは、 `bower_components` ではなく `node_modules` からコンポーネントをロードし、 `bower.json` ではなく `package.json` でパッケージ名を検索するように、devserverに指示します。

Safari 10.1またはChrome 61以降でプロジェクトを読み込んでいることを確認してください。この時点でCLIはモジュールの変換を行わないため、3.0はES6 Modulesをサポートしているブラウザでのみ動作します。

# 既存プロジェクトのアップグレード

Polymer ModulizerツールはPolymer 2.xプロジェクトをPolymer 3.0のnpmおよびES6モジュール形式にアップグレードします。
このツールは早期プレビュー版です。数週間後に解決すべき既知の問題がいくつかあります。なので、問題が発生した場合でも、心配ないしないで！できるだけ解決できるように積極的に取り組んでいます。

それでもModulizerを試したい場合は、 [README](https://github.com/Polymer/polymer-modulizer/blob/master/README.md) を参照してください。Polymer Modulizerに関するご質問がある場合は、Slackの `#modulizer` チャンネルに参加できます。

# 現状

うまくいけば、この記事で、Polymer 3.0プレビューを試してみることができます。この記事は、更新されます。

# 試す
Dockerをインストールした環境で、
以下のコマンドを実行し、 [http://localhost:8081/](http://localhost:8081/) にアクセスすると上記でやったことが再現できます。

```bash
docker run -p 8081:8081 nyanpass/polymer3
```