nginxがシンボリックリンクで403を返す
nginxが403を返す理由は様々です。
まずはこちらをざざっと参照し、気になるポイントがあったら試してみましょう:
僕は時々はシンボリックリンクを設定して403になってしまい頭を抱えてしまいます。数年に一回ぐらいのペースでやらかすので、毎回ググってるんですよね。
たとえば以下のように、your-project 以下に存在する assets ディレクトリを https://localhost/assets でアクセスできるようにしようとして、シンボリックリンクを設定すると403になったりします。
$ cd your-project $ ln -s assets /usr/local/var/www/assets
この場合は nginx.conf に location /assets/
を追加すると良いでしょう。
location /assets/ { root /usr/local/var/www/your-project/; }
蛇足になりますが、慣れていないと以下のように書いてしまいがちです。 このように設定すると nginx は https://localhost/assets へのアクセスを your-project/assets/assets/ として解決しようとします。 この試みは失敗し404が帰るでしょう。
# これはダメな例です location /assets/ { root /usr/local/var/www/your-project/assets/; }
こちらの記事も参考にしてください:
macで起動しているnginxに外部からアクセスできない? ひょっとしてファイアーウォールがONになっていませんか?
気がついたらiPhoneからmac上のnginxにアクセスできなくなってて(OS入れ替えの時にONに戻ったらしい)、さらに僕はこの設定の存在自体をど忘れしてしまって、なんだかんだで2時間ほど悩みました ><
ルータの設定をみなおしたり、nginxの設定色々変えたり見直したり、ディレクトリのパーミッションを見直したり、Proxy立てたり、あと沢山ググったよね… そんでファイアーウォールの設定をOFFにしたら一発で開通したよね…
macOS Sierra などでは、コマンドライン上から socketfilterfw を使ってもうまく設定できなくなっているようですので、GUI上でOFFにしましょう。
参考リンク:
macos - 80番ポートで起動させているnginxのWebサーバーに外部からアクセスできない - スタック・オーバーフロー
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add `readlink \`which nginx\`` sudo /usr/libexec/ApplicationFirewall/socketfilterfw --unblockapp `readlink \`which nginx\``
What I feel React Native.
パパッと作る場合はWrite once Run anywhere類似技術を活かせるし、それでOKとなるのだけど、解像度の低い発注者(お金で時間を買う人)が最終的に求めてくる物が
— うーぱーです (@uupaa) 2018年6月4日
・差別化要素が高く
・高速動作し
・非力な環境でも安定動作する物
の場合はリテイクが多発する事に
それなら最初から素で書くか…となるね
事前に"これはできます。こういうのはできません"と説明しても、お金を出す側は(なぜか)速攻でこちらの説明を忘れ「アレもコレもしたい」「競合アプリの機能をうちにも」と、すぐに要求が跳ね上がるのが常なので、一度書けばドコでも動く系技術における開発の難しさはこの辺にあるという肌感です
— うーぱーです (@uupaa) 2018年6月4日
2000年頃から人類はその時のプラットフォームに合わせたReact Nativeを発明し続けているのだけど、「こちらがサクッと対応してしまうが為に、発注側が勘違いし出したりして発注側の期待値と要求がマッハで跳ね上がる」という課題を人類はクリアできていないので、この手のやつはどうしたら良いんだろね
— うーぱーです (@uupaa) 2018年6月4日
時間とお金をかけて素で開発している強豪/競合アプリのステキ機能に発注元が気がついてしまうと
— うーぱーです (@uupaa) 2018年6月4日
「うちの(React Nativeベースの)アプリでも実現してよ!」
「えっ?できない?なんで!?」
となりがちで、それが"一度書けばどこでも動く"系開発の苦難だったりする。
なので最初から自社開発ならいいと思う
一度書けばどこでも動く系の技術は、 深さを犠牲に面積を取りに行く戦略(高機能性はネイティブAppには勝てないけど、そのかわりにスピードと面を取りに行く戦略)なので、 それを忘れて、銀の弾丸風に「80%はこれでカバーできる」「まだNativeでかいてるの?」「とりあえずビール」という感じのムードになると、(ちゃんと理解して使おうとしない層が大挙して押し寄せる事で) React Native もこれまでの何かのように早逝の道にルートが切り替わると思うので、過去の類似技術の失敗例を参考に、技術を育てていくのも大事だと思うのです。
過去の例だと、
- 適材適所という言葉がいつの間にか失われてた
- ムード先行で、実際の事例がしょぼかった
- 成功例だけが大きく宣伝され、失敗事例となぜ失敗したかが共有されなかった
みたいな感じでしたっけ
An interesting recent browser API for me.
Worker上の複数のWebAssembly instance間でメモリを共有可能にする
WebAuthn による安全なクライアント認証 API
メモリプレッシャーイベント navigator.onmemorypressure -https://www.chromestatus.com/feature/5719614029824000
新しい汎用センサーAPI
CustomElements で class NewButtonElement extends HTMLButtonElement を可能に
- これまでは class NewbuttonElement extends HTMLElement しかできなかった
- https://www.chromestatus.com/feature/4670146924773376
node.classList.replace():void が replace():boolean に
- 実際に書き換えが発生したかを知るための contains() が不要になりコードがコンパクトに
- https://www.chromestatus.com/feature/5690841569951744
Array.prototype.{flatten,flatMap}
AudioWorklet
- 従来の ScriptProcessorNode は非推奨に
- https://www.chromestatus.com/feature/4588498229133312
WebXR Device API (VR + AR = XR)
WebSockets over HTTP/2
WebAudio: Remove dezippering
Web Locks API
- 複数タブにまたがるリソースのロック。タブ間の協調動作を可能に
- https://www.chromestatus.com/feature/5287995770929152
ImageBitmap render for Canvas
- リソースの無駄を抑え最適化されたレンダリングを可能に
- https://www.chromestatus.com/feature/5709799995998208
catch (error) を catch() または catch と書けるようにする
存在しない blob URL を読み込ませた場合に404を返さずネットワークエラーにする
Media Capabilities: decoding API
- メディアを実際にデコードする前に、デコード可能かどうかをより詳しく調べる事が可能に
- video.canPlayType(“foo/bar”) が ‘maybe’ を返してくるので困ってた人々への福音?
- https://www.chromestatus.com/feature/5869632707624960
Link rel=modulepreload
- モジュールを事前にロードする事を指示することができる
- 既に普段使いしている機能
- https://www.chromestatus.com/feature/5762805915451392
JSON の文字列に U+2028 と U+2029 を使用する事を可能に
Fetch API の options で keepalive の指定が可能に
Fetch API を cancel 可能に
- AbortController と signal を使用することで XHR の abort() 相当の振る舞いを再現可能に
- https://developers.google.com/web/updates/2017/09/abortable-fetch
- https://www.chromestatus.com/feature/5631483679080448
MediaQuery 内部で CSS calc() を使用可能に
new CSS Typed Object Model
- CSS を js から文字列ではなく px や em といった型付きのまま扱う事ができる新しいAPIを提供
- https://developers.google.com/web/updates/2018/03/cssom
- https://www.chromestatus.com/feature/5682491075592192
Text以外のオブジェクトも扱う事ができる非同期クリップボードAPI
- document.execCommand() を過去の遺物にする新しいAPI
- 画像やユーザ定義オブジェクトなどもゆくゆくは扱えるようにするらしい
- https://www.chromestatus.com/feature/5861289330999296
PerformanceEntry.toJSON()
- パフォーマンス情報のJSON化が簡単に
- https://www.chromestatus.com/feature/6730557958389760
CSS display: contents
- display: contents 要素はboxを作成しないが、子要素は作成する
- ユースケースがまだよくわからない…
- https://www.chromestatus.com/feature/5663606012116992
Worklet
- 新しい Thread API。 Worker を置き換えてゆくもの
- AudioWorket や PaintWorket もあるよ
- https://www.chromestatus.com/feature/5275637463908352
-
- div { background-image: paint(“foo”); } で描画スペースを予約し
- CSS.paintWorklet.addModule(“Foo.js”); で Foo.js を module としてロードして
- class Foo { paint(ctx, geom, props) { … } } registerPaint(“foo”, Foo); するとCanvas APIで自由にレンダリング
- https://www.chromestatus.com/feature/5685444318593024
ethos agent tools: Add NightShift mode. it can reduce fan noise.
ethos-agent は ethOS を強化するツールです。
今日は、ethos-agent に夜間の騒音を低減する、NightShiftモードというものを追加しました。
NightShift を有効にすると、20:00〜05:00 の間は自動的にFanの回転数を一時的に下げ、静音化が可能になります。朝になると local.conf で設定している値に自動的に復帰します。
rigと同じ部屋で生活している人にとっては朗報でしょう。ほとんどrigの存在を気にせずに済むようになるはずです。
開発ログ
一枚目はデフォルト状態の騒音レベル(GPU4枚)
— コラーゲンたっぷりさん (@uupaa) 2018年3月27日
二枚目は昨日の時点の騒音レベル(GPU15枚、細かくチューニング済み)
三枚目は電源OFF状態(比較用)
マイニングリグは熱と音の問題があるのですが、やりようによってはクールで静かにやれる事がわかりました。枕元に置けるレベルです pic.twitter.com/hdBl7Q2kFf
/etc/rc.local の中で nvidia-setting を実行しようとするとディスプレイが割り当てられていないためコケる
— コラーゲンたっぷりさん (@uupaa) 2018年3月27日
su -l USER -s /bin/bash -c ‘実行したいコマンド’
でユーザを割り当てることで回避できる。睡眠時間は犠牲になったのだ…
rc.local の中でうっかりコケると、stdout, stderr がどこにも出ない + ひどいとOSが起動しなくなる(シングルユーザモードでrc.local編集が必要になる)ので、時間が溶ける
— コラーゲンたっぷりさん (@uupaa) 2018年3月27日
ドハマリして2時間しか寝れなかったので、日中どこかで仮眠しませんと…
— コラーゲンたっぷりさん (@uupaa) 2018年3月27日
/etc/rc.local に設定するコマンドを以下のように、su -l -s -c ...
と工夫することで、root ユーザでも、
/usr/bin/sudo /usr/bin/nvidia-settings -a [gpu:0]/GPUFanControlState=1 -a [fan:${index}]/GPUTargetFanSpeed="40"
が実行可能になりました。
単純に /usr/bin/node --experimental-modules /home/ethos/ethos-agent/index.mjs
だけだと、error: XDG_RUNTIME_DIR not set in the environment
でコケてしまいます。
su -l ethos -s /bin/bash -c '/usr/bin/node --experimental-modules /home/ethos/ethos-agent/index.mjs
eslint の async/await サポートと rollup の dynamic import サポート
github.com を update しました。
最新の eslint が async/await に対応し、
{ "parserOptions": { "ecmaVersion": 2017 } }
最新の rollup がフラグ付きながら import() に対応しました。
$ rollup --experimentalDynamicImport
これで eslint + rollup な bundle 環境における ES2017 + import() 対応がほぼ出揃った感じになりました。
npm で公開されているパッケージも、徐々に ES Modules にマイグレーションしていく流れができてきました。
2018/06/28 追記
dynamic import はeslintが公式にはサポートしてないため、
.eslinttc に "parser": "babel-eslint"
を追加し、$ npm i -D babel-eslint
を追加することでエラーを消す事ができます。
examples
// a.js export class Foo { async fetch() { return new Promise(async(resolve, reject) => { try { const url = `https://localhost`; const text = await(await fetch(url)).text(); await import("./b.js"); resolve(text); } catch(err) { reject(err); } }); } } (async() => { const foo = new Foo(); const html = await foo.fetch(); alert(html); })();
// b.js alert("b.js");
<!-- index.html --> <script type="module" src="a.js"></script>
.eslintrc
{ "parser": "babel-eslint", "parserOptions": { "ecmaVersion": 2017, "sourceType": "module" }, "env": { "browser": true, "node": true, "es6": true }, "extends": [ "eslint:recommended" ], "rules": { "strict": [0], "no-new": [0], "new-cap": [0], "no-empty": [0], "no-shadow": [0], "camelcase": [0], "key-spacing": [0], "dot-notation": [0], "comma-dangle": [0], "no-console": [0], "no-multi-str": [0], "no-multi-spaces": [0], "no-control-regex": [0], "no-unused-vars": [1, { "vars": "all", "args": "after-used"} ], "no-underscore-dangle": [0], "no-use-before-define": [0], "no-inner-declarations": [0] }, "globals": { "unescape": false, "escape": false, "google": false } }
package.json
{ "name": "app", "version": "0.0.0", "description": "", "main": "a.js", "scripts": { "bundle": "npm run bundle:es6", "bundle:es6": "rollup -c .rollup.es6.js", "bundle:es5": "rollup -c .rollup.es5.js" }, "repository": { "type": "git", "url": "..." }, "author": "", "license": "MIT", "devDependencies": { "babel-eslint": "^8.2.5", "babel-preset-es2015-rollup": "^3.0.0", "eslint": "^5.0.1", "execa": "^0.10.0", "npm-run-all": "^4.1.3", "request": "", "rollup": "^0.62.0", "rollup-plugin-babel": "^3.0.5", "rollup-plugin-buble": "^0.19.2", "rollup-plugin-cleanup": "^3.0.0-beta.1", "rollup-plugin-commonjs": "^9.1.3", "rollup-plugin-eslint": "^4.0.0", "rollup-plugin-license": "^0.6.0", "rollup-plugin-node-resolve": "^3.3.0", "rollup-watch": "^4.3.1", } }
.rollup.es6.js
import path from "path"; import resolve from "rollup-plugin-node-resolve"; // resolve node_modules/index.js to ES6 import commonjs from "rollup-plugin-commonjs"; // convert CommonJS -> ES6 //import buble from "rollup-plugin-buble"; // convert ES6 -> ES5 import eslint from "rollup-plugin-eslint"; // ESLint //import cleanup from "rollup-plugin-cleanup"; // clear comments and empty lines import license from "rollup-plugin-license"; // add License header // --- ES5/ES6/CommonJS/ESModules -> ES6 bundle --- export default { format: "es", entry: "a.js", dest: "bundle.es6.js", plugins: [ resolve({ jsnext: true }), commonjs(), //buble(), // ES6 -> ES5 eslint({ configFile: path.resolve("./.eslintrc") }), //cleanup(), license({ banner: "", //thirdParty: { // output: path.join(__dirname, "dependencies.txt"), // includePrivate: true, // Default is false. //}, }), ], intro: "", outro: "", banner: "", footer: "", }
これらのファイルを用意して、 $ npm run bundle
を実行すると、以下の bundle.es6.js
が生成されます。
bundle.es6.js
class Foo { async fetch() { return new Promise(async(resolve, reject) => { try { const url = `https://localhost`; const text = await(await fetch(url)).text(); await Promise.resolve().then(function () { return b; }); resolve(text); } catch(err) { reject(err); } }); } } (async() => { const foo = new Foo(); const html = await foo.fetch(); alert(html); })(); alert("b.js"); var b = /*#__PURE__*/Object.freeze({ }); export { Foo };