2020/02/27

webpackとは

webpack(ウェブパック)は、複数のJSファイルをまとめてくれるツールです。
webpackは「gulp」「Grunt 」「Browserify」のようなタスクランナーですが、最大の特徴は「モジュールバンドラ」です。

モジュールバンドラーはファイルをまとめることを指し、複数のモジュール(ここではJS)の依存関係を解決します。

今回は下記を参考にて webpack4 を npm で構築してみました。

参考

最新版で学ぶwebpack 4入門 JavaScriptのモジュールバンドラ

webpack の特徴

webpackのメリットはいくつかあります。

  • 複数のJSファイルを1つのファイル(main.js や bundle.js)にまとめる
  • HTTPリクエストの数を減らす
  • 設定ファイルに基づいて開発環境を統一できる
  • 「React」「Vue.js」をはじめとしたサードパティの JavaScript と連携して開発できる
  • CSSやリソース(画像など)もバンドルできる

 

など、今まで別々で管理していたJSファイルを1つにまとめることで、フロントエンド開発手法そのものが変わってきます。

gulp で開発してきた場合は、gulp + webpack で運用してるようですが、新規ならば webpack で十分みたいです(開発者の好みか?)。

Node.js の確認

node.js のバージョンは13以上


$ node -v
v13.6.0

プロジェクト作成

webpack のテストサンプルを利用するロジェクトを作成する。
また、npm init で package.json も作成しておく。


$ mkdir webpack-test
$ cd webpack-test
$ npm init -y
$ mkdir src

webpack のインストール

devDependencies(-D) で webpack webpack-cli をインストールする


$npm i -D webpack webpack-cli
...
+ webpack-cli@3.3.11
+ webpack@4.41.6
...

JavaScript をモジュールで実装

現時点で、「モジュール方式」で JavaScript を実装することが推奨されている。
※ECMAScript Modules(ES Modules、ESM)

webpack4 では明示的に指定しない場合、以下の設定となります。

  • 「src/index.js」がエントリーポイント
  • 「dist/main.js」が出力ファイル

JavaScript ファイル記述

src/index.js


import { say } from "./module1";
say();

src/person.js


export function say() {
    alert("module1 hello!");
}

webpackビルド

手っ取り早く npm 5.2.0 で追加された「npx」コマンドで webpack ビルドしてみる。
(npm run build で webpack を動作させた方が応用が効くが) 


$ npx webpack
Hash: 58e8f21bff04a84f6d5c
Version: webpack 4.41.6
Time: 247ms
Built at: 2020/02/27 20:49:44
  Asset       Size  Chunks             Chunk Names
main.js  957 bytes       0  [emitted]  main
Entrypoint main = main.js
[0] ./src/index.js + 1 modules 96 bytes {0} [built]
    | ./src/index.js 42 bytes [built]
    | ./src/person.js 54 bytes [built]

src/index.js に src/person.js が統合され dist/main.js が書き出される

HTML実装&確認

index.html を作成し「dist/main.js」を読み込む

npm でビルド

npx webpack でなく package.json を設定して npm ビルドする

package.json の設定

  • scripts の build に「webpack」
  • devDependencies に 「webpack」「webpack-cli」のパッケージを記述

{
  "name": "webpack-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "dependencies": {
    "webpack": "^4.41.6",
    "webpack-cli": "^3.3.11"
  },
  "devDependencies": {
    "webpack": "^4.41.6",
    "webpack-cli": "^3.3.11"
  },
  "scripts": {
    "build": "webpack"
  }
}

npm ビルド

npm run build で webpack ビルドされる


$ npm run build
> webpack-test@1.0.0 build /Users/yoo/docker/projects/webpack-test
> webpack
...

webpack.config.js を設定してビルド

webpack.config.js を作成して、「entry」「output」を設定することで、エントリポイント、出力先ファイルをカスタマイズできます。

※前述の通り webpack4 では「src/index.js」「dist/main.js」がデフォルト


module.exports = {
  entry: `./src/index.js`,
  output: {
    path: `${__dirname}/dist`,
    filename: "main.js"
  },
  mode: "development"
};

$ npm run build 

modeを「development」にすると、出力ファイル(main.js)が圧縮されずに書き出されます。

ウォッチを利用するビルド

webpack-dev-server をして、JavaScriptの実装をリアルタイムにブラウザ確認することもできるが、一般的なウォッチを利用してビルドする。

package.json に watch を設定


  "scripts": {
    "build": "webpack",
    "watch": "webpack --watch"
  },

watch を起動


$ npm run watch

これで、JavaScript を保存すると自動でビルドされます。

  2020/02/14

MacBook Pro 256 で開発やクリエイティブ作業していくと容量が厳しくなってきた。

自分の場合

  • Xcode(iOSシミュレータ含む)
  • Homebrew
  • VirtualBox & Vagrant
  • Docker
  • Adobe Creative Cloud
  • DAW、音楽ライブラリ
  • 写真ライブラリ

がかなり容量を圧迫しています。

ファイルを検索

5G以上のファイル検索


$ sudo du -gxd 5 / | awk '$1 >= 5{print}'

1G以上のファイル検索(現在のディレクトリ)

$ sudo du -gxd 1| awk '$1 >= 1{print}'

これらをもとに、手動で削除

Xcode 端末シミュレータの削除

Xcodeの場合、ツールコマンドを利用する

端末リスト確認


$ xcrun simctl list devices
== Devices == 
-- iOS 13.3 
-- iPhone 8 (69D4A89A-704C-43E0-8C71-6437C551DEB6) (Shutdown) iPhone 11 (DC5B21DE-21CA-4624-8C1C-7CDC349B9DDA) (Shutdown) ... 
-- Unavailable: com.apple.CoreSimulator.SimRuntime.iOS-10-1 
-- iPhone 5 (CE4E79DC-CE71-47A9-B2C8-5F77EE73196F) (Shutdown) (unavailable, runtime profile not found) iPhone 5s (C94451DC-A342-46AE-8E69-52D6DF928E77) (Shutdown) (unavailable, runtime profile not found) 

不要端末削除


$ xcrun simctl delete unavailable

Docker

Dockerは不要なコンテナー、イメージが溜まりがち

イメージ一覧情報を表示


$ docker image ls

不要(none)の情報を表示


$ docker images -f dangling=true

不要(none)の情報を削除


$ docker image rm $(docker image ls  --filter "dangling=true" -aq)

イメージ・コンテナー・ボリュームの情報を表示


$ docker system df TYPE TOTAL ACTIVE SIZE RECLAIMABLE Images 85 0 18.97GB 18.97GB (100%) Containers 0 0 0B 0B Local Volumes 24 0 80.44MB 80.44MB (100%) Build Cache 0 0 0B 0B

停止中(exited)のイメージ・コンテナー・ボリュームを削除


$ docker system prune

全てのイメージ・コンテナー・ボリュームを削除


$ docker system prune -a

GrageBand 削除

別途DAWを入れているので、Garageband は削除


$ sudo rm -rf /Applications/GarageBand.app
$ sudo rm -rf /Library/Application\ Support/GarageBand
$ sudo rm -rf /Library/Application\ Support/Logic
$ sudo rm -rf /Library/Audio/Apple\ Loops
$ sudo rm -rf /Library/Audio/Apple\ Loops\ Index

  2020/02/08

DIについては、DI(依存性注入) を参照

DIコンテナは、DIのインスタンス生成を、別のファイルでコンテナ化して解決しようという設計パターンです。

共通クラスを用意

まず、共通で使う Animalクラスを用意します。
手っ取り早くファイル分割せず Animal.php にクラス(Dog、Cat)を記述しました。


interface Animal {
    public function bow();
}

class Dog implements Animal {
    public function bow() {
        echo 'wan! wan!'.PHP_EOL;
    }
}

class Cat implements Animal {
    public function bow() {
        echo 'nya-! nya-!'.PHP_EOL;
    }
}

DIでない例

下記のサンプルはコンストラクタ内で Dog を生成して鳴きます。


class AnimalConsole {
    protected $dog;

    public function __construct() {
        $this->dog = new Dog();
    }

    public function bow() {
        $this->dog->bow();
    }
}

$animal_console = new AnimalConsole();
$animal_console->bow();

この場合、コンストラクタで new Dog() するため、Dogが実装できるまで AnimalConsole が実装できません。

DI(?)の場合

コンストラクタの引数に、Dog、Cat インスタンスを注入します(コンストラクタインジェクション)
他の記事をみているとこれで「DI」となってますが、まだ Dog に依存しているため Cat に修正したい場合に手間がかかります。


require_once 'Animal.php';

class AnimalConsole {
    protected $dog;

    public function __construct(Dog $dog) {
        $this->dog = $dog;
    }

    public function bow() {
        $this->dog->bow();
    }
}

$animal_console = new AnimalConsole(new Dog());
$animal_console->bow();

インターフェイス(モック)を引数にしてみる

今度は Dog、Cat 両方扱えるように Amimal を引数とします。


require_once 'Animal.php';

class AnimalConsole {
    protected $animal;

    public function __construct(Amimal $animal) {
        $this->animal = $animal;
    }

    public function bow() {
        $this->animal->bow();
    }
}

$animal_console1 = new AnimalConsole(new Dog());
$animal_console1->bow();

$animal_console2 = new AnimalConsole(new Cat());
$animal_console2->bow();

これで、Dog、Cat どちらでも注入できるようになりました。

pimpleでDIコンテナを作成する

インスタンスを直接渡すのではなく、コンテナ(箱)内でインスタンスを作成して処理するのが、DIコンテナです。

今回は、composerのContainerライブラリ「pimple」を利用しています。

Pimpleインストール


$ composer require pimple/pimple ~3.0

PimpleによるDIコンテナ

下記の場合、Dog、Cat のインスタンスをコンテナ化しています。

また、$container['animal'] では、インスタンスを簡単に切り替えることができます。


require_once 'Animal.php';
require_once __DIR__.'/../vendor/autoload.php';

use Pimple\Container;

class AnimalConsole {
    protected $animal;

    public function __construct(
        Animal $animal
        ) {
        $this->animal = $animal;
    }

    public function bow() {
        $this->animal->bow();
    }
}

$container = new Container();

$container['dog'] = function($c) {
    return new Dog();
};

$container['cat'] = function($c) {
    return new Cat();
};

$container['animal'] = function($c) {
    return $c['dog'];
};

$container['animalConsole'] = function ($c) {
    return new AnimalConsole($c['animal']);
};

$container['animalConsole']->bow();

Container の部分はファイル分離する必要はあります。

  2020/02/06

Freee SDK

ありそうでなかった会計向けSDK
freee が国内初なようで、2020/02時点の対応言語は「C#」「Java」「PHP」

freee API と統制をとるために「OpenApi generator」を利用して有志が開発しているとのこと

C#

https://github.com/freee/freee-accounting-sdk-csharp/

Java

https://github.com/freee/freee-accounting-sdk-java

PHP

https://github.com/freee/freee-accounting-sdk-php/

PHPの場合は、composer で用意されており、さらにサンプル用に Docker & Laravel が公開されている。

サンプルの動作例

freee API

freee API

Docker & Laravel でサンプルを動かす

コールバックURL

freee APIアプリの「コールバックURL」は以下を設定しておく
※デフォルト:urn:ietf:wg:oauth:2.0:oob
※Laravel dでも後に設定する


http://localhost:8000/auth-callback

サンプルダウンロード & 設定

サンプルは SDK の中に入っているので git clone


$ git clone https://github.com/freee/freee-accounting-sdk-php.git

.env を設定する


$ cd freee-accounting-sdk-php.git
$ cd samples/BasicWebApp
$ cp .env.example .env

freeeアプリ の Client ID、Secret ID を記述


FREEE_ACCOUNTING_CLIENT_ID=Client ID
FREEE_ACCOUNTING_CLIENT_SECRET=Secret ID

Dockerの起動

freee-accounting-sdk-php にあるサンプルを利用する

$ cd freee-accounting-sdk-php/samples/BasicWebApp
$ cd samples
$ docker-compose build
$ docker-compose up -d
$ docker exec -it samples_webapp_1 /bin/bash

docker-compose.yaml


version: "3.7"
services:
  console:
    build:
      context: .
      dockerfile: Dockerfile
    image: freee-accounting-sdk-php-console
    volumes:
      - "./BasicConsole:/usr/src/app"
    command: /bin/sh -c "while sleep 1000; do :; done"
  webapp:
    build:
      context: .
      dockerfile: Dockerfile
    image: freee-accounting-sdk-php-webapp
    ports:
      - "80:80"
      - "8000:8000"
    volumes:
      - "./BasicWebApp:/usr/src/app"
    command: /bin/sh -c "while sleep 1000; do :; done"

Dockerfile


FROM php:7.3-cli
RUN apt-get update; \
    curl -sL https://deb.nodesource.com/setup_12.x | bash -; \
    apt-get install -y --no-install-recommends \
        git \
        libzip-dev \
        nodejs \
        unzip \
        zlib1g-dev \
    ; \
    rm -rf /var/lib/apt/lists/*

RUN docker-php-ext-install zip
WORKDIR /tmp
RUN curl https://raw.githubusercontent.com/composer/getcomposer.org/76a7060ccb93902cd7576b67264ad91c8a2700e2/web/installer -o - -s | php -- --quiet; \
    mv composer.phar /usr/local/bin/composer
WORKDIR /usr/src/app
RUN composer global require laravel/installer
ENV PATH /root/.composer/vendor/bin:$PATH
EXPOSE 8000

Composer インストール

webpackが用意されているので、すぐインストールできる


# composer install

composer、Laravel を直にインストールする場合


$ composer require freee/freee-accounting-sdk
$ composer require socialiteproviders/generators
$ composer require socialiteproviders/manager

artisan で socialiteproviders/generators を実行


$ php artisan make:socialite FreeeAccounting --spec=oauth2 --authorize_url=https://accounts.secure.freee.co.jp/public_api/authorize --access_token_url=https://accounts.secure.freee.co.jp/public_api/token --user_details_url=https://api.freee.co.jp/api/1/users/me
$ composer dumpautoload

Laravel/UI を作成


$ composer require laravel/ui --dev
$ php artisan ui vue --auth
$ npm install && npm run dev

Laravel artisanサーバ起動


# php artisan key:generate
# php artisan serve

Docker の場合は、ホスト指定します。


# php artisan serve --host 0.0.0.0

プロジェクトルートは「samples/BasicWebApp/」

認証処理

routes/web.php


Auth::routes([
    'register' => false,
    'reset' => false,
]);

Route::get('login', 'Auth\LoginController@redirectToProvider')->name('login');
Route::get('auth-callback', 'Auth\LoginController@handleProviderCallback')->name('authCallback');

config/service.php

「client_id」「client_secret」「redirect」をそれぞれ設定 (リダイレクトURLは、freeeのアプリ管理と合わせる)


 'freeeaccounting' => [
        'client_id' => env('FREEE_ACCOUNTING_CLIENT_ID'),
        'client_secret' => env('FREEE_ACCOUNTING_CLIENT_SECRET'),
        'redirect' => 'http://localhost:8000/auth-callback',
    ],

config/auth.php

freee用ドライバー、プロバイダー設定

    'defaults' => [
        'guard' => 'freee',
        'passwords' => 'users',
    ],
....
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'api' => [
            'driver' => 'token',
            'provider' => 'users',
            'hash' => false,
        ],
        'freee' => [
            'driver' => 'freee',
            'provider' => 'freee',
        ],
    ],
...
    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],
        'freee' => [
            'driver' => 'freee',
        ],
    ],

app\Http\Auth\LoginController.php

ログイン処理は、Laravel Socialite ドライバーを利用し、GenericUser で認証する


use App\Http\Controllers\Controller;
use Illuminate\Auth\GenericUser;
use Illuminate\Support\Facades\Auth;
use Socialite;

...

    public function redirectToProvider()
    {
        return Socialite::driver('freeeaccounting')->redirect();
    }

    public function handleProviderCallback()
    {
        $user = Socialite::driver('freeeaccounting')->user();

        $genericUser = $user->getRaw();
        $genericUser['token'] = $user->token;
        $genericUser['remember_token'] = '';
        Auth::login(new GenericUser($genericUser));

        return redirect()->intended($this->redirectTo);
    }

    public function logout()
    {
        Auth::logout();
        return redirect()->intended('/');
    }

認証用サービスプロバイダー

app/Providers/AuthServiceProvider.php


namespace App\Providers;

use App\Extensions\SampleSessionGuard;
use App\Extensions\FreeeUserProvider;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Auth;

class AuthServiceProvider extends ServiceProvider
{
  protected $policies = [
    // 'App\Model' => 'App\Policies\ModelPolicy',
  ];
  public function boot()
  {
    $this->registerPolicies();

    Auth::extend('freee', function ($app, $name, array $config) {
      return new SampleSessionGuard(
        $name,
        Auth::createUserProvider($config['provider']),
        $app['session.store']
      );
    });

    Auth::provider('freee', function ($app, array $config) {
      return new FreeeUserProvider();
    });
  }
}

イベントサービスプロバイダー

app/Providers/EventServiceProvider.php


namespace App\Providers;

use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
use SocialiteProviders\Manager\SocialiteWasCalled;
use SocialiteProviders\FreeeAccounting\FreeeAccountingExtendSocialite;

class EventServiceProvider extends ServiceProvider
{
    protected $listen = [
        Registered::class => [
            SendEmailVerificationNotification::class,
        ],
        SocialiteWasCalled::class => [
            FreeeAccountingExtendSocialite::class,
        ],
    ];

    public function boot()
    {
        parent::boot();
    }
}

SocialiteProviders設定

SocialiteProviders/src/FreeeAccounting/Provider.php

https://api.freee.co.jp/api/1/users/me からユーザを返す関数を作成


    protected function getUserByToken($token)
    {
        $response = $this->getHttpClient()->get('https://api.freee.co.jp/api/1/users/me', [
            'headers' => [
                'Authorization' => 'Bearer '.$token,
            ],
        ]);

        $body = json_decode($response->getBody(), true);
        return $body['user'];
    }

User のマッピング


    protected function mapUserToObject(array $user)
    {
        $user['name'] = $user['last_name'] . ' ' . $user['first_name'];
        return (new User())->setRaw($user)->map([
            'id'       => $user['id'],
            'name'     => $user['name'],
            'email'    => $user['email'],
            'display_name' => $user['display_name'],
            'first_name' => $user['first_name'],
            'last_name' => $user['last_name'],
            'first_name_kana' => $user['first_name_kana'],
            'last_name_kana' => $user['last_name_kana'],
        ]);
    }

事業所と取引(収入/支出)一覧の取得

app/Http/AccountController.php

ログイン認証したユーザトークンを、Configuration クラスに設定


$user = Auth::user();
$config = Configuration::getDefaultConfiguration()->setAccessToken($user->token);

ちなみに、getAccessToken() でアクセストークンを確認できる。


$config->getAccessToken()

CompaniesApi で事業所IDを取得


$companiesApiInstance = new CompaniesApi(null, $config);
$companiesResponse = $companiesApiInstance->getCompanies();
$targetCompanyId = $companiesResponse->getCompanies()[0]->getId();

DealsApi で取引(収入/支出)一覧の取得


$limit = 5;
$dealsApiInstance = new DealsApi(null, $config);
$dealsResponse = $dealsApiInstance->getDeals(
            $targetCompanyId,
            null, null, null, null, null, null, null, null, null, null, null, null,
            $limit);
$deals = $dealsResponse->getDeals();

getDeals() の引数がちょっとどうなんだろ?

  2020/02/06

freee API は 開発者向けにOSS として公式公開されています。

https://developer.freee.co.jp/

 

ここでは、リファレンスを利用して認可コード・アクセストークン・API確認をしてみる。

実際の開発は各言語やSDKを使ってコーディングが必要だが、PHPに関しては、freee SDKを Laravel で使ってみる でやってみた。

開発者アカウント登録と環境・アプリ作成

まず、freeeアカウントを作成(一般ユーザアカウント)する

開発用テスト環境作成

次に開発ユーザでログインし、開発用テスト環境の作成する。

テスト環境の事業所を選択

アプリ追加

 アプリ追加画面でアプリを追加すると、Client ID, Client secret が発行される

作成したアプリは、アプリ管理 で管理する

freee API のドキュメント

API を試してみる

認可コード発行

「Webアプリ認証用URL」でブラウザでアクセスし、許可すると「認可コード」が発行される
※アクセストークンではない

アクセストークン発行

https://accounts.secure.freee.co.jp/public_api/authorize?client_id={client_id}&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&response_type=token 

上記のURLに freee アプリで発行された Client ID を入れてブラウザでリクエストする

事業所取得

https://developer.freee.co.jp/docs/accounting/reference#/Companies/get_companies

鍵マークをクリック

value に アクセストークンを入力して [Authorize]し、成功したら[Close]

[Try it out] をクリックし [Execute] するとAPIが実行される

事業所一覧取得API(companies)の場合

curl


curl -X GET "https://api.freee.co.jp/api/1/companies" -H "accept: application/json" -H "Authorization: Bearer {Client ID}"

Request Body


https://api.freee.co.jp/api/1/companies

Request URI


{
  "companies": [
    {
      "id": xxxxxxx,
      "name": "",
      "name_kana": "",
      "display_name": "個人事業主名",
      "role": "admin"
    },
    {
      "id": xxxxxxx,
      "name": null,
      "name_kana": null,
      "display_name": "個人事業主スタータープラン: 開発用テスト環境",
      "role": "admin"
    }
  ]
}

  2020/02/01

Segue を利用せずに Storyboard の Storyboard ID を利用して present で画面遷移させる。 遷移先の UIViewController を明示的にクラス名を指定すると値を渡すことも可能

画面遷移

  • 遷移元:ViewController
  • 遷移先:PageViewController
  • Storyboard ID:page

let storyboard: UIStoryboard = self.storyboard!
let page = storyboard.instantiateViewController(identifier: "page") as! PageViewController
page.customValue = customValue
page.modalPresentationStyle = .fullScreen
page.modalTransitionStyle = .crossDissolve
self.present(page, animated: true, completion: nil)
  1. Storyboard から instantiateViewController() で PageViewController を生成
  2. 値を受け渡し
  3. 画面遷移先の画面スタイル、アニメーションを設定

.modalPresentationStyle、.modalTransitionStyle プロパティは、iOSバージョンによって異なる

.modalTransitionStyle


public enum UIModalTransitionStyle : Int {
    case coverVertical
    case flipHorizontal
    case crossDissolve
    @available(iOS 3.2, *)
    case partialCurl
}

.modalPresentationStyle


public enum UIModalPresentationStyle : Int {
    case fullScreen
    @available(iOS 3.2, *)
    case pageSheet
    @available(iOS 3.2, *)
    case formSheet
    @available(iOS 3.2, *)
    case currentContext
    @available(iOS 7.0, *)
    case custom
    @available(iOS 8.0, *)
    case overFullScreen
    @available(iOS 8.0, *)
    case overCurrentContext
    @available(iOS 8.0, *)
    case popover
    @available(iOS 7.0, *)
    case none
    @available(iOS 13.0, *)
    case automatic
}

  2020/01/31

Xcode で vim を利用するには「XVim2」をプラグインをインストールすると良い。
(11.3 で動作確認)

Github から XVim2をダウンロード

XVimProject/XVim2 にあるソースをダウンロード


$ https://github.com/XVimProject/XVim2.git

コード署名

SIGNING_Xcode.md を参照

  1. アプリケーション > ユーティリティ > キーチェンアクセスを開く
  2. 証明書アシスタント > 証明書を作成... を選択
  3. 名前:「XcodeSigner」を入力、証明書のタイプ:「コード証明書」を選択して作成
     

Xcodeに署名する

 $ sudo codesign -f -s XcodeSigner /Applications/Xcode.app

プラグインフォルダの確認


$ xcode-select -p
/Applications/Xcode.app/Contents/Developer

※選択されていない場合は、「xcode-select -s」で選択する

Xvim2ビルド


$ cd XVim2
$ make

Xcodeプラグインをアップデート

update_xcode_plugins インストール

update_xcode_plugins コマンドを gem でインストール


$ sudo gem install update_xcode_plugins
Password:
Fetching: sync-0.5.0.gem (100%)
Successfully installed sync-0.5.0
...

update_xcode_plugins 実行


$ update_xcode_plugins
Found:
- Xcode (11.3.1) [BAB79788-ACEE-4291-826B-EC4667A6BEC5]: 
...

$ update_xcode_plugins --unsign
Looking for Xcode...

Unsigning Xcode will make it skip library validation allowing it to load plugins.
However, an unsigned Xcode presents security risks, and will be untrusted by both Apple and your system.
This tool will create a backup and allow you to restore Xcode's signature by running

$ update_xcode_plugins --restore

Choose which Xcode you would like to unsign (use arrows): Xcode (11.3.1) [Signed]: /Applications/Xcode.app
Unsign xcodebuild too?: Yes
...

 

XCodeを起動する

  1. 起動済みの場合、終了させて再度起動
  2. 再起動後ポップアップが表示されたら「Load bundle」を選択

メニューバー >「Edit」>「XVim」が表示される

  2020/01/30

Codable を利用して、JSONを 構造体の配列で扱ってみる

構造体を定義

JSONのデータにあわせて、Codable クラスの構造体を定義する。


struct HiraganaEntry: Codable {
    var word:String
    var kana:String
    var length:Int
}

Entityを定義

カスタムクラスのEntity の配列を定義する


var hiraganaEnties: [HiraganaEntry] = []

JSONファイルのパスを設定する

Bundle.main.path() でプロジェクト内の JSON ファイルのパスを作成する。

  • forResource: ファイル名
  • ofType: 拡張子

guard let path = Bundle.main.path(forResource: name, ofType: "json") else { return nil }

JSONを読み込む

ファイルパスから UTF-8 で String型で読み込む


let json:String
json = try String(contentsOfFile: path, encoding: .utf8)

JSONデコード

JSON(String)を、定義したEntity の配列でデコードする


let entries = try! jsonDecoder.decode([HiraganaEntry].self, from: (json.data(using: .utf8)!))

全体のコード


    let jsonDecoder = JSONDecoder()
    var hiraganaEnties: [HiraganaEntry] = []
    
    struct HiraganaEntry: Codable {
        var word:String
        var kana:String
        var length:Int
    }

    func getJSON(name:String) -> Codable? {
        let json:String
        guard let path = Bundle.main.path(forResource: name, ofType: "json") else { return nil }
        do {
            json = try String(contentsOfFile: path, encoding: .utf8)
        } catch _ {
            return nil
        }
        let entries = try! jsonDecoder.decode([HiraganaEntry].self, from: (json.data(using: .utf8)!))
        return entries
    }
    
    func loadHiragana() {
        hiraganaEnties = getJSON(name: "file_name") as! [GameViewController.HiraganaEntry]
        print(hiraganaEnties.randomElement())
    }

  2020/01/24

webpack の環境を構築してみる
参考:webpack 4 入門 webpackの最大の特徴は「モジュールバンドラ」を利用して、複数のjsファイルを1つのファイル「bundle.js」にまとめる。

構成


├── node_modules
├── package.json
├── public
│   ├── index.html
│   └── js
│       └── bundle.js
├── src
│   └── js
│       ├── app.js
│       └── modules
│           ├── add-calculator.js
│           └── tax-calculator.js
└── webpack.config.js

上記の場合「app.js」「add-calculator.js」「tax-calculator.js」をビルドして「bundle.js」にまとめます。
※NodeJS, npm, yarn などは解説省略

package.json 作成


$ yarn init  --yes
yarn init v1.21.1
warning The yes flag has been set. This will automatically answer yes to all questions, which may have security implications.
success Saved package.json
✨  Done in 0.04s.

webpackインストール


$ yarn add webpack webpack-cli webpack-dev-server --dev

package.json の内容


var path = require('path');

module.exports = {
  entry: "./src/js/app.js",
  output: {
    path: path.join(__dirname, 'public/js'),
    filename: 'bundle.js',
  },
  resolve: {
    extensions: ['.js', '.ts', '.svg']
  },
  module: {
    rules: [{
      test: /\.js$/,
      use: [{
        loader: 'babel-loader',
        options: {
          presets: ['es2015']
        }
      }],
    }, {
      test: /\.ts$/,
      use: [{
        loader: 'ts-loader',
        options: {
          compilerOptions: {
            declaration: false,
            target: 'es5',
            module: 'commonjs'
          },
          transpileOnly: true
        }
      }]
    }, {
      test: /\.svg$/,
      use: [{
        loader: 'html-loader',
        options: {
          minimize: true
        }
      }]
    }]
  }
}

entry & output

entry:コンパイルするメインJSファイルパス(エントリーポイント)

output:出力するメインJSファイルのパス 最初に require した path を利用して最終的に「public」ディレクトリに「bundle.js」を書き出す

resolve.extensions

require , importするファイル拡張子を省略設定

module:babel-loader

ビルドする際、利用するモジュールを設定 babel-loader: Bableに対応する

Babel

次世代 EcmaScript で書かれたJSを、サポートしていないブラウザでも動くJSに変換

module:ts-loader

ts-loader:TypeSceiptに対応する

yarnでインストール


$ yarn install
yarn install v1.21.1
[1/4] 🔍  Resolving packages...
success Already up-to-date.
✨  Done in 0.12s.

jsファイルの作成


$ mkdir src

modules/add-calculator.js


export default function addCalculator(number1 ,number2) {
    return number1 + number2;
}

app.js


import addCalculator from './modules/add-calculator';
import taxCalculator from './modules/tax-calculator';

var item1_price = 100;
var item2_price = 300;
var total_price = addCalculator(item1_price, item2_price);
var tax = 0.1;
var tax_price = taxCalculator(total_price, tax);

window.onload = function() {
    document.getElementById('calculate-result').innerHTML = tax_price;
};

modules/tax-calculator.js


export default function taxCalculator(price ,tax) {
    return Math.round(price * (1 + tax));
}

webpackでビルド


$ yarn run webpack

webpack コマンドを実行する

node_modules のパスをbash に登録することで、webpack コマンドを直接利用できる

.bash_profile を開く


$ vi ~/.bash_profile

.bash_profile に追記


export PATH=$PATH:./node_modules/.bin

.bash_profile を再読み込み


$ source ~/.bash_profile

  2020/01/21

Laradock の接続は psql のバージョンが 12 だとプロトコルエラーとなった。


$ psql -h localhost -U default -l
psql: error: could not connect to server: FATAL:  unsupported frontend protocol 1234.5679: server supports 2.0 to 3.0

Macにインストールした psql のバージョンを変更する。

psql のパスを確認

$ which psql
/usr/local/opt/libpq/bin/psql

Homebrew で任意のPostgreSQLをインストール

$brew search postgresql
...
$ brew install postgresql@11

エイリアスを追加

$ alias psql='/usr/local/opt/postgresql@11/bin/psql'
pngファイルの軽量化
Google DriveのIconを再起的に削除
php-markdownでバニラPHPなコードブロック処理
laravel-ffmpeg を使う
2021年版 Ubuntu + certbot + Let's Encrypt でサーバ証明書設定
GihHub のデフォルトでない master ブランチを checkout する
マルチログインで未認証のリダイレクト
Homebrew で Redis をインストール
CSS だけでスムーズスクロール
EC-CUBE4 で Gmail の smtp を利用する
Amazon Linux 2 の amazon-linux-extras とは
UNIQUE カラムのバリデーションで自分自身を除外して更新
フォーム有効期限切れで Page Expired をリダイレクト
ログを日付でローテーションやクリアや削除
Homebrew で PHP8.0 から PHP7.4 にダウングレード
Big sur で zsh 移行と Homebrew アップグレード
Mac に minikube をインストール
途中から .gitignore に追加する
Larevel 6.x から Laravel 8.x にバージョンアップ
Composer で Allowed memory size (メモリ不足)エラー
Blade でカスタムクラスを利用する
git push git pull にブランチ指定せずに実行する
git pull や git push できなくなったとき
Docker のコンテナからホストOS に接続
Mac で ローカル IP アドレス(ipv4)のみを表示する
ホストOS から Docker の MySQLコンテナに接続
caching_sha2_password のエラー
node-config で環境設定ファイルを利用する
rootパスワードを初期化(再設定)する
Git から clone したときのエラー対処
Mac に MySQL をインストール
Mac に PostgreSQL をインストール
Laravel 環境構築 - Mac ネイティブ編
Firebase 入門 - Firebase とは
Firebase 入門 - CLI インストールとデータベースの設定
AWS 無料枠(t2.micro)で容量とメモリエラー
Cloud9 を起動する -初心者編-
gcloud で GCEインスタンスを起動してみる
AWS CLI と jq でインスタンス一覧を整形して表示
React と Laravel7 のプロジェクトを作成する
Homebrewインストール-2020年版
3直線で囲まれた範囲塗りつぶし
PuLP で線形最適化問題を解く
カスタムのペジネーションを作る
node-sass を使って sass をコンパイルする
Log ファサードでSQLログを分離して書き出す
いちから始める Docker - 複数のコンテナを使う - (2020年)
いちから始める Docker - docker-compose を使う - (2020年)
AWS ECR を使ってみる
Laravel7 でマルチ認証