Slide 1

Slide 1 text

ASP.NET CoreやTypeScriptの 力を借りて レガシー寄りの環境に 立ち向かいたかった話 2019/07/20 @わんくま同盟 大阪勉強会 #76 by masanori_msl

Slide 2

Slide 2 text

About me  Name:Masui Masanori  Work:Unity中心でしたが最近はWeb寄り  Twitter:https://twitter.com/masanori_msl  Blog:http://mslgt.hatenablog.com/

Slide 3

Slide 3 text

なんか社内で使うための システム作ることになりました。 あらすじ

Slide 4

Slide 4 text

 割とレガシーな環境  別のサービスが動いていたりする(あまり新規でインストールしづらい)  開発環境へは比較的自由にインストールできる( ASP.NET Core や Node.js など)  社内システムにアクセスするためのライブラリ(dll)がある 前提(環境)

Slide 5

Slide 5 text

 基本的にぼっち開発。  特にフロントエンドの経験は少ない。  レガシーな環境で動かすとはいえ、できるだけモダンな言語やフレームワークを 使いたい(そして助けてほしい)。 前提(開発者)

Slide 6

Slide 6 text

 Visual Studio Code (サーバー・クライアントサイド両方を開発する上で一番使いやすかった)  PgAdmin 4 (DB Access)  Node.js、npm、tsc、etc. 開発ツール

Slide 7

Slide 7 text

サーバーサイド( ASP.NET Core など)でのあれこれ ↓ クライアントサイド( TypeScript など)でのあれこれ お話の流れ

Slide 8

Slide 8 text

サーバーサイドでのあれこれ

Slide 9

Slide 9 text

 ASP.NET Core を使う(所属メンバー的に .NET の開発経験がある人が多いため)。  ただし社内ライブラリを使うところは ASP.NET Frameworkで。 技術選定(サーバーサイド)

Slide 10

Slide 10 text

技術選定(サーバーサイド) IIS Access URL rewrite ASP.NET Core ASP.NET Framework http://localhost:XXXX

Slide 11

Slide 11 text

開発(サーバーサイド) 実際の開発については下記から推測してください。 https://mslgt.hatenablog.com/archive/category/ASP.NET%20Core https://mslgt.hatenablog.com/archive/category/Entity%20Framework%20Core

Slide 12

Slide 12 text

開発(サーバーサイド) 今回は開発環境に .NET Core が インストールされていなくても 何とかする方法についてだけ。

Slide 13

Slide 13 text

開発(サーバーサイド) 発行時に必要なファイル( .NET Core 含む)を一緒に出力することで、 実行環境に .NET Core がインストールされてなくても実行可能に。 (Self-contained .NET Core Applications) 必要なことは① .csproj ファイルへの RuntimeIdentifier 追加と ② publish コマンドへのオプション追加。

Slide 14

Slide 14 text

開発(サーバーサイド) netcoreapp2.2 InProcess win-x86 ① .csproj ファイルへの RuntimeIdentifier 追加

Slide 15

Slide 15 text

開発(サーバーサイド) ② publish コマンドへのオプション追加 dotnet publish -c Release -r win-x86

Slide 16

Slide 16 text

開発(サーバーサイド) 参照 .NET Core application deployment – .NET Core – Microsoft Docs https://docs.microsoft.com/en-us/dotnet/core/deploying/ How to create a self contained .Net core application? https://dotnetthoughts.net/how-to-create-a-self-contained-dotnet-core-application/

Slide 17

Slide 17 text

開発(サーバーサイド) 課題 プロジェクトフォルダー > bin > Release > netcoreapp2.2 > win-x86 > publish に 発行したファイルが出力される。

Slide 18

Slide 18 text

開発(サーバーサイド) 課題 不要 これが欲しい

Slide 19

Slide 19 text

あ、Entity Framework Core は PostgreSQL が少々古くても 問題なくアクセスしてくれてました。よ。 ※ PgAdmin 4 が IE で動かないっぽいので注意 開発(サーバーサイド)

Slide 20

Slide 20 text

クライアントサイドでのあれこれ

Slide 21

Slide 21 text

 HTML5  Razor  TypeScript  PostCSS  webpack  Polyfillあれこれ 技術選定(クライアントサイド) 主に使ったもの

Slide 22

Slide 22 text

TypeScript 選択の理由  やっぱり(静的な)型が欲しい。 (実際には「静的な」型ではなく「強い」型)  いざとなったら JavaScript に変換してしまうことだってできる。

Slide 23

Slide 23 text

JavaScript の Framework は? Angular 、 React 、 Vue(ABC 順) どれも人気があるが、 下記の点が気になって今回は選択せず。  基本的に Node.js を使って動作するため、実行環境にも Node.js が必要。  半年でメジャーバージョンアップデートする Angular をはじめ(LTSはあるが)、 更新が速い。(ASP.NET Coreについては目をつぶる方針で。。。)  自分をはじめ、メンバーの中で開発経験が少ない。

Slide 24

Slide 24 text

PostCSS 選択の理由  Autoprefixer (CSS のベンダープレフィックスを自動でつけてくれる)が 使いたかった。  @import も便利(※)。  CSS 変数も便利(※)。 ※PostCSSの機能ではないが、コンパイル時1つのファイルにまとめてくれるため、 ブラウザ間の対応の違いなどを気にせず使えた。

Slide 25

Slide 25 text

webpack 選択の理由  きっかけは Pikaday(https://pikaday.com/ シンプルなデートピッカー。 IE7から対応しているらしい) を使うのに、 import / export が必要になったため。  TypeScript -> ES3 の JavaScript に変換、というのは tsc で可能だが、 import / export は別途ツールが必要。

Slide 26

Slide 26 text

Razor を使う

Slide 27

Slide 27 text

Razorを使う  DB からデータを取得する、かつ同期的にデータを更新する要素で使用。  head など各画面共通要素をひとまとめにできるの便利。  静的な HTML ファイルと比較して、サーバーサイドの Controller で ルーティングしやすいの便利。

Slide 28

Slide 28 text

Razorを使う  TypeScript( JavaScript )にデータが渡しづらい。 (ViewData などは Razor でしか扱えないため、 HTML から TypeScript に データを渡す処理を別途書く必要がある)  複数人で開発する時に、クライアントサイドを分割しづらい。 課題

Slide 29

Slide 29 text

Razorを使う この課題については良いバランスを見つけたいところ。 (その前に Blazor が来るかもしれない)

Slide 30

Slide 30 text

TypeScript を使う

Slide 31

Slide 31 text

TypeScript を使う  TypeScript  tsc (コンパイラ)  InversifyJS (Dependency Injection)  reflect-metadata (InversifyJS で使用)  pikaday (デートピッカー)  moment (日付を良い感じに扱えるようにする)  jest (テストツール) 主に使ったもの

Slide 32

Slide 32 text

TypeScript でハマったところ

Slide 33

Slide 33 text

TypeScript でハマったところ 主に TypeScript が「静的に」型を持つのではない、ということと、 最終的に JavaScript に変換される、という点に起因して、 C# 脳のまま書いていると失敗した、というお話。

Slide 34

Slide 34 text

TypeScript でハマったところ export function doSomething(){ let numbers = [10, 5, 3, 44, 1]; for(let n of numbers.sort()){ console.log(n); } } Sort 結果は 1 -> 10 -> 3 -> 44 -> 5 となる。 これは引数無しで sort() を実行すると辞書順でソートされる、という JavaScript の 挙動がそのまま反映されるため。

Slide 35

Slide 35 text

TypeScript でハマったところ export function doSomething(){ let numbers = [10, 5, 3, 44, 1]; for(let n of numbers.sort((a, b) => a - b)){ console.log(n); } } 数値順でソートするには引数を指定する。

Slide 36

Slide 36 text

TypeScript でハマったところ 型が保持されない場合がある 特に型が入れ子構造になっている場合に、クラス間でのデータ受け渡しや JSON.parse() による変換を行うと、子の型が保持されず undefined になってしまう、 といった現象が。。。

Slide 37

Slide 37 text

TypeScript でハマったところ 。。。と思ったのですが、この資料を作成するときに確認したら再現しませんでした (^o^)\ ※TypeScript のバージョン違いや再現手順の間違いによるものかも。

Slide 38

Slide 38 text

TypeScript でハマったところ 型が保持されない問題が再現したら as Sample と明示的に子どもの型も指定した変数に格納した上で (または元のデータ取得時に型を指定して子のデータを入れ直す)使用すると、 解決していた。

Slide 39

Slide 39 text

TypeScript の好きなところ

Slide 40

Slide 40 text

TypeScript の好きなところ 強い型を持つ 少なくとも自分の書くコードでは、その変数(プロパティ)の型が何を気にしなくても、 間違っていればコンパイラが怒ってくれる。 さらに Webpack を使って import / export が可能になったことで、 1 クラス 1 ファイルに分ける、責務ごとに分割、といったことが容易に。

Slide 41

Slide 41 text

TypeScript の好きなところ 持ちうるデータの制限が容易 下記の変数は 1, 2, 3 以外を入れようとするとエラーになる。 let numbers: 1 | 2 | 3; numbers = 0; // ERROR numbers = 1; // OK

Slide 42

Slide 42 text

TypeScript の好きなところ Non-Nullable Null になり得るかどうかが指定できる(ただし undefined にはなる)。 かつ Kotlin でいう Smart cast のように扱われる。 (Nullable であっても Null チェック後は Non-Nullable として扱われる)

Slide 43

Slide 43 text

TypeScript の好きなところ Non-Nullable export class User{ public name: string = “”; // Non-Nullable public nickname: string| null = null; // Nullable } export function doSomething(){ let newUser = new User(); newUser.name = null; // ERROR let nickname = newUser.nickname.toString(); // ERROR if(newUser.nickname !== null){ let nickname2 = newUser.nickname.toString(); // OK } }

Slide 44

Slide 44 text

TypeScript の好きなところ と言いつつ柔軟性もある 例えばこんな interface を受け取る関数があるとして。 export interface Option{ option1?: string; option2?: number; } export function doSomething(option: Option){ // あれこれする. }

Slide 45

Slide 45 text

TypeScript の好きなところ と言いつつ柔軟性もある こんな風に引数を渡すことができる。 doSomething({ option1: “Hello” }); // option2 は undefined

Slide 46

Slide 46 text

参照 参照 Matering TypeScript 3 https://subscription.packtpub.com/book/application_development/9781789536706 実践 TypeScript https://book.mynavi.jp/ec/products/detail/id=104703 Interfaces - TypeScript http://www.typescriptlang.org/docs/handbook/interfaces.html

Slide 47

Slide 47 text

IE 11 に立ち向かう

Slide 48

Slide 48 text

一番辛かったところ

Slide 49

Slide 49 text

エラーがでない(場合がある)

Slide 50

Slide 50 text

IEでエラーがでない Promise を使ったコードを IE11 で実行すると、 Promise が見つからない、といった エラーが発生する。 しかし、 Array.prototype.find() を使うと、エラーが表示されず、 かつ処理がそこで止まってしまうため問題を発見しづらい。

Slide 51

Slide 51 text

解決方法 IEでエラーがでない

Slide 52

Slide 52 text

他のブラウザと組み合わせて頑張る IEでエラーがでない

Slide 53

Slide 53 text

Polyfill

Slide 54

Slide 54 text

Polyfill 先ほどの Promise 、 Array.prototype.find() が IE 対応の必要があるからといって 使えないのはツラい。 ということで Polyfill 先生の力を借りることに。

Slide 55

Slide 55 text

Polyfill  Promise: https://www.promisejs.org/  fetch: https://github.com/github/fetch  Array.prototype.find() : https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/find  Array.prototype.findIndex() : https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex  url-search-params-polyfill: https://github.com/jerrybendy/url-search-params-polyfill fetch と ur—search-params-polyfill は npm install 、他はファイルを用意して _Layout.cshtml で読み込みました。

Slide 56

Slide 56 text

Polyfill 注意点として、import 漏れがあっても IE で実行しないと気付かない、 というのがあります。 定期的に IE でも確認しましょう(白目)

Slide 57

Slide 57 text

文字化け

Slide 58

Slide 58 text

日本語データの文字化け URL のパラメータに日本語を渡すと、 IE のみ文字化けする現象が。。。 encodeURIComponent(文字列) で事なきをえました。 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent

Slide 59

Slide 59 text

PostCSS を使う

Slide 60

Slide 60 text

PostCSS を使う PostCSS は JavaScript のプラグインによって CSS をあれこれ変換してくれるツール。 具体的にはベンダープレフィックスを追加してくれる Autoprefixer など。 (というか Autoprefixer が使いたいがために導入した) https://postcss.org/

Slide 61

Slide 61 text

PostCSS を使う  PostCSS  postcss-cli  precss  autoprefixer インストールしたもの

Slide 62

Slide 62 text

PostCSS を使う 設定ファイル module.exports = { plugins: [ require("autoprefixer")({ "grid": true }), require("precss") ] } postcss.config.js というファイルを作り(多分ファイル名は何でも良さそう)、 有効にするプラグイン、 ( Autoprefixer の場合) 有効にする CSS の種類 ( CSS grid など)を指定する。

Slide 63

Slide 63 text

PostCSS を使う 設定ファイル { ~省略~ "browserslist": [ "last 2 version", "> 1%", "maintained node versions", "not dead" ], ~省略~ } 対応するブラウザバージョンは、以前 postcss.config.js に書いていたが、 現在は package.json に書くよう変更されている。

Slide 64

Slide 64 text

PostCSS を使う 課題 正直設定ファイルの書き方よくわかりません (^o^)\ (grid の場合は postcss.config.js で true にすると有効になるが、 flexbox は browserlist を指定する必要があるとか)

Slide 65

Slide 65 text

PostCSS を使う ともあれコンパイル npx postcss 変換前の PostCSSファイルパス -c postcss.config.js -d 出力先のディレクトリパス ※出力先ディレクトリパスに元のファイル名でコンパイル済みの CSS が出力される。 ※ オプションとして -w をつけると、 CSS ファイルを監視して変更のたびに自動コンパイルしてくれる。

Slide 66

Slide 66 text

PostCSS を使う package.json の script に追加する ~省略~ "scripts": { “css”: “npx postcss 変換前の PostCSSファイルパス -c postcss.config.js -d 出力先のディレクトリパス -w" } } npm run css を実行するとコンパイルを実行してくれる。 webpack も同じことができるが、両方いっぺんに監視する、というのは難しそう。

Slide 67

Slide 67 text

PostCSS の良いところ

Slide 68

Slide 68 text

PostCSS の良いところ  何といっても Autoprefixer が便利!  @import や CSS 変数などもコンパイル時に解決してくれるので、 IE でも心配せずに使える。  プラグインが豊富なので、Autoprefixer 以外もあれこれ試すと良さそう。

Slide 69

Slide 69 text

その他あれこれ その他七転八倒の様子はこの辺で。 https://mslgt.hatenablog.com/archive/category/TypeScript https://mslgt.hatenablog.com/archive/category/CSS

Slide 70

Slide 70 text

その他の課題

Slide 71

Slide 71 text

Powershell開きまくり Webpack .NET Core PostCSS Git

Slide 72

Slide 72 text

JavaScript Frameworkは使うべきか スキル問題は置いておくとして、結局 Framework を使わなかったとしても、 オレオレ Framework になってしまう。 であれば、ある程度スタンダードになっている Framework の流儀に沿って 作る方がメンテもしやすい? ただし更新速度にどう追従するかの問題はある。

Slide 73

Slide 73 text

おわりに 手探りながらもなんとか形にできたのは、公式や MDN をはじめ、 インターネット上にたくさんの知識が共有されていたから。 (特に「新しめの機能 + IE」でググるとほぼ確実にヒットするあたり、 先人の苦労を感じる) JavaScript Framework をはじめ、今後もあれこれ試しつつ自分も 情報共有していきたい。

Slide 74

Slide 74 text

License  Google Noto Fonts http://www.google.com/get/noto/ Copyright(c) Google Inc SIL Open Font License (https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL )

Slide 75

Slide 75 text

Thank you