狛ログ

2018年12月27日木曜日

Angular5から7へのバージョンアップ・後編


オフィス狛 技術部のKoma(Twitterアカウントの中の人&CEO)です。

前回(Angular5から7へのバージョンアップ・前編)の続きとなります。 前回は、本家の手順通りにポチポチとコマンドを実行していきましたが、実際にどんな風に変更されて、どんな部分はやっぱりエラーになってしまうのか、確認していきます。

自動修正された部分の確認

まずは、前回の「更新後作業(After the Update)」で行ったマイグレーション、
rxjs-5-to-6-migrate -p src/tsconfig.app.json
について、自動で修正された部分が気になったので、どう修正されたのか確認しました。
例えば、
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/retry';
上記のような記載が、

import { Observable ,  of } from 'rxjs';
に変わっていました。

後は、
import { Subscription } from 'rxjs/Subscription';
import 'rxjs/add/operator/skip';
上記のような記載が、

import { Subscription } from 'rxjs';
に変わっていました。

自動修正されたのは、全てimportの部分でした。
今後は、基本的に「rxjs」を参照すれば、問題なさそうですね。

ビルドエラーになった部分の確認

続いて、前回バージョンアップ作業後に、ビルドエラーになっている部分を確認していきます。
エラーとなった部分の修正方法については、RxJS本家サイトの「RxJS v5.x to v6 Update Guide」を参考にしていきたいと思います。

まずは、下記のエラーメッセージ。
[ts] プロパティ 'skip' は型 'Observable<number>' に存在しません。

該当箇所は、
import { skip } from 'rxjs/operators';
// ・・・(中略)
error$ = this.store.select(fromAuth.getError).skip(1);
です。
本家サイトによると、処理をチェーンさせて行く時は、「pipe」syntaxを使用する、とあります。
よって、
error$ = this.store.select(fromAuth.getError).pipe(skip(1));
のように修正します。

続いてのエラーメッセージ、
[ts] プロパティ 'map' は型 'Observable<HttpResponse<Object>>' に存在しません。

該当箇所は、
  checkEmail(email: string): Observable<boolean> {
    return this.http
      .post('user-test/check-email', { email }, { observe: 'response' })
      .map(data => true);
  }
こちらも先程と同じ感じで修正します。
  checkEmail(email: string): Observable<boolean> {
    return this.http
      .post('user-test/check-email', { email }, { observe: 'response' })
      .pipe(map(data => true));
  }

続いてのエラーメッセージ、
[ts] プロパティ 'do' は型 'Observable<HttpResponse<{ user: HogeModel; }>>' に存在しません。
該当箇所は、
    return this.http
      .post<{ user: HogeModel }>('user-test/authenticate', body, {
        observe: 'response'
      })
      .do(console.log)
      .map(data => {
        const user = data.body.user;
        this.userId = user.id;
        return user;
      });
  }
です。
本家サイトによると、「do、catch、switchは、JavaScriptの予約語になっているので、変更しました」とあります。
よって、
    return this.http
      .post<{ user: HogeModel }>('user-test/authenticate', body, {
        observe: 'response'
      })
      .pipe(
        tap(console.log),
        map(data => {
          const user = data.body.user;
          this.userId = user.id;
          return user;
        })
      );
  }
のように修正します。それぞれの対応は以下の通りです。
  • do -> tap
  • catch -> catchError
  • switch -> switchAll
  • finally -> finalize

上記までがRxJS絡みのエラーでしたが、
他にも、下記のようなエラーが出ました。
ERROR in The Angular Compiler requires TypeScript >=3.1.1 and <3.2.0 but 3.2.1 was found instead.
これは単純にTypeScriptのバージョンを「3.1.6」にする事で解決しました。

以上で、Angular5から7へのバージョンアップが完了しました。
思ったより、やる事が少なくて意外でしたが、気軽にアップデート出来るのは最高ですね。


それでは、良いAngularライフを!


,

2018年12月11日火曜日

Angular5から7へのバージョンアップ・前編


オフィス狛 技術部のKoma(Twitterアカウントの中の人&CEO)です。

少しAngularから離れていたのですが、過去のプロジェクトをアップデートする事になったので、備忘録で作業内容を残しておこうと思います。(他にもいくつかのプロジェクトでも同じ事する必要があるので・・・・)

基本的な作業としては、こちらの手順通りになります。 バージョンは(Angular Version)は、5.2から7.0でいきます。
アプリの複雑度(App Complexity)は・・・・Mediumぐらいですかね、とりあえず。
その他の依存関係(Other Dependencies)ですが、今回のプロジェクトは、AngularJSも混在していませんし、 Angular Materialも使用していないので、チェックは付けません。
パッケージ管理(Package Manager)はnpmを使っているので、npmを選択します。

・・・・・ん???
Warning: We do not recommend moving across multiple major versions.
複数のメジャーバージョンを跨いだアップデートはオススメしない??
・・・・まあ、モノは試し、オススメしない方法でとりあえずやってみよう。

「Show me how to update!」を押すと、下記のように手順が表示されるので、順番にやっていこうと思います。

更新する前に(Before Updating)

・・・これ、もしかして、アプリの複雑度(App Complexity)によって出てくる内容違うのでは?と思ったら、案の定違うので、念の為「Advanced」の方の記載も見ておいた方が良いかもしれません。
今回のプロジェクトはこのまま「Medium」で行きます。

まずは、
If you import any animations services or tools from @angular/core, you should import them from @angular/animations
です。
以前(Angular2ぐらい?)のバージョンでは、animations系の処理はcoreに含まれてたので、それは使えないよ、と言う事ですね。
まあ、今回は元のバージョンがAngular5なので、気にする必要はなさそうです。

続いての
Switch from HttpModule and the Http service to HttpClientModule and the HttpClient service. HttpClient simplifies the default ergonomics (You don't need to map to json anymore) and now supports typed return values and interceptors. Read more on angular.io
です。
これも似たような事ですが、HttpModuleは使えないからHttpClientModuleに変更してね、と言う事ですね。
HttpClientModuleは、確かAngular 4.3 ぐらいから使えるようになった機能です。

最後の
Choose a value of off for preserveWhitespaces in your tsconfig.json to gain the benefits of this setting, which was set to off by default in v6.
です。
Angular5から追加になったpreserveWhitespacesは、tsconfig.jsonに記載するのですが、これをoff(false)にする事で、コンパイル時に余計な空白を削除することができます。 Angular6から、これはデフォルトoff(false)だよ、と注意を促してくれています。

今回は全て問題ないので、そのまま次の手順に進んで行きます。

更新作業(During the Update)

Make sure you are using Node 8 or later

Node のバージョンは8以降である必要があります。
コマンドラインやターミナル等で「node -v」を実行して確認しましょう。

Update your Angular CLI globally and locally, and migrate the configuration to the new angular.json format by running the following:

続いて、Angular CLIの最新をインストールします。
以降は、バージョンアップを行いたいプロジェクトディレクトリで実行して下さい。
npm install -g @angular/cli
npm install @angular/cli
ng update @angular/cli
グローバルのAngular CLIを更新した後、ローカルの更新を行い、最後にローカルのパッケージの更新を行なっています。
ただ、上記「npm install @angular/cli」だとローカル側のAngular CLIのバージョンが変わらなかったので、「npm install @angular/cli@latest」として最新をインストールしました。

正しく動いていると、
DELETE .angular-cli.json
CREATE angular.json (4321 bytes)
こんな感じで、旧バージョン形式である「angular-cli.json」が削除され、新バージョンの「angular.json」が作成されているはずです。

その後、もう一度「ng update @angular/cli」を行なっています。

ちなみに、プロジェクトでngrxを使っていると、モジュールに対してのワーニングが出ます。
ここでは無視して構いません。

Update any scripts you may have in your package.json to use the latest Angular CLI commands. All CLI commands now use two dashes for flags (eg ng build --prod --source-map) to be POSIX compliant.

package.jsonに記載されているscriptsは、最新のコマンドで更新してね、と言っていますね。
よくあるのが、「"build": "ng build --prod",」とかで、コマンドを簡略化するパターンですが、
最終的なコマンドはAngular CLIなので、そこは最新のコマンドに書き換えする必要があります。

Update all of your Angular framework packages to v6, and the correct version of RxJS and TypeScript.

続いて、Angular自体のアップデートを行います。(下記のコマンドを実行)
ng update @angular/core
注意書きとして、
After the update, TypeScript and RxJS will more accurately flow types across your application, which may expose existing errors in your application's typings
とあります。
AngularをUpdatesする事で、型チェック等が厳密になる為、既存のプログラムでエラーが出る可能性があるよ、と言う事ですね。まあ、その辺は想定内というか、多分別のところでエラーになるでしょう・・・。

ngModelChange is now emitted after the value/validity is updated on its control instead of before to better match expectations. If you rely on the order of these events, you will need to begin tracking the old value in your component.

Angular6以前でngModelChangeを使用している場合、実装方法によっては、変更前の値が取れてしまう問題がありましたが、
それがAngular6で修正されているので、ngModelChangeを使用しているところは注意してね、という事です。

Use ng update or your normal package manager tools to identify and update other dependencies.

先程は、Angular自体のアップデートを行ったので、個々のパッケージの依存関係は「ng update」などで更新してね、という事です。
という訳で、
ng update --all
をやっておきましょう。

ただ、ngrxを使っている場合はエラーでupdate出来ないと思います。
Package "@ngrx/store" has an incompatible peer dependency to "@angular/core" (requires "^6.0.0", would install "7.1.1")

ここは一旦強制的にupdateしてしまいます。
ng update --all --force
ng updateの度に、
@ngrx/store@6.1.2 requires a peer of @angular/core@^6.0.0 but none is installed. You must install peer dependencies yourself.
のようなワーニングは出てしまうのですが、
6.1.2はangular7に対応はしているので、一旦このままで行きます。
関連: https://github.com/ngrx/platform/issues/1397

If you have TypeScript configured to be strict (if you have set strict to true in your tsconfig.json file), update your tsconfig.json to disable strictPropertyInitialization or move property initialization from ngOnInit to your constructor. You can learn more about this flag on the TypeScript 2.7 release notes.

TypeScript 2.7から追加されたstrictPropertyInitializationについての記載です。より厳密な初期化チェックを行うかどうかのフラウですが、元々から存在しているstrictが有効になっている場合、サブセットであるstrictPropertyInitializationも有効になってしまうので、tsconfig.jsonで無効にするか、厳密なチェックに対応するようプログラムを変更してね、という事です。
(プロパティの初期化は、ngOnInitではなく、コンストラクタでやらないといけない)

更新後作業(After the Update)

Remove deprecated RxJS 6 features using rxjs-tslint auto update rules For most applications this will mean running the following two commands:

deprecatedされた機能を削除する、という事で、
これは、指示通り、以下のコマンドを実行します。
npm install -g rxjs-tslint
rxjs-5-to-6-migrate -p src/tsconfig.app.json
そうすると、変更されたファイルが表示されます。
Fixed 5 error(s) in /Users/officekoma/hoge-web-prj/src/app/auth/services/hoge1.service.ts
Fixed 1 error(s) in /Users/officekoma/hoge-web-prj/src/app/auth/services/hoge2.service.ts
// (中略)
Fixed 5 error(s) in /Users/officekoma/hoge-web-prj/src/app/home/store/effects/my-page.effect.ts
Fixed 5 error(s) in /Users/officekoma/hoge-web-prj/src/app/home/store/effects/my-page-edit.effect.ts

WARNING: /Users/officekoma/hoge-web-prj/src/app/auth/services/hoge1.service.ts[3, 1]: duplicate RxJS import

Once you and all of your dependencies have updated to RxJS 6, remove rxjs-compat.

続いて、rxjs-compatを削除します。
npm uninstall rxjs-compat

If you use the Angular Service worker, migrate any versionedFiles to the files array. The behavior is the same.

Angular Service workerを使っている場合もマイグレーションを行う必要があるようですが、
今回のプロジェクトでは使用していないので、特に何もしません。

という事で、5.2から7.0へのアップデートを行いました。
後は、個々のプログラムの中を見て、エラーとなっている部分を修正していく事になります。
長くなったので、その辺は次回ブログに記載しようと思います。

それでは、良いAngularライフを!

2018年12月7日金曜日

Photoshopでスライスツールを使わずにパーツを一気に書き出す方法。

こんにちは、オフィス狛 デザイン部のSatoです。

今回はPhotoshopで作ったモック画像からスライスツールを使わないで細かい画像を書き出す方法をご紹介しようと思います。

モック画像からスライスを設定して書き出しするのは地味に大変な作業だと自分は思っているので、できるだけ楽に作業したいと思っていましたが実はスライスツールを使うよりも、もっと楽に細かいウェブデザインのパーツを書き出す方法があったのでご紹介させていただきます。

方法1 画像アセット機能で書き出す。


1.書き出したいレイヤーのレイヤー名またはグループのグループ名を「(書き出したい画像のタイトル).(書き出したい画像拡張子)」にします。

2.Photoshopのメニューバーの「ファイル」の「生成」にマウスカーソルを合わせると「画像アセット」という項目が出てくるのでクリックします。

psdファイルを保存している場所に「(書き出したpsdファイル名)-assets」というフォルダーができているので、その中に書き出されています。


書き出せる拡張子はJPEGや透過PNG透過GIFはもちろんの事、SVGも書き出せるそうです。
個人的にはSVGが書き出せるのがうれしいですね。

詳しい設定などはAdobeのブログで解説されていますので是非参考にしてみてください。


方法2 選択したレイヤーを「書き出し形式」で書き出す。


1.書き出したいアイコンなどのパーツを移動ツール+shiftキーで全て選択します。

2.レイヤーパネルの上で右クリックして出てきたメニューから「書き出し形式」を選択します。

3.画像のサイズや拡張子を選択する画面になるのでお好みで設定を変えてください。

書き出し設定を全て終えたら、右下の全て書き出しボタンを押します。
保存するフォルダーを選択して開くボタンを押すと指定したフォルダー中に書き出されています。

この方法なら色々なサイズのアイコンを一気に書き出せるのでとても便利です。

ただ、この方法で自分が少し躓いたところが一つあります。
画像のサイズや拡張子を選択する画面で画像の解像度を変えたはずなのに、1ファイルのみその拡張子で書き出され、他の画像はもともとの拡張子のままで書き出されていました。
実は左の書き出す画像の一覧の部分で、選択した画像しか設定が反映されないようです。
書き出す画像全ての拡張子を変えたい場合はCtrlキーを押しながら全てクリックして選択してから拡張子を変えてから書き出すと全部同じ拡張子になってくれます。


どちらの機能も背景を消してスライスツールでスライスを引いて……という作業を省略できる素晴らしい機能なのですごい時短になります!
みなさんもぜひ使ってみてください。

2018年12月5日水曜日

C# foreachでListに要素を追加する方法。


オフィス狛 技術部のHammarです。

最近業務でC#を使うことが多いのですが、個人的にはまだまだやり始めでわからないことが多く、ちょっとしたことで詰まる今日この頃なんですが、基本的なところで「こういう書き方もあるんだなー」とわかったことを今回は書きたいと思います。

■foreachでListに要素追加方法

C#のCollectionであるListクラスは配列っぽいイメージですが、動的に長さ(サイズ)を自由に変えられることと、データを途中に挿入できる点が配列との大きな違いとなっています。

で、例えばListや配列を回しながら、ある条件のとき等にListに要素を追加したいとき等がよくあると思いますが、最初自分は下記のように記述していました。
ちなみに下記は配列を回しながら、indexの値と配列の中身を新たなListに作っているだけの記述です。

public class animalList
{
    public int Seq { get; set; }
    public string AnimalName { get; set; }
}

public void TestMethod()
{
    string[] animals = new string[] { "lion", "zebra", "elephant" };
    var index = 0;

    List<animalList> result = new List<animalList>();
    animalList animalListdata = null;

    foreach (var name in animals)
    {
        animalListdata = new animalList
        {
            Seq = index,
            AnimalName = name
        };
        index++;
        result.Add(animalListdata);
    }
}

上記でも作りたい形になるのですが、ほんの少しだけ簡単に記述できる方法がありました。
※animalListクラスは同じものを使います。

public void TestMethod()
{
    string[] animals = new string[] { "lion", "zebra", "elephant" };
    var index = 0;

    var result = new List<animalList>();
    foreach (var name in animals)
    {
        result.Add(new animalList
        {
            Seq = index,
            AnimalName = name
        });
        index++;
    }
}

たった2~3行だけですが、回すと同時にListにAddしているので個人的にはこっちのほうがスッキリしているように見えます。

というわけで、C#をよくご存知の方にはそんなことは基本中の基本と怒られそうですが、まだ触れてから日の浅い自分にとってはちょっとしたことですが勉強になりました。