webpackまとめ
webpackとは
webpackとはモジュールバンドラーになります。
webpacklを利用することで、複数のモジュールを依存関係を解決して一つのアセットにまとめることが出来ます。(下記イメージ図)
webpackメリット
- モジュールを一つにまとめることで、パフォーマンスを落とさずにHTTP通信が可能になる
- スクリプトの読み込み順番とかの依存関係をwebpackでまとめることが出来る
- 外部モジュール(npmとかでインストールしたもの)もバンドリングすることができる
webpackデメリット
- 概念理解が難しい
- webpack.config.js の設定がややこしい
webpackインストール
npm init
でpackaje.jsonを作成する。
npm install webpack webpack-cli
でwebpck本体とCLIを同時にインストールする。
webビルド
npx webpack
でビルドすることが可能です。
npx webpack --mode development
でdevelopmentoモードでビルドすることができる。
※ npxとは npmとnpx。なにが違う?
webpack.config.js
バンドリングの説明などの設定を記載するファイル。
webpackを理解する上で一番大事な箇所。
webpack.config.jsには大量の設定項目がありますが、まずは4つの中心的な項目について理解する必要があります。
■ Entry
webpackがビルドを始める際の開始点となるjsファイル。 モジュールやライブラリの依存関係を判断、処理してくれます。
const path = require('path') module.exports = { entry: path.resolve(__dirname, "entry.js"), }
■ Output
bundleファイルをwebpackがどこにどのような名前で出力すればいいのかを指定できます。
distディレクトリの中にbundle.jsという名前で出力するとしたら次のようになります。
__dirname
はディレクト名称になります。
const path = require('path') module.exports = { entry: path.resolve(__dirname, "entry.js"), output: { path: path.resolve(__dirname, 'dist'), filename: 'bundle.js' } }
■ Loaders
webpack自身はJavaScriptしか理解できませんが、Loaderを使うことによってJavaScript以外のものも処理できるようになります。
testプロパティに拡張子を指定して、あるLoaderがどのような種類のファイルを処理するべきなのか特定する(正規表現で拡張子を指定)。下記の例で言うと、拡張子が.txtのものを指定している。
useプロパティにLoaderを指定して、testプロパティに指定したファイルがアプリケーションの依存関係や最終的なbundleファイルに加えられるように変換する。下記の例で言うと、txtファイルの場合はbundleファイルに追加する前にraw-loaderで変換する。
const path = require('path') module.exports = { entry: path.resolve(__dirname, "entry.js"), output: { path: path.resolve(__dirname, 'dist'), filename: 'bundle.js' }, module: { rules: [ { test: /\.txt$/, use: 'raw-loader' } ] } }
■ Plugins
Pluginはwebpackができることの幅を広げてくれます。
プラグインを利用する場合はrequireして、plugins配列に追加します。
const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') const webpack = require('webpack') module.exports = { entry: path.resolve(__dirname, "entry.js"), output: { path: path.resolve(__dirname, 'dist'), filename: 'bundle.js' }, module: { rules: [ { test: /\.txt$/, use: 'raw-loader' } ] }, plugins: [ new webpack.optimize.UglifyJsPlugin(), new HtmlWebpackPlugin({template: './src/index.html'}) ] }
参考
:isで動的にコンポーネントを変更する方法
:isで動的にコンポーネントを変更する方法
動的にコンポーネントを変更する方法としてv-ifを利用する方法がありますが、コンポーネントの数が増えてくると非常に手間になります。
その時に便利なのが:isを利用してパラメーターによってコンポーネントを変更する方法です。
例)テンプレート側
<div>
<!--ここで読み込むコンポーネントが動的に変わる-->
<component :is="currentHeader">
<slot></slot>
<footer>同じ内容</footer>
</div>
例)JS側
import IndexHeader from './IndexHeader.vue' import SearchHeader from './SearchHeader.vue' import ArchiveHeader from './ArchiveHeader.vue' export default { props: ['currentHeader'], components: { Index: IndexHeader, Search: SearchHeader, Archive: ArchiveHeader } }
Type Scriptの型(基本)
Type Scriptの型(基本)
// 型推論の場合は型を定義しなくてもOK let hasValue = true; let count = 10; let float = 3.14; let negative = -0.12; let single = 'hello'; let double = "hello"; let back = `hello`; // 型注釈の場合は型を定義する let hello: string; hello = 'hello'; // オブジェクトに型を定義する const person: { name: string age: number } = { name: 'jack', age: 21 } // 配列に型を定義する const fruits: string[] = ['Apple', 'Banana', 'Grape']; // tuple型を定義する(型定義以外のものがくればエラーになる。より厳密にしたい場合に利用する) const book: [string, number, boolean] = ['business', 1500, false]; // enum定義もできる enum CoffeeSize { SHORT, TALL = 'TALL', GRANDE = 1, VENTI } const coffee = { hot: true, size: CoffeeSize.TALL } coffee.size = CoffeeSize.SHORT; // anyはなんでも入れる事が出来る(TypeScriptの恩恵を受けれないので基本は利用しないようにする) let anything: any = true; anything = 'hello'; anything = ['hello', 33, true]; anything = {}; anything.fjiafjaj = 'faijfi'; let banana = 'banana'; banana = anything; // unionは複数の型を定義できる let unionType: number | string = 10; let unionTypes: (number | string)[] = [21, 'hello'] // unionとliteralを同時に使え // typeエイリアスを利用して複雑な型を変数のように扱う type ClothSize = 'small' | 'medium' | 'large'; const apple = 'apple'; let clothSize: ClothSize = 'large'; const cloth: { color: string; size: ClothSize } = { color: 'white', size: 'medium' } // 関数に型をつけることも可能 // パラメーターの後(第二引数)に戻り値の型を指定する function add(num1: number, num2: number): number { return num1 + num2 } // 関数の戻り値にvoidをすると何も返さない(undefined)という意味になる function sayHello(): void { // console.log('Hello!'); } // console.log(sayHello()); let tmp: undefined; // 関数型を使えば特定の関数のみ代入できる変数を作成できる const anotherAdd: (n1: number, n2: number) => number = function (num1, num2) { return num1 + num2 }; // アロー関数で書く場合 const doubleNumber: (num: number) => number = num => num * 2; // callback関数に型をつけることもできる function doubleAndHandle(num: number, cb: (num: number) => void): void { const doubleNum = cb(num * 2); // console.log(doubleNum); } doubleAndHandle(21, doubleNum => { return doubleNum }); // unknownはanyと一緒でなんでも入れられる let unknownInput: unknown; let anyInput: any; let text: string; unknownInput = 'hello'; unknownInput = 21; unknownInput = true; text = anyInput; if (typeof unknownInput === 'string') { text = unknownInput; } function error(message: string) { throw new Error(message); } console.log(error('This is an error'));
Cloud Build is 何?
Cloud Build is 何?
Cloud Build は、Google Cloud Platform のインフラストラクチャでビルドを行うサービスです。 Cloud Build は、さまざまなリポジトリやクラウド ストレージ スペースからソースコードをインポートし、仕様に合わせてビルドを実行し、Docker コンテナや Java アーカイブなどのアーティファクトを生成できます。
簡単に言うとGCPが提供するCIツールの一種になります。
GCPに特化したビルドサービスがCloud Buildになる感じです。
料金
フルマネージドのサービスで、1分あたりの料金も$0.003と非常に安く、1 日あたり120分は無料
デプロイイメージ
CludBuild設定
Cloud Build で必要なものは主に以下になります。
1. トリガー 2. リポジトリ/ブランチ(git 関連) 3. ビルド実行用ファイル 4. Dockerfile
例) 1. 任意のブランチからSource Repositories に対してgit push 2. 事前にCloud Build のトリガーを作成し、git push を検知してトリガーを実行 3. コンテナイメージをビルドして、Container Registry にpush 4. push したイメージを元にGKE にコンテナをデプロイ
参考
ffiインストールエラー対策
bundle installで下記のエラーが出る
1 error generated. make: *** [Function.o] Error 1 make failed, exit code 2 Gem files will remain installed in /Users/inouehiroki/ghq/github.com/SchooLynk/schoolynk-intelligence-api/vendor/bundle/ruby/2.6.0/gems/ffi-1.11.1 for inspection. Results logged to /Users/inouehiroki/ghq/github.com/SchooLynk/schoolynk-intelligence-api/vendor/bundle/ruby/2.6.0/extensions/-darwin-20/2.6.0/ffi-1.11.1/gem_make.out An error occurred while installing ffi (1.11.1), and Bundler cannot continue. Make sure that `gem install ffi -v '1.11.1' --source 'https://rubygems.org/'` succeeds before bundling. In Gemfile: guard-rspec was resolved to 4.7.3, which depends on guard was resolved to 2.15.1, which depends on listen was resolved to 3.1.5, which depends on rb-inotify was resolved to 0.10.0, which depends on
gem install ffi -v '1.11.1' --source 'https://rubygems.org/'
と言われているので実施する
➜ schoolynk-intelligence-api git:(master) gem install ffi -v '1.11.1' --source 'https://rubygems.org/' Building native extensions. This could take a while... ERROR: Error installing ffi: ERROR: Failed to build gem native extension. current directory: /Users/inouehiroki/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/ffi-1.11.1/ext/ffi_c /Users/inouehiroki/.rbenv/versions/2.6.6/bin/ruby -I /Users/inouehiroki/.rbenv/versions/2.6.6/lib/ruby/2.6.0 -r ./siteconf20210605-43335-vyqlly.rb extconf.rb checking for ffi_call() in -lffi... yes checking for ffi_closure_alloc()... yes checking for shlwapi.h... no checking for rb_thread_call_without_gvl()... yes checking for ruby_native_thread_p()... yes checking for ruby_thread_has_gvl_p()... yes checking for ffi_prep_cif_var()... yes checking for ffi_raw_call()... yes checking for ffi_prep_raw_closure()... yes creating extconf.h creating Makefile current directory: /Users/inouehiroki/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/ffi-1.11.1/ext/ffi_c make "DESTDIR=" clean current directory: /Users/inouehiroki/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/ffi-1.11.1/ext/ffi_c make "DESTDIR=" compiling AbstractMemory.c compiling ArrayType.c compiling Buffer.c compiling Call.c compiling ClosurePool.c compiling DynamicLibrary.c compiling Function.c Function.c:867:17: error: implicit declaration of function 'ffi_prep_closure' is invalid in C99 [-Werror,-Wimplicit-function-declaration] ffiStatus = ffi_prep_closure(code, &fnInfo->ffi_cif, callback_invoke, closure); ^ 1 error generated. make: *** [Function.o] Error 1 make failed, exit code 2 Gem files will remain installed in /Users/inouehiroki/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/ffi-1.11.1 for inspection. Results logged to /Users/inouehiroki/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/extensions/-darwin-20/2.6.0/ffi-1.11.1/gem_make.out
Function.c:867:17: error: implicit declaration of function 'ffi_prep_closure' is invalid in C99 [-Werror,-Wimplicit-function-declaration] ffiStatus = ffi_prep_closure(code, &fnInfo->ffi_cif, callback_invoke, closure);
このエラーの対策
export PKG_CONFIG_PATH="/opt/homebrew/opt/libffi/lib/pkgconfig"
参考:
M1 MAC で ARM64版のnodebrewインストール
M1 MAC で ARM64版のnodebrewインストール
https://minnano.app/support/2021/04/09/m1-mac-arm64-homebrew-node-2021-04/
この記事を参考にした。
vuex-persistedstateハマりポイント(Vuex)
vuex-persistedstateハマりポイント(Vuex)
vuex-persistedstateがイケてなくてリロード時にgettersでnullになった話
■ 原因 ローカルストレージ→storeのコピーがmounted()の後にコピーされる
■ 対策 nuxt-client-init-moduleをインストールする。
これで “nuxtClientInit” という関数でクライアントが初期がしたときの動作を定義できる
参考
【Nuxt.js】vuex-persistedstateがイケてなくてリロード時にgettersでnullになった話 | のうみそブログ
続きを読む