MacでローカルのWebリソースを表示するためにApacheを起動する

## やりたいこと

Macのローカルフォルダに置いたちょっとしたウェブページやスクリプトを、いつでもどのブラウザでも気軽に表示したり動かしたりできるようにしておきたい。

## 方法の検討

* HTMLファイルを直接ブラウザで開く→スクリプトをちゃんと動かせないからだめ
* VSCodeのLive Server→常にVSCodeを起動してないとだめなのは嫌
* VMとかDockerとかでローカルディレクトリをマウントしてWebサーバー起動→そこまでするほどのことじゃないしかえって面倒

最近のmacOSにあらかじめ入っているApacheを使うのがよさそう。

## やること

### Apacheを自動起動するようにする

毎回手動でApacheを起動するのも面倒なので、OS起動時に一緒に動くようにする。
これなら毎度何もしなくても、URLを叩けばいつでもローカルのリソースを表示できる。

自動起動対象になっているかは以下のコマンドで確認する。

```
$ sudo launchctl list | grep httpd
 5029	0	org.apache.httpd
```

このように1行出力されれば、自動起動対象となっているので、このままでよし。
出力がない場合は以下のコマンドで自動起動の対象に設定する。

```
$ sudo launchctl load -w /System/Library/LaunchDaemons/org.apache.httpd.plist
```

OSを再起動してApacheが起動できていればOK。

```
$ ps -ef | grep httpd
    0   134     1   0  8:45AM ??         0:00.84 /usr/sbin/httpd -D FOREGROUND
  502   389   134   0  8:46AM ??         0:00.01 /usr/sbin/httpd -D FOREGROUND
  502   790   134   0  8:47AM ??         0:00.00 /usr/sbin/httpd -D FOREGROUND
  502   792   134   0  8:47AM ??         0:00.00 /usr/sbin/httpd -D FOREGROUND
  502   793   134   0  8:47AM ??         0:00.00 /usr/sbin/httpd -D FOREGROUND
  502  3006  2956   0 12:11PM ttys003    0:00.00 grep httpd

$ sudo apachectl status
Go to http://localhost:80/server-status in the web browser of your choice.
Note that mod_status must be enabled for this to work.
```

なお以降のプロセスでApacheの設定を変更した場合は、以下のコマンドで再起動して設定を反映させる。

```
$ sudo apachectl restart
```

### ユーザー個別のホームディレクトリを準備する

Apacheが起動してる状態で http://localhost にアクセスすると、いちおう 'It works!' の表示は出る。
でもデフォルトでは `/Library/WebServer/Documents/` がドキュメントルートになっていて、ユーザーフォルダを参照することもできず、使いづらい。
このためユーザー個別のホームディレクトリを準備する。

ホームディレクトリは `/Users/username/Sites` とする。
以前のmacOSでの「Web共有」機能のために用意されていたフォルダで、この名前にしておくと何かと便利。
（リソースを全部この配下に置く必要はなく、見たい場所のシンボリックリンクを張ればよい）
最近のmacOSにはそもそもフォルダがないので、作る。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27654/3eea621a-ff1f-814b-d54e-81556448ac5f.png)

Finderで見ると、以前の名残で専用のアイコンで表示される。

### 表示確認用ファイルを準備する

上で作ったホームディレクトリに、JavaScriptファイルとそれを読み込むHTMLファイルを用意する。

```javascript:check.js
export function check() {
    alert('check ok!');
};
```

```html:check.html
<html>
<head>
<script type="module">
    import {check} from './check.js';
    check();
</script>
</head>
<body>
</body>
</html>
```

このHTMLを単にブラウザで開くと、オリジン間リソース共有 (CORS) とみなされて、jsファイルを読み込むことができない。
ブラウザの開発者ツールには以下のようなエラーが出る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27654/21a1199a-3729-1259-29fe-4206115ef895.png)

（なお上記サンプルコードは、 `<script src="check.js">` での読み込みはCORS制約外で実行できてしまうため、importを使っている）

無事Apacheが設定できれば、htmlとjsは同一オリジンとなるため（要は普通に1つのWebサーバーに置いた状態）、このスクリプトが実行できるはず。

### 「ユーザー専用ディレクトリ」モジュールを設定する

上で用意したホームディレクトリを見れるようにするため、Apacheの設定ファイル `/etc/apache2/httpd.conf` で「ユーザー専用ディレクトリ」モジュールを使えるようにする。

まずはモジュールの読み込みをする記述を確認する。
以下が `#` でコメントアウトされていたら、`#`を削除して記述を有効にする。

```
LoadModule userdir_module libexec/apache2/mod_userdir.so
```

次に「ユーザー専用ディレクトリ」設定ファイルを取り込む記述を確認する。
以下が `#` でコメントアウトされていたら、`#`を削除して記述を有効にする。

```
Include /private/etc/apache2/extra/httpd-userdir.conf
```

で、実際に↑のファイルの中身を見る。
だいたいこんな感じになってる。

```httpd-userdir.conf
# Settings for user home directories
# 
# Required module: mod_authz_core, mod_authz_host, mod_userdir

#
# UserDir: The name of the directory that is appended onto a user's home
# directory if a ~user request is received.  Note that you must also set
# the default access control for these directories, as in the example below.
#
UserDir Sites

#
# Control access to UserDir directories.  The following is an example
# for a site where these directories are restricted to read-only.
#
Include /private/etc/apache2/users/*.conf
<IfModule bonjour_module>
       RegisterUserSite customized-users
</IfModule>

```

`UserDir Sites` と書いてあれば、 `/Users/username/Sites` がユーザーのホームディレクトリと認識されて、 http://localhost/~username でアクセスできるよ、とのこと。

また、このあとユーザー個別の設定ファイルを作るのだけど、それを読み込む設定になってるかを確認する。
以下が `#` でコメントアウトされていたら、`#`を削除して記述を有効にする。

```
Include /private/etc/apache2/users/*.conf
```

（なお↑にprivateとあるのは、etcが `/etc -> private/etc` とリンクされてるため）

### ユーザー個別の設定ファイルを設定する

↑の設定にあった通り、個人の設定ファイル `/etc/apache2/users/username.conf` を作成する。
※root権限で作成・編集すること

ファイルの中はこんなかんじ。

```:username.conf
<Directory "/Users/username/Sites/">
	Require all granted
</Directory>
```

これでホームディレクトリへのアクセスが可能になる。
Apacheを再起動して http://localhost/~username/check.html を表示すると、JavaScriptが実行される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27654/7aee8777-064e-021d-7adb-b3a06b30248e.png)


あとはSites配下にリソースを放り込むなり、シンボリックリンクを貼りまくるなり思いのままに。

## 細かい設定

### ドキュメントルートの変更

自分しか使ってないMacでいちいち ~username をURLに入れるのは嫌な場合。
個別の設定ファイルでドキュメントルートを上書きする。

```:username.conf
DocumentRoot "/Users/username/Sites/"
<Directory "/Users/username/Sites/">
	Require all granted
</Directory>
```

Sitesが嫌なら任意の別のディレクトリにすることもできる。

```:username.conf
DocumentRoot "/Users/username/web/"
<Directory "/Users/username/web/">
	Require all granted
</Directory>
```

### Apache実行ユーザーの変更

Apacheの実行ユーザーは _www なので、自分のリソースに閲覧権限がないと（770とか440とか）表示・実行できない場合がある。
（もちろんリソースファイルの権限を変える方法もあるけど）
この場合も個別の設定ファイルでUser/Groupを指定すればよい。

```:username.conf
User username
Group staff
DocumentRoot "/Users/username/web/"
<Directory "/Users/username/web/">
	Require all granted
</Directory>
```

## 参考文献

[macOS に標準インストールされている Apache httpd の自動起動を解除する方法](https://weblabo.oscasierra.net/apache-macos-launchd-unload/)
[オリジン間リソース共有 (CORS)](https://developer.mozilla.org/ja/docs/Web/HTTP/CORS)
[Get Apache, MySQL, PHP and phpMyAdmin working on OSX 10.10 Yosemite](http://coolestguidesontheplanet.com/get-apache-mysql-php-phpmyadmin-working-osx-10-10-yosemite/)