Address already in use の対処法
たまにビルドインサーバーの遮断し忘れとかで Address already in use
がでるので、対処法をメモ。
まず、ポート番号を指定して、実行中のプロセスを確認し、
lsof -i:8888
出力された PID をコピーして、以下のコマンドで遮断する。
kill ${PID}
【Android】View の id とエントリ名の変換
エントリ名から id を取得
hoge
というエントリ名から、R.id.hoge
という id の数値を取得するなら、
int viewId = getResources().getIdentifier("hoge", "id", getPackageName());
この viewId
で findViewById(viewId)
できる。for で連番しているエントリ名などから View を取得するのに便利。
id からエントリ名を取得
逆に、id の数値からエントリ名を取得するなら、
String viewIdStr = getResources().getResourceEntryName(viewId);
View から getId()
とかで id さえ取得していれば、それを上記のようにエントリ名へ変換して正規表現でチェックとかできる。
他のリソース
View の id 以外でもできる。
int strId = getResources().getIdentifier("hoge", "string", getPackageName());
注意点
getIdentifier について、ドキュメント曰く、
Note: use of this function is discouraged. It is much more efficient to retrieve resources by identifier than by name.
オススメできない方法とのこと。
Mac の ターミナルで tree を表示
tree をインストール
brew install tree
tree を表示
当該ディレクトリで、
tree
パスを指定するなら、
tree .
など。日本語が文字化けする際は、
tree . -N
でOK。表示するディレクトリの深さをしていするなら、
tree -L LEVEL
次のような感じに表示される。
. ├── CHANGELOG.md ├── LICENSE ├── README.md ├── assets │ ├── fonts │ ├── images │ ├── javascripts │ └── stylesheets ├── eyeglass-exports.js └── package.json
パスを書く必要がある際には便利。他、使いそうなオプションは、
オプション | |
---|---|
-a | 隠しファイルも表示 |
-d | ディレクトリのみ表示 |
-P | 正規表現にマッチするものを表示 |
-F | ディレクトリ末尾にスラッシュを表示 |
-o | 書き出し |
Android の apk 出力で Unsupported major.minor version 52.0 エラー
出力する apk ファイルの量が多いので、コマンドラインから gradle 使ってビルドをすることが多いけど、今回急に次のエラーが出て戸惑った。
A problem occurred evaluating project ':app'. > java.lang.UnsupportedClassVersionError: me/tatarka/RetrolambdaPlugin : Unsupported major.minor version 52.0
結論だけ言えば、java8 を使えば解消される。 以下が詳しくて助かった。
Androidアプリのビルドで「Unsupported major.minor version 52.0」のビルドエラーが発生する
webpack をサクッと使う手順
- 0. ディレクトリとテストファイルの準備
- 1. package.json を作る
- 2. devDependencies に追加する
- 3. dependencies に追加する
- 4. package.json を修正
- 5. webpack.config.js を置く
- 6. ビルドして確かめる
webpack の基本操作 にて述べた方法で、効率良く開発環境を整える手順を改めてまとめておく。
要件は、
- js モジュールの統合と単一書き出し
- sass の 統合と css 単一書き出し
- compass の読み込み
- js, css のミニマイズ
- js, css の map ファイルの生成
- ES6 -> ES5 トランスパイル(コンパイル)
- jquery の読み込み
- watch で変更を監視
完成後のディレクトリ構成(ビルド前)は次のようになる。
project/ ├── _css │ ├── entry.sass │ └── sub.sass ├── _js │ ├── entry.js │ └── sub.js ├── css ├── js ├── node_modules ├── package.json ├── webpack_index.html └── webpack.config.js
- ビルド前の各モジュールは
_
(アンダースコア)から始まるディレクトリに入れる - ビルド後のファイルは、それぞれ js, css ディレクトリに格納される
- webpack_index.html は確認用の html
0. ディレクトリとテストファイルの準備
# 各ディレクトリ mkdir {_css,_js,css,js} # テスト用 html echo '<html><link rel="stylesheet" media="all" href="./css/style.css"><body><h1></h1></body><script src="./js/bundle.js"></script></html>' > webpack_index.html # entry.scss echo '@import "compass"; @import "sub"; h1 { @include inline-block; color: #f00; }' > _css/entry.scss # sub.scss echo '@import "compass"; h1 { background-color: #000; }' > _css/sub.scss # entry.js echo 'var $ = require("jquery"); $(function(){$("h1").text(require("./sub.js"));});' > _js/entry.js # sub.js echo 'module.exports = "OK";' > _js/sub.js
- webpack_index.html ではビルド後の js と css の読み込みの他、h1 タグを用意しておく
- entry.scss では sub.scss を読み込む他、h1 を赤字に、また compass で inline-block にする
- sub.scss では h1 の背景を黒にする
- entry.js では jquery の読み込みの他、sub.js の出力を h1 にセットする
- sub.js は “OK” を返す
- ビルド後のイメージは次の感じ
1. package.json を作る
-y
オプションを付けて対話をせずに、初期化する。
npm init -y
2. devDependencies に追加する
npm install --save-dev webpack babel-loader babel-core babel-preset-es2015 node-sass style-loader css-loader sass-loader extract-text-webpack-plugin compass-mixins
それぞれ、
webpack 本体
- webpack
ES6 対応
- babel-loader
- babel-core
- babel-preset-es2015
- sass 対応
- node-sass
- style-loader
- css-loader sass-loader
- sass -> css 書き出し対応
- extract-text-webpack-plugin
- compass 対応
- compass-mixins
3. dependencies に追加する
npm install jquery --save
4. package.json を修正
... "private": true, "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack --optimize-minimize" }, ...
- プライベート用にして警告排除
"private": true
- ビルドファイルのミニマイズ設定
"build": "webpack --optimize-minimize"
5. webpack.config.js を置く
var path = require('path'); var ExtractTextPlugin = require('extract-text-webpack-plugin'); module.exports = [ /** * js */ { entry: "./_js/entry.js", watch: true, output: { path: path.join(__dirname, './js'), filename: "bundle.js" }, module: { loaders: [{ test: /\.js[x]?$/, exclude: /node_modules/, loader: 'babel-loader?presets[]=es2015' }] }, devtool: 'source-map' }, /** * Sass */ { entry: './_css/entry.scss', watch: true, output: { path: path.join(__dirname, './css'), filename: 'style.css' }, module: { loaders: [{ test: /\.scss$/, loader: ExtractTextPlugin.extract({ use: [{ loader: 'css-loader' }, { loader: 'sass-loader', options: { includePaths: ['node_modules/compass-mixins/lib'] }, } ], fallback: 'style-loader' }) }] }, plugins: [ new ExtractTextPlugin('style.css') ], devtool: 'source-map' } ];
6. ビルドして確かめる
npm run build
実行後、webpack_index.html をブラウザで開き、
と表示されれば、js, sass ともにビルドができている。
また、js/bundle.js, css/style.css はそれぞれミニマイズされていて、かつ同階層に map ファイルも出力されていれば問題ない。
webpack の基本設定
webpack を初めて触ったので、調べたことなどを備忘録として残しておく。webpack のインストールから、ES6, jQuery, Sass, compass の対応まで。
- 1. npm の準備
- 2. ローカルに webpack をインストール
- 3. ローカルにパスを通す
- 4. webpack でビルドをテストする
- 5. webpack.config.js からビルドする
- 6. watch モードにする
- 7. jquery を使う
- 8. ES6 に対応させる
- 9. js を minimize する
- 10. Sass の設定をする
- 11. compass を使う場合
1. npm の準備
package.jsonを作る。
npm init
2. ローカルに webpack をインストール
package.json に書き込みたいので、--save-dev
オプションをつける。
npm install webpack --save-dev
No repository field.
と怒られた場合、一先ず、package.json に "private": true
を追加すれば警告は消える。
ドキュメントに依ると、
If you set “private”: true in your package.json, then npm will refuse to publish it.
This is a way to prevent accidental publication of private repositories. If you would like to ensure that a given package is only ever published to a specific registry (for example, an internal registry), then use the publishConfig dictionary described below to override the registry config param at publish-time.
要は公開用のリポジトリじゃなく、プライベートなリポジトリのみで使うっていう設定。これを指定すれば、repository field
の指定がなくても許される。
3. ローカルにパスを通す
このままだと、webpack
コマンドは動かないので、パスを通す。
export PATH=$PATH:./node_modules/.bin
以下でバージョンが確認出来る。
webpack -v
もちろん、パスを通す必要がないなら、直接、
node_modules/.bin/webpack -v
でも良い。
4. webpack でビルドをテストする
適当に、sub.js を作る。
module.exports = ["a", "b", "c"];
module.export
は return 的なやつ。これを app.js で読み込み、出力する。
console.log(require("./sub.js"));
これを bundle.js としてビルドする。
webpack app.js bundle.js
実行すると、
Version: webpack 2.6.1 Time: 81ms Asset Size Chunks Chunk Names bundle.js 2.78 kB 0 [emitted] main [0] ./sub.js 34 bytes {0} [built] [1] ./app.js 34 bytes {0} [built]
こんな感じの実行結果と bundle.js が書き出されている。
この bundle.js を実行すると、次のような結果になる。
[ 'a', 'b', 'c' ]
なお、npm の実行時にこれも一緒にビルドして欲しいので、build:
の項目を設け、そこに追加する。
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack app.js bundle.js" },
そうすれば、
npm run build
でビルドしてくれる。
5. webpack.config.js からビルドする
そもそも webpack 実行時に js のビルドも自動的にしてほしいので、webpack.config.js にその設定を書く。
まずは、package.json の build:
項目を webpack
だけにして、
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack" },
以下のように webpack.config.js を作成。entry
と output
の filename
指定する。
module.exports = { entry: "./app.js", output: { filename: "bundle.js" } }
そうすれば、先ほどと同様に、
npm run build
でビルド出来る。ディレクトリパスを別途指定するなら、path モジュールを読み込んで、
var path = require('path'); module.exports = { entry: "./js/modules/app.js", watch: true, output: { path: path.join(__dirname, './js'), filename: "bundle.js" } }
のようにする。
6. watch モードにする
ファイルを監視させて、変更時に自動ビルド。コマンドラインから設定するなら、
webpack --watch
一方、webpack.config.js で指定するなら、watch:
を設けて、true
にする。
module.exports = { watch: true, entry: "./app.js", ...省略...
7. jquery を使う
まずは、npm で jquery をダウンロード。プロダクトでもつかうので、 オプションは --save
。
npm install jquery --save
var $ = require("jquery"); $(function(){ });
件の通り、$ に jquery をつっこむだけ。
8. ES6 に対応させる
ES6 を ES5 にコンパイルというかトランスパイルというか、とにかく変換する場合は、babel-loader
を使う。
開発用なので、オプションは --save-dev
でインストールする。
npm install babel-loader babel-core babel-preset-es2015 --save-dev
webpack.config.js に以下を追加する。
...省略... module: { loaders: [{ test: /\.js[x]?$/, exclude: /node_modules/, loader: 'babel-loader?presets[]=es2015' }] } ...省略...
正規表現で node_modules を除く js 系の拡張子を対象にしている。
試しに app.js を次のように書き換え、
/*jshint esversion: 6 */ var $ = require("jquery"); $(function(){ "use strict"; const hoge = "!!!!"; $("body").text(hoge); });
ビルドすると、bundle.js では、
...省略... /*jshint esversion: 6 */ var $ = __webpack_require__(0); $(function () { "use strict"; var hoge = "!!!!"; $("body").text(hoge); }); ...省略...
const
-> var
の変換がされている。
9. js を minimize する
圧縮したいなら、packege.json の build:
で --optimize-minimize
のオプションをつける。
ただ、このままだとデバッグし難いので、更に --devtool source-map
のオプションもつけて、デベロッパーツールから圧縮前を見れるようにする。
...省略... "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack --optimize-minimize --devtool source-map" }, ...省略...
これで、Chrome デベロッパーツールの Sources タブに webpack:// のディレクトリが表示される。
source-map は webmap.config.js でも指定できる。
末尾に devtool:
の項目を追加し、source-map
を指定する。
...省略... module: { loaders: [{ test: /\.js[x]?$/, exclude: /node_modules/, loader: 'babel-loader?presets[]=es2015' }] }, devtool: 'source-map' ...省略...
10. Sass の設定をする
まずは、必要なモジュールをインストール。
npm install --save-dev node-sass style-loader css-loader sass-loader extract-text-webpack-plugin
css の出力も可能にするため、extract-text-webpack-plugin
も入れている。
webpack.config.js の exports
の対象をオブジェクト({}
)からオブジェクトの配列([{},{}]
)形式にして、次のように変更する。
var path = require('path'); var ExtractTextPlugin = require('extract-text-webpack-plugin'); module.exports = [ /** * js の設定 */ { entry: "./js/modules/app.js", watch: true, output: { path: path.join(__dirname, './js'), filename: "bundle.js" }, module: { loaders: [{ test: /\.js[x]?$/, exclude: /node_modules/, loader: 'babel-loader?presets[]=es2015' }] }, devtool: 'source-map' }, /** * Sass の設定 */ { entry: './css/modules/style.scss', watch: true, output: { path: path.join(__dirname, './css'), filename: 'app.css' }, module: { loaders: [{ test: /\.scss$/, loader: ExtractTextPlugin.extract('css-loader!sass-loader') }] }, plugins: [ new ExtractTextPlugin('app.css') ], devtool: 'source-map' } ];
これで、複数指定ができる。なお、出力先のディレクトリなども整理してある。
11. compass を使う場合
npm install --save-dev compass-mixins
sass-loader の includePaths に compass-mixins/lib を指定して読み込ませる。
/** * Sass の設定 */ { entry: './css/modules/style.scss', watch: true, output: { path: path.join(__dirname, './css'), filename: 'app.css' }, module: { loaders: [{ test: /\.scss$/, loader: ExtractTextPlugin.extract({ use: [{ loader: 'css-loader' }, { loader: 'sass-loader', options: { includePaths: ['node_modules/compass-mixins/lib'] }, } ], fallback: 'style-loader' }) }] }, plugins: [ new ExtractTextPlugin('app.css') ], devtool: 'source-map' }
下の config ファイルを参考にさせてもらった。
wkhtmltopdf で HTML を PDFにする
wkhtmltopdf のインストール
コマンド確認
wkhtmltopdf -h
上手くインストールされていれば、なんか色々表示される。
PDF に変換
試しに google.com を PDF 出力する。
wkhtmltopdf http://google.com google.pdf
これで簡単に出力できてハッピーなはずが……
ちっさ。サイズがひどいことになってる……。
サイズが小さい問題の対処
--disable-smart-shrinking
というオプションを付ければ良さそうという記事を読んで、さっそくトライするも、変わらず。このオプションは最適化してくれるものだけど、この出力は最悪化されているので、まぁ、違うだろう。
で、もう少し調べ、ようやく同じ事例を発見。
https://stackoverflow.com/questions/40814680/wkhtmltopdf-generates-tiny-output-on-mac
ここで問題が報告されている Mac OS のバージョンが自分のものと一致していて、少し、面倒臭い雰囲気がする……。なお、この時点の環境は、
- OS バージョン: 10.11.6(15G31)
- wkhtmltopdf バージョン: 0.12.4
手動で wkhtmltopdf を消し去って、別バージョンを入れてみる。インストール先に wkhtmltoimage もあって、一緒にインストールされたものなのでこれも消す。
以下から新しく 0.12.3 のインストーラーを落としてインストール。
https://downloads.wkhtmltopdf.org/0.12/0.12.3/
改めて、出力する。
はい、ハッピーになれた。