この記事は「株式会社オープンストリーム "小ネタ" Advent Calendar 2020」の1日目の記事です。
はじめに
ここ最近のWebページを見るとVueやReactがいろいろなところで導入されてきて「モダンで仮想DOMなフレームワークを触りたい!」と考える方もいるでしょう。
(WebページからVueやReactの雰囲気を感じ取れない場合はWappalyzerでも導入しておきましょう)
この記事ではWindowsにNode.jsをインストールせず、プロジェクトごとにNode.jsのバージョンを指定してほかの環境で再現できるようにDockerを用いてプロジェクトを立ち上げます。
環境
- Windows 10 Home 20H2
- Windows 10 Pro 1909
最低限WSL2が動作する環境が必要です。
WSL(Windows Subsystem for Linux)2の導入
調べると 公式のドキュメント含めて 同様な方法が出ます。私がまとめたものはこちらになります。
次の手順でWSL2のUbuntuからDockerを操作できる環境ができ上がります。
- WSL2を導入する
- Docker Desktop for Windowsを導入する
Windows Terminal向けの設定
Windows Terminalを使いたい場合はWSL2での作業が遅くなる問題を回避するため、Windows Terminalの初期ディレクトリの設定も変えておきます。
Windows Terminalの新規タブを開くボタンの横に選択肢がありますので、その「設定」から settings.json
を開いて、Ubuntuがある profiles
について startingDirectory
の設定を //wsl$/Ubuntu/home/%USERNAME%
にしましょう。
Linuxのパス (/home/
) では受け付けられません。
...
"profiles":
{
"list":
[
{
"guid": "{2c4de342-38b7-51cf-b940-2309a097f518}", // 環境によって違うので触らない
"hidden": false,
"name": "Ubuntu",
"source": "Windows.Terminal.Wsl",
"startingDirectory": "//wsl$/Ubuntu/home/%USERNAME%" // ここを追加する
}
]
},
...
Windows エクスプローラーからのアクセスが面倒?
//wsl$/Ubuntu/home/
となっているようにエクスプローラーからは \\wsl$\Ubuntu\home\
でファイル共有のようにアクセスできます。
そして、このディレクトリをエクスプローラーのクイックアクセスに登録すれば使い勝手がよくなります。
Nuxt/Nextを導入する
Dockerコンテナーの立ち上げを簡単にするため、docker-composeを用います。
docker-compose.yml
を配置する必要がありますが、 create-nuxt-app
, create-next-app
は空のディレクトリしか受け付けないため、別にディレクトリを作成してDockerのVolumeに割り当てる必要があります。
あ、ここの部分はあまりWindows関係ないです
VueユーザーはNuxt
先にDockerfileで create-nuxt-app
をグローバルにインストールするように指示してコンテナーを作らないと、Nuxtのプロジェクト作成に失敗します。
$ docker-compose exec frontend npx create-nuxt-app .
internal/modules/cjs/loader.js:883
throw err;
^
Error: Cannot find module '/root/.npm/_npx/17/lib/node_modules/create-nuxt-app/node_modules/ejs/postinstall.js'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:880:15)
at Function.Module._load (internal/modules/cjs/loader.js:725:27)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
at internal/main/run_main_module.js:17:47 {
code: 'MODULE_NOT_FOUND',
requireStack: []
}
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! ejs@2.7.4 postinstall: `node ./postinstall.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the ejs@2.7.4 postinstall script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /root/.npm/_logs/2020-12-01T02_01_08_277Z-debug.log
Install for [ 'create-nuxt-app@latest' ] failed with code 1
そのため、ファイル構成は次の通りになります。
$ tree
├── Dockerfile
├── docker-compose.yml
├── .dockerignore
└── src <--- ここにNuxtのプロジェクトを作る
docker-compose, Dockerfileの設定内容は次の通りです。
- コンテナーを立ち上げた後、追加でコマンドを実行できるように
tty:true
を追加する - development用のサーバーにアクセスできるようにポートを開く
version: '3'
services:
frontend:
build:
context: ./
dockerfile: Dockerfile
container_name: nuxt-frontend
tty: true
volumes:
- ./src:/app
ports:
- 3000:3000
working_dir: /app
-
create-nuxt-app
をグローバルにインストールする
FROM node:lts
RUN npm install -g create-nuxt-app
また、 volumes
でディレクトリと紐づけている構成になっていますが、すでにプロジェクトができている状態でコンテナーをビルドしようとすると context
で指定しているディレクトリ以下をDockerデーモンにコピーするため時間がかかります。
そのため、 .dockerignore
でプロジェクトのディレクトリを除外しておきます。
src
コンテナーのビルドが伴うため、初回起動時やDockerfile
を変更したときは --build
オプションをつけます。
docker-compose up -d --build frontend
そのあとにコンテナー内でコマンドを実行してプロジェクトを作成します。
引数に .
を選択して、 docker-compose.yml
で指定した working_dir
直下にプロジェクトのファイルが展開されるようにします。
docker-compose exec frontend npx create-nuxt-app .
あとは、 src
ディレクトリをVSCodeなどで開いたりdevelopment用のサーバーを立ち上げたりすることができます。
code src
docker-compose exec frontend yarn dev
そのままではWindowsホストからdevelopment用のサーバーに接続できないため、 nuxt.config.js
にサーバーを 0.0.0.0
で開くように追記します。
設定が正しいと、 docker-compose exec
でも yarn dev
したときにWindowsホストのブラウザが自動的に開きます。
export default {
server: {
port: 3000,
host: '0.0.0.0',
},
プロジェクトにファイルを保存できない場合は後述する対策を試してください。
ReactユーザーはNext
Next.jsのプロジェクトを作る場合は、Node.jsのコンテナーで npx create-next-app
を実行するだけです。事前にコンテナーに仕込むものはありません。
そのため、ファイル構成は次の通りになります。
$ tree
├── docker-compose.yml
└── src <--- ここにNextのプロジェクトを作る
version: '3'
services:
frontend:
image: node:lts
container_name: next-frontend
tty: true
volumes:
- ./src:/app
ports:
- 3000:3000
working_dir: /app
docker-compose でコンテナーを立ち上げてから、コマンドを実行してプロジェクトを作成します。
引数に .
を選択して、 docker-compose.yml
で指定した working_dir
直下にプロジェクトのファイルが展開されるようにします。
docker-compose up -d frontend
docker-compose exec frontend npx create-next-app .
あとは、 src
ディレクトリをVSCodeなどで開いたりdevelopment用のサーバーを立ち上げたりすることができます。
こちらは特に設定変更しなくてもdevelopment用のサーバーに接続できます。
code src
docker-compose exec frontend yarn dev
プロジェクトにファイルを保存できない場合は後述する対策を試してください。
罠1: Windowsファイルシステムではフロントエンドのコンパイルが遅い
Windows Terminalの環境構築例で startingDirectory
の設定を \\wsl$/Ubuntu/home/%USERNAME%
にすべきとありますが、その理由がこちらになります。
デフォルトのままUbuntuのタブを開くとWindowsファイルシステムがカレントディレクトリになります。 /mnt/c/
になっているやつですね。
WSL2のUbuntuからアクセスすると厄介で、アクセスが非常に遅くなります。 "WSL2 slow" で検索するとさんざん報告されています。
そのため、WSL上で作業する場合はLinuxのファイルシステム (/mnt/c
のようにWindowsのドライブレターが含まれない)に移動しましょう。
試しに Nuxt.js製の簡単なポートフォリオ のプロジェクトを yarn install
して yarn generate
で静的ファイルにビルドするまでの時間を確かめてみましょう。
$ /usr/bin/time -p yarn install
Done in 33.09s.
real 33.50
user 26.22
sys 21.91
$ /usr/bin/time -p yarn generate
Done in 7.67s.
real 7.92
user 14.26
sys 0.60
$ /usr/bin/time -p yarn install
Done in 304.11s.
real 304.39
user 71.74
sys 117.38
$ /usr/bin/time -p yarn generate
Done in 158.66s.
real 158.95
user 33.10
sys 11.48
Windowsファイルシステムで作業してしまうと驚きの遅さ & PCのファンが思いっきり回ります。
処理中にAdvent Calendarの記事だって書けます。
罠2: プロジェクト作成後に権限が引っかかってファイルの編集できない
こちらはUbuntu(Linux)でDockerを動かした環境での問題になります。
create-nuxt-app
などで立ち上げたプロジェクトを編集しようとすると権限の問題で保存に失敗する問題です。
Failed to save 'nuxt.config.js': Unable to write file 'vscode-remote://wsl+ubuntu/home/yoshida-m/frontend/src/nuxt.config.js' (NoPermissions (FileSystemError): Error: EACCES: permission denied, open '/home/yoshida-m/frontend/src/nuxt.config.js')
これはDockerコンテナーからホストのディレクトリに紐づけているボリュームに対して書き込みをするとrootユーザーの所有権で作成されるためです。
いったんプロジェクトを立ち上げた後、WSL2で使っているグループ名とユーザー名を控えてから chown
でプロジェクトのディレクトリに対して一括で設定変更すると解決します。
$ id
uid=1000(yoshida-m) gid=1000(yoshida-m) groups=1000(yoshida-m),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),117(netdev),1001(docker)
sudo chown -R yoshida-m:yoshida-m src
このほかに何かいい方法がないか探っています。
参考
Windows10 WSL2にLinux居城を爆誕させる - Qiita
https://qiita.com/v2okimochi/items/f53edcf79a4b71f519b1#%E9%96%8B%E7%99%BA%E7%94%A8%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%81%AFwsl%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E5%86%85%E3%81%AB%E3%81%97%E3%81%A6%E3%81%8A%E3%81%8F
wsl2が異常に遅くてホットリロードも効かないとき - Tamaosa
https://www.tamaosa.com/2020/wsl2/