DIVでBlurっぽいことをやる(React)
DIVでもInput要素のblur的なことがしたい!
InputElementは別のところを触るとBlurイベントを発火してフォーカスが外れます.
MDNのサイトで動作は確認できるかと思います.
これをDIV Elementでもやりたいなぁと言うのが今回の議題です.
今回はBlur的なことをしたくなったSelectorUIを用意しました.https://naporin0624.github.io/napoblog-assets/#/div-blur
ようなUIを考えます.
方針
セレクターUIはdivの中に存在するようになっていて,次のようなDOM構成になっています.
- ContainerDIV
- ButtonDIV
- MenuDIV
- OptionGroupDIV
- OptionDIV
- OptionDIV
- ...
- OptionGroupDIV
ButtonDIVもOptionGroupDIVもOptionDIV触っても親の要素は常にContainerDIVになるので
こちらのclosest
メソッドを使ってクリックされた要素の親にContainerがあるかどうかでフォーカスがはずれたかどうかを検知するようにしていきます!関係ないところをクリックしてもその親にはContainerはいないのでフォーカスは外れる仕組みです!
実装
こんな感じでできるかと思います!InputElementが自分でblurイベントを発火してくれるところを自分でclosestメソッドを使ってblurイベント相当のものを生成しています.
function Selector() { // closestにSelectorをわたすためにContainerのrefをとります const ref = useRef<HTMLDivElement>(null); useEffect(() => { const handler = (e: Event) => { // Blurを制御したい親Elementのselector(クラス)refからを作る const selector = ref.current?.className .split(" ") .map(s => `.${s}`) .join(); // eはクリックしたところから発火されるイベント // eをclosestで比較し,eの親にrefが含まれるか確認する const blur = !(e.target as HTMLElement).closest(selector || ""); // 親にrefが含まれていなければフォーカスを外す if (blur) setIsFocus(false); }; document.addEventListener("click", handler); return () => document.addEventListener("click", handler); }, []); return ( <Container ref={ref}> <Button></Button> <Menu> <OptionGroup> <Option>hoge</Option> <Option>huga</Option> <Option>nyan</Option> </OptionGroup> </Menu> </Container> ) }
ここなんですが
const selector = ref.current?.className .split(" ") .map(s => `.${s}`) .join();
const selector = [...ref.current.classList].map(s => `.${s}`).join()
みたいなことができたんですけど,TSだと怒られましたw
最後に
今回使ったプログラムはここに置いてあります!必要であれば使ってください. github.com
自作のUI(DIVで作ったやつ)でフォーカス制御してみたいなことがあって困っていろいろ模索した結果こんな感じの解にたどり着きました.MDNじろじろ見る癖が少しづつついてきたかなぁって感想と,CSS筋が前よりついてきた気がします.
もっとこうしたらいいよとかあれば@naporin24690に教えてください〜!
LottieWebでチェックボックスの状態を管理する
Lottieで消えちゃうCheckBox作るぞ!
こういうのを作りたい
https://naporin0624.github.io/napoblog-assets/#/
今回はこちらのチェックボックスアニメーションを使わせていただきました.
コードの全体像
Lottieのマウントにはreact-lottieを使っています.animを直で触りたいのでそこの部分だけ型定義を拡張して使っている感じですね.
index.tsx
import React, { useRef, useEffect } from "react"; import Lottie from "react-lottie"; import checkbox from "./checkbox.json"; import { AnimationItem } from "lottie-web"; interface LottieType extends Lottie { anim: AnimationItem; } interface Props { checked: boolean; } const options = { loop: false, autoplay: false, animationData: checkbox, rendererSettings: { preserveAspectRatio: "xMidYMid slice", }, }; export const CheckBox = (props: Props) => { const { checked } = props; const ref = useRef<LottieType>(null); const prev = useRef<boolean>(); useEffect(() => { // 初回マウントときはレンダリングしない // falseでは行ってきたときにgoToAndPlayされるのを防ぐため if (prev.current === undefined) { prev.current = checked; // 初回マウント かつ チェックボックスが選択されているならフレームの最後からアニメーションを実行する checked && ref.current?.anim.goToAndPlay(ref.current?.anim.getDuration(true), true); return; } if (checked) { ref.current?.anim.goToAndPlay(0, true); } else { ref.current?.anim.setDirection(-1); ref.current?.anim.goToAndPlay(15, true); } }, [checked]); return <Lottie ref={ref} options={options} width={300} />; };
最後に
lottie-webにはここでフレームを止めるみたいなことができないぽいのでこのような措置を取りました.もっといい方法があれば教えてください🙇♂️
初めはこの子
で実装していてチェックされてから消えるまでセットのアニメーションだったために以下のようにしていたのですが
useEffect(() => { ref.current?.anim.playSegments([30, 75], true); ref.current?.anim.stop(); }, []);
なぜかこうなる・・・・・・
消すとうまくいくので明らかにplaySegmentが悪いのはわかっているんですけど,どう直したらいいのかわからなかったので上で紹介したアニメーションを使いました
有識者教えてください!!!!
わかっていること
- destroyの前に動き始めている
- useEffectのreturnにconsole.logをしこませて検証
- playSegmentの上にconsole.logをおいても初期レンダリング以外では反応なし
ぐらいです・・・・・・
react-transition-groupでリストを表示するときはkeyにindexを設定するのはやめよう
リストで表示したものにトランジションを適用したい
こんなやつをやりたかった
なんかこうなる
🤔
コードを比較
styles.ts
については一番下に書いておきます.
変な挙動をするコード
import React, { Fragment, useState, useCallback, useMemo } from "react"; import { Container, AnimationBox, FormContainer, Input, Submit } from "./styled"; export const ListTransition = () => { const [state, setState] = useState<string[]>(["hoge", "huga"]); const [value, setValue] = useState<string>(""); const onAdd = useCallback(() => { if (value.length <= 0) return; setState(ls => [...ls, value]); setValue(""); }, [value]); const onRemove = useCallback((s: string) => setState(l => l.filter(el => el !== s)), []); const disabled = useMemo(() => value.length <= 0, [value]); return ( <Fragment> <Container> {state.map((s, idx) => ( <AnimationBox key={idx} unmountOnExit timeout={800} onClick={() => onRemove(s)}> {s} </AnimationBox> ))} </Container> <FormContainer> <Input value={value} onChange={e => setValue(e.target.value)} /> <Submit onClick={onAdd} disabled={disabled}> Add Item </Submit> </FormContainer> </Fragment> ); };
想定している動きをするコード
import React, { Fragment, useState, useCallback, useMemo } from "react"; import { Container, AnimationBox, FormContainer, Input, Submit } from "./styled"; export const ListTransition = () => { const [state, setState] = useState<string[]>(["hoge", "huga"]); const [value, setValue] = useState<string>(""); const onAdd = useCallback(() => { if (value.length <= 0) return; setState(ls => [...ls, value]); setValue(""); }, [value]); const onRemove = useCallback((s: string) => setState(l => l.filter(el => el !== s)), []); const disabled = useMemo(() => value.length <= 0, [value]); return ( <Fragment> <Container> {state.map(s => ( <AnimationBox key={s} unmountOnExit timeout={800} onClick={() => onRemove(s)}> {s} </AnimationBox> ))} </Container> <FormContainer> <Input value={value} onChange={e => setValue(e.target.value)} /> <Submit onClick={onAdd} disabled={disabled}> Add Item </Submit> </FormContainer> </Fragment> ); };
原因
keyをindexにしていたからでした.keyが変わるので最後のコンポーネントが消えたと認識されてしまってトランジションが最後のコンポーネントにしか効かなかったというオチでした.
styles.ts
import styled from "styled-components"; import { TransitionGroup } from "react-transition-group"; import transition from "styled-transition-group"; export const Container = styled(TransitionGroup)` position: absolute; top: 0px; display: flex; width: 300px; overflow-x: scroll; margin: 12px; `; export const AnimationBox = transition.p` padding: 8px 16px; font-size: 13px; border: solid 1px #c1c1c1; margin: 0 8px; border-radius: 3px; background-color: #c1c1c1; color: white; cursor: pointer; &:enter { opacity: 0; } &:enter-active { opacity: 1; transition: all 0.8s ease-out; } &:exit { opacity: 1; } &:exit-active { opacity: 0; transition: all 0.8s ease-out; } `; export const FormContainer = styled.div` display: flex; margin-top: 56px; `; export const Input = styled.input``; export const Submit = styled.button``;
【NestJSアドベントカレンダー】NestJSとwebpack-dev-middlewareを組み合わせる【23日目】【遅刻】
NestJSにwebpack-dev-middlewareを組み込む
2020-04-09追記
ライブラリとして公開しました
遅刻しました.今日は25日.クリスマスです.名取の配信見てたら24日もいつのまにか終わっていました. 23日目は研究室の実験があり,徹夜でNestJSを書いていたので実質NestJSアドベントカレンダー書いたようなものじゃないですか?許してください・・・・・・・
本日のリポジトリ
webpack-dev-middlewareって何?
こいつです.こいつは開発時のみ使える良きもの.webpack-dev-serverだと内部のexpressが使われてしまいまサーバーがフロントエンド用と,バックエンド用の2つできてしまいますが,こいつを使えば自分のサーバの上でwebpack-dev-server的なことができてしまうわけです.よいですね.
Usageを見てみましょう
const webpack = require('webpack'); const middleware = require('webpack-dev-middleware'); const compiler = webpack({ // webpack options }); const express = require('express'); const app = express(); app.use( middleware(compiler, { // webpack-dev-middleware options }) ); app.listen(3000, () => console.log('Example app listening on port 3000!'));
シンプルですね.これをNestJSに組み込んでいきます.
NestJS & webpack-dev-middleware
僕 <「webpack-dev-middlewareを使う.」,「本番でもそのまま動くようにする.」両方やらなくちゃいけないのが〇〇の辛いところだな.*〇〇にしたのは思いつかなかったため
webpack-dev-middlewareを使うmoduleを作る
client.module.tsみたいな名前でやりましょう.名前をつけるのが下手なのは目を瞑ってください
nest g mo client
import { Module, DynamicModule, OnModuleInit, Inject } from '@nestjs/common'; import { HttpAdapterHost } from '@nestjs/core'; import { CLIENT_MODULE_OPTIONS } from './client-options.constant'; import { ClientOptions } from './client-options.interface'; import { ClientProvider } from './client.provider'; @Module({ providers: [ClientProvider], }) export class ClientModule implements OnModuleInit { constructor( @Inject(CLIENT_MODULE_OPTIONS) private readonly clientOptions: ClientOptions, private readonly httpAdapterHost: HttpAdapterHost, private readonly clientProvider: ClientProvider, ) {} static forRoot(options: ClientOptions): DynamicModule { return { module: ClientModule, providers: [ { provide: CLIENT_MODULE_OPTIONS, useValue: options, }, ], }; } public async onModuleInit() { if (process.env.NODE_ENV !== 'development') return; const httpAdapter = this.httpAdapterHost.httpAdapter; const { webpackConfig } = this.clientOptions; this.clientProvider.register(httpAdapter, webpackConfig); } }
moduleではforRootを使ってDynamicModuleを返すようにします.MongooseModuleとかTypeOrmModuleとかと同じですね.
@Inject(CLIENT_MODULE_OPTIONS) private readonly clientOptions: ClientOptions
これ頭いいなぁって思ったんですけど,forRootで返したproviderから拾ってきています.forRootはstaticmethodなのでonModuleInitに対して変数を渡すことはできないのですがこれで実現しています.
こんなことは自分では考え付かない・・・後述するServeStaticModule
の内部実装がこうなっていたのを真似しました.
続いてProviderを作っていきます. Providerではwebpackのコンフィグをwebpack-dev-middlewareに食わせて,httpAdapter.つまり,NestJSの本体に登録していきます.
import { Injectable } from '@nestjs/common'; import { Configuration, Entry, EntryFunc } from 'webpack'; import webpack from 'webpack'; import { AbstractHttpAdapter } from '@nestjs/core'; import webpackDevMiddleware from 'webpack-dev-middleware'; import webpackHotMiddleware from 'webpack-hot-middleware'; @Injectable() export class ClientProvider { async register(app: AbstractHttpAdapter, config: Configuration) { const compiler = webpack({ ...config, mode: 'development', entry: await this.appendHotMiddlewareToEntry(config.entry), plugins: [...config.plugins, new webpack.HotModuleReplacementPlugin()], }); app.use(webpackDevMiddleware(compiler)); app.use(webpackHotMiddleware(compiler)); } private async appendHotMiddlewareToEntry( entry: string | string[] | Entry | EntryFunc, ) { const hot: string = 'webpack-hot-middleware/client?reload=true&timeout=1000'; let e = entry; e = e instanceof Function ? await e() : e; if (e instanceof Array) return [...(e as string[]), hot]; else if (typeof e === 'string') return [e, hot]; else { for (const key in e) { if (e[key] instanceof Array) e[key] = [...e[key], hot]; else e[key] = [e[key], hot] as string[]; } return e; } } }
どうせならHMRも登録してしまえ!ということでやっています.appendHotHiddlewareToEntry
ではwebpackのentry全てにhot-middlewareを付け加えています.なんかヤバそうな気がする・・・・
ここでやるのはwebpack-dev-middleware周りの設定だけにしています. 特に説明すべきことはないと思いますので次に行きます.
configの型を決めましょう.
configだけくれればそれでええ!
import { Configuration } from 'webpack'; export interface ClientOptions { webpackConfig: Configuration; }
export const CLIENT_MODULE_OPTIONS = 'CLIENT_MODULE_OPTIONS';
moduleを登録する
import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { ClientModule } from './client/client.module'; import config from '@/webpack.config.client.js'; import { Configuration } from 'webpack'; @Module({ imports: [ ClientModule.forRoot({ webpackConfig: config as Configuration, }), ], controllers: [AppController], providers: [AppService], }) export class AppModule {}
実行する
やることリスト
- [ ] webpack.config.jsを書く
- [ ] フロントエンドのコードをcliet/App.tsxみたいな感じで作っとく
わからなかったら僕の作ったリポジトリをそのまま使えば大丈夫です
動かしてみる
NODE_ENV=development yarn ts-node src/main.ts
で動くはず
僕のリポジトリを使っている場合は
yarn build:dev yarn start:dev
でも動きます.
プロダクションではwebpack-dev-middlewareを使わずにやる
serve-staticを使うと静的サイトを配信できます.これと今作ったwebpack-dev-middlewareのmoduleをNODE_ENV
の状態で切り替えれば完璧に動くはずです.
moduleを変更する
import { Module, DynamicModule, OnModuleInit, Inject } from '@nestjs/common'; import { HttpAdapterHost } from '@nestjs/core'; import { CLIENT_MODULE_OPTIONS } from './client-options.constant'; import { ClientOptions } from './client-options.interface'; import { ServeStaticModule } from '@nestjs/serve-static'; import { ClientProvider } from './client.provider'; @Module({ providers: [ClientProvider], }) export class ClientModule implements OnModuleInit { constructor( @Inject(CLIENT_MODULE_OPTIONS) private readonly clientOptions: ClientOptions, private readonly httpAdapterHost: HttpAdapterHost, private readonly clientProvider: ClientProvider, ) {} static forRoot(options: ClientOptions): DynamicModule { return process.env.NODE_ENV !== 'development' ? ServeStaticModule.forRoot(options) : { module: ClientModule, providers: [ { provide: CLIENT_MODULE_OPTIONS, useValue: options, }, ], }; } public async onModuleInit() { if (process.env.NODE_ENV !== 'development') return; const httpAdapter = this.httpAdapterHost.httpAdapter; const { webpackConfig } = this.clientOptions; this.clientProvider.register(httpAdapter, webpackConfig); } }
interfaceを変更する
import { ServeStaticModuleOptions } from '@nestjs/serve-static'; import { Configuration } from 'webpack'; export interface ClientOptions extends ServeStaticModuleOptions { webpackConfig: Configuration; }
app.module.tsに変更を反映する
静的サイトはdist/public
にbuildされるように僕のリポジトリでは設定されているのでそのように設定します.
import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm'; import { ClientModule } from './client/client.module'; import config from '@/webpack.config.client.js'; import { Configuration } from 'webpack'; import { getMetadataArgsStorage } from 'typeorm'; import { UserModule } from './user/user.module'; import ormConfig from '@/ormconfig.json'; import { join } from 'path'; const { cli, migrations, ...typeOrmConfig } = { ...ormConfig, entities: getMetadataArgsStorage().tables.map(tbl => tbl.target), }; @Module({ imports: [ ClientModule.forRoot({ renderPath: '/', rootPath: join(__dirname, 'public'), webpackConfig: config as Configuration, }), TypeOrmModule.forRoot(typeOrmConfig as TypeOrmModuleOptions), UserModule, ], controllers: [AppController], providers: [AppService], }) export class AppModule {}
以上です.これで先ほどと同じように
NODE_ENV=development yarn ts-node src/main.ts
僕のリポジトリを使っている場合は
yarn build:dev yarn start:dev
で動くかと思います.clientもビルドして配信されるかどうか試してみてください.
僕のリポジトリでは
yarn build yarn start:prod
でできると思います.
TypeORMとwebpack-dev-middlewareとaspidaと俺と
Reactで作ったUserのCreateとid検索ができるサンプルアプリを作りました.aspidaで型安全にapiを叩きながらNestJSでapiを実装する.それを開発時はwebpack-dev-middlewareから配信されるReactから叩く,プロダクション時はserve-staticで配信されるReactからapiが叩かれる.なかなか型で守られていていいのではないでしょうか?僕はいいと思って作りました.
動かし方
開発時
docker-compose up --build -d yarn typeorm migration:run yarn build:dev yarn start:dev
それ以外
mysqlはdocker-composeで立ち上げたままで,開発環境と別にしたい時は,ormconfig.jsonをdevとprodでわけるといいでしょう.
yarn build yarn start:prod
こんな画面になるはずです
おわりに
お疲れ様でした.長い記事になってしまいました.きっとDXが上がるはず!と信じてやってみました.なかなか良さそうではないでしょうか?
今回はReactでやっていますが,Vueでもできると思います.Angularはコマンド一発でできるのでこんなことはしなくていいです.
どうでもいいのですが.明日卒論の目次案のゼミがあります.書くことが何もありません・・・・・NestJSの記事貼り付けようかな・・・・
これと関連している記事でTypeORMとwebpackという記事も書いているのでよかったらみてください naporitan.hatenablog.com
【NestJSアドベントカレンダー】NestJS & TyoeORMをWebackでつかう!!!【21日目】
NestJS & TypeORM & Webpackで優勝したい!
NestJsはmoduleが膨れ上がっていくと, ts-nodeだと起動がめちゃくちゃ遅くなって開発時にすごいストレスになります。それを解決できるのがHMRで、webpackです
はじめに結論
entities: getMetadataArgsStorage().tables.map(tbl => tbl.target)
をTypeOrmModule.forRootのコンフィグに設定すれば行けます
今回のリポジトリです。
NestJS & TypeORMの環境を作る
プロジェクトを作って, 必要なものをいれる
nest new sample cd sample yarn add @nestjs/typeorm typeorm mysql class-transformer class-validator
ormconfig.jsonをつくる
ormconfig.jsonにしたがってmigrationファイルとかentiiyファイルをtypeorm cliが動きます。 typeorm cliがあるとmigrationファイルを生成したり、entityファイルを生成できるので設定しておきましょう。
{ "type": "mysql", "host": "localhost", "port": 3307, "username": <user_name>", "password": <mysql_password>, "database": <database_name>, "entities": ["src/entities/*.ts"], "migrations": ["src/migrations/*.ts"], "synchronize": false, "cli": { "migrationsDir": "src/migrations", "entitiesDir": "src/entities" } }
cliについてはこちらでより詳細に見れるかと思います。
app.module.tsにtypeormをimportする
先ほど作ったjsonを元にTypeOrmModuleがデータベースと接続を試みます。
import { Module } from '@nestjs/common'; import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import ormConfig from '../ormconfig.json'; @Module({ imports: [TypeOrmModule.forRoot(ormConfig as TypeOrmModuleOptions)], controllers: [AppController], providers: [AppService], }) export class AppModule {}
以下のようなエラーが出るときはdatabase周りの設定が間違っているので見直してみましょう
[TypeOrmModule] Unable to connect to the database. Retrying
一応これでTypeORMが使えるようになってWebpackでビルドの方に行ってもいいのですが、どうせならentityとマイグレーションとCR(UD)を作って、Webpackでビルドしても動くことを確かめましょう。
User Entityを作る
package.jsonのscriptsに
"typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js"
を追加しておきましょう。yarn typeorm ...
でコマンドを使えるようになって便利です。
Userエンティティを作っていきます。
yarn typeorm entity:create -n User
Userには名前を保存するようにしましょう
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; @Entity() export class User { @PrimaryGeneratedColumn() id!: number; @Column('varchar') name: string; }
エンティティ作成おわり
Migrationを作る
yarn migration:generate -n CreateUserTable
これだけでentities配下にあるファイルとデータベースの差分を計差してtimestamp-CreateUserTable
という名前でファイルが作られます。
これをデータベースに反映させたい時は以下のコマンドでできます
yarn migration:run
データベースにはmigrationsテーブルが勝手に作られそこでどこまでマイグレーションしたかを保存しているみたいです。
UserCR(UD)をつくる
nest g mo user nest g s user nest g co user
- user.module.ts
import { Module } from '@nestjs/common'; import { UserController } from './user.controller'; import { UserService } from './user.service'; import { TypeOrmModule } from '@nestjs/typeorm'; import { User } from '../entities/User'; @Module({ imports: [TypeOrmModule.forFeature([User])], controllers: [UserController], providers: [UserService], }) export class UserModule {}
- user.service.ts
import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { User } from '../entities/User'; import { Repository } from 'typeorm'; import { CreateUserDto } from './dot/createUser.dto'; @Injectable() export class UserService { constructor(@InjectRepository(User) private readonly userRepository: Repository<User>) {} async findById(id: number) { return await this.userRepository.findOne(id); } async create(createUserDto: CreateUserDto) { return this.userRepository.save(createUserDto); } }
- user.controller.ts
import { Controller, Get, Param, Post, UsePipes, ValidationPipe, Body } from '@nestjs/common'; import { UserService } from './user.service'; import { CreateUserDto } from './dot/createUser.dto'; @Controller('user') export class UserController { constructor(private readonly userService: UserService) {} @Get(':id') async findUserById(@Param('id') id: string) { return this.userService.findById(parseInt(id, 10)); } @Post() @UsePipes(new ValidationPipe()) async create(@Body() createUserDto: CreateUserDto) { return this.userService.create(createUserDto); } }
- src/user/createUserDto.ts
import { IsString, IsNotEmpty } from 'class-validator'; export abstract class CreateUserDto { @IsString() @IsNotEmpty() name: string; }
実行する
これで動けばNestJSとTypeORMの設定は終わりです。
yarn ts-node src/main.ts
WebpackでNestJSをビルドする
without cliをやっていきます docs.nestjs.com
必要なライブラリをインストールする
yarn add -D webpack-node-externals webpack webpack-cli webpack-node-externals ts-loader
webpackでHMRをやる
const webpack = require("webpack"); const path = require("path"); const nodeExternals = require("webpack-node-externals"); module.exports = { entry: ["webpack/hot/poll?100", "./src/main.ts"], target: "node", externals: [ nodeExternals({ whitelist: ["webpack/hot/poll?100"], }), ], module: { rules: [ { test: /.tsx?$/, use: "ts-loader", exclude: /node_modules/, }, ], }, resolve: { extensions: [".tsx", ".ts", ".js"], }, plugins: [new webpack.HotModuleReplacementPlugin()], output: { path: path.join(__dirname, "dist"), filename: "server.js", }, };
- main.ts
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; declare const module: any; async function bootstrap() { const app = await NestFactory.create(AppModule); await app.listen(3000); if (module.hot) { module.hot.accept(); module.hot.dispose(() => app.close()); } } bootstrap();
これをしてyarn webpack --config webpack.cofig.js
してビルドできれば成功なのですが、できません。
こうなると思います。これはormconfig.jsonのentitiesに書いてあるファイルをTypeORMModuleが読みに行こうとするが、commonjsでないため起動できないという感じになります。
これをどう解決するかが、本題なのですが長くなりました。すみません。
答えはこちらです。
app.modules.tsのTypeOrmModuleでconfigを読み込むところを以下のように変更してください。
import { Module } from '@nestjs/common'; import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { UserModule } from './user/user.module'; import { getMetadataArgsStorage } from 'typeorm'; import ormConfig from '../ormconfig.json'; const { cli, migrations, ...typeOrmConfig } = { ...ormConfig, entities: getMetadataArgsStorage().tables.map(tbl => tbl.target), // < --これを設定することで }; @Module({ imports: [TypeOrmModule.forRoot(typeOrmConfig as TypeOrmModuleOptions), UserModule], controllers: [AppController], providers: [AppService], }) export class AppModule {}
できた
おわりに
自分の使っているプロジェクトでやってみたんですけど、起動時間が大幅に短縮されています。
明日は @potato4d さんのExpress + TypeORM NestJS 移行です
にじめぐりをAirPodsProで聞いてみた感想
にじめぐりをAirPodsProで聞いてみる
セットで売られている骨伝達BluetoothイヤホンではなくAirPodsProで聞いてみたオタクの感想ブログです。外音取り込みでにじめぐりを聞いたらテンションが上がってしまっていてもたってもいられなくなり、文章に綴りました。
AirPodsProを書いました
2週間くらいまってようやくきました。めっちゃ待ちました・・・・
やあああああああたああああああAirPodsPro届いた!!、!!!!! pic.twitter.com/2rNsUCOR37
— 🍆naporitan🍆@うーねこ団 (@naporin24690) 2019年11月22日
AirPodsProのいいところ
- ノイキャンがなかなかいい
- エアコンの音とか車の音、換気扇の音などが消えます。音で気が散る人はおすすめです
- 外音取り込みがすごい
- これがにじめぐりとの相性の良さを発揮します。
- 僕はこの機能が良すぎて常にAirPodsProを装着して人と話しています。(補聴器かな?)
- ヘッドホン・イヤホンと比べて顔に発生する違和感がない
- これは人それぞれかと思います。
- ヘッドホンの頭に乗っかる感じは僕はあまり好きじゃないので完全ワイヤレスのイヤホンが気に入っています。
にじめぐりとは
- 秋葉原と両国を歩いているとライバーから話しかけてくれる
- チェックポイントに到達するとライバー同士の会話が聴ける
という感じのGPSと音声を利用したアプリケーションです。
秋葉原に寄ったときに5箇所くらいだけ回ったのですが、本当に最高でした・・・・・・近々時間を空けて再チャレンジする予定です
【スマホアプリ「にじめぐり」サービス開始!!】
— にじさんじ公式🌈🕒 (@nijisanji_app) 2019年12月1日
「VtL両国」に出演するメンバーが現実世界に飛び出して、秋葉原・両国の街巡り!
1カ月間限定のスマホアプリ「にじめぐり」いよいよ本日よりサービス開始!
iOS版▽https://t.co/AW1SOaLZDG
Android版▽https://t.co/18feBsfgB5#VtL両国 pic.twitter.com/deE8KKpn1Q
にじめぐり × AirPodsProの良さ
外音取り込みの精度のよさ。これに尽きると思います。AirPodsProはイヤホンの外にあるマイクで拾った音をスピーカーで再生しているようなものなので(厳密にはどうなっているかは知りませんが)本当に街の雑踏の中にライバー同士の会話が紛れ込んでいるような印象を受けました。
これは少し慣れが必要なのですが、僕は補聴器のように使っていると述べたように1日のほとんどをAirPodsProをつけてすごしています。そうするとつけている感覚が薄れるのです。完全ワイヤレスなのも感覚が薄れる1つの要因になっているでしょう。薄れている状態で、外音取り込みをしながらにじめぐりを聞く!はい、最高。良すぎ!そこにいる。ライバーたちが見えた!!!!!!
最高すぎてイケメンになっちゃいました。
こんなかんじになれるのでにじめぐり × AirPodsProは相性がいいよって話でした。
AirPodsPro3万だけど常につけてるしライバーが見える(幻覚)ので0円!!!!!!!!!!!!!!