VSC(Visual Studio Code) Dev Containers環境

Dev Containers

Dev Containers 公式

設定ファイル

設定ファイルは以下の通り。

.devcontainer/devcontainer.json

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node
{
  "name": "Node.js & TypeScript",
  // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
  "image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bullseye",

  "runArgs": ["--name", "vsc_react_base"],

  // Features to add to the dev container. More info: https://containers.dev/features.
  "features": {
    "node": {
      "version": "v20.12.2"
    }
  },
  // Use 'forwardPorts' to make a list of ports inside the container available locally.
  // "forwardPorts": [],

  // Use 'postCreateCommand' to run commands after the container is created.
  "postCreateCommand": "yarn install",

  // Configure tool-specific properties.
  "customizations": {
    // Configure properties specific to VS Code.
    "vscode": {
      "settings": {
        "eslint.nodePath": "./node_modules",
        "editor.defaultFormatter": "esbenp.prettier-vscode",
        "[typescript]": {
            "editor.defaultFormatter": "esbenp.prettier-vscode"
        },
        "editor.formatOnSave": true,
        "editor.codeActionsOnSave": {
            "source.fixAll.eslint": "explicit",
            "source.organizeImports": "explicit"
        },
        "cSpell.files": [
            "!package.json"
        ]
      },
      // Add the IDs of extensions you want installed when the container is created.
      "extensions": [
        "dbaeumer.vscode-eslint",
        // 共通
        "esbenp.prettier-vscode",
        "mhutchie.git-graph",
        "eamodio.gitlens",
        "usernamehw.errorlens",
        "oderwat.indent-rainbow",
        "aaron-bond.better-comments",
        "streetsidesoftware.code-spell-checker"
      ]
    }
  }

  // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
  // "remoteUser": "root"
}
  • 6行目は、Dev Containerのイメージを指定
  • 8行目はDockerのイメージに名前をつけるため
  • 12-14行でnodeのバージョンを指定
  • 26-40行でVSCの設定
  • 42-53行でVSCにインストールするextensionを指定

パッケージ マネージャー

パッケージ マネージャーはYarn 4.0を使う

1
2
3
4
$ yarn set version stable
➤ YN0000: Downloading https://repo.yarnpkg.com/4.2.2/packages/yarnpkg-cli/bin/yarn.js
➤ YN0000: Saving the new release in .yarn/releases/yarn-4.2.2.cjs
➤ YN0000: Done in 0s 181ms
.yarnrc.yml
1
2
3
nodeLinker: node-modules

yarnPath: .yarn/releases/yarn-4.2.2.cjs

Remix

Remix公式

Remix is a full stack web framework that lets you focus on the user interface and work back through web standards to deliver a fast, slick, and resilient user experience. People are gonna love using your stuff.

Remixはフルスタックのウェブフレームワークで、ユーザーインターフェイスに集中し、ウェブスタンダードを通して、高速で、スムーズで、弾力性のあるユーザーエクスペリエンスを提供します。人々はあなたのものを使うのが好きになるでしょう。

Quick Start

Templateを使ってチュートリアルを実行してみる

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
$ yarn create remix --template remix-run/remix/templates/remix
➤ YN0000: · Yarn 4.2.2
➤ YN0000: ┌ Resolution step
➤ YN0085: │ + create-remix@npm:2.9.2, @nodelib/fs.scandir@npm:2.1.5, @nodelib/fs.stat@npm:2.0.5, @nodelib/fs.walk@npm:1.2.8, @remix-run/web-blob@npm:3.1.0, @remix-run/web-fetch@npm:4.4.2, @remix-run/web-file@npm:3.1.0, @remix-run/web-form-data@npm:3.1.0, @remix-run/web-stream@npm:1.1.0, and 189 more.
➤ YN0000: └ Completed in 2s 564ms
➤ YN0000: ┌ Fetch step
➤ YN0013: │ 198 packages were added to the project (+ 30.73 MiB).
➤ YN0000: └ Completed
➤ YN0000: ┌ Link step
➤ YN0000: └ Completed in 0s 501ms
➤ YN0000: · Done in 3s 223ms


 remix   v2.9.2 💿 Let's build a better website...

   dir   Where should we create your new project?
         .

      ◼  Template: Using remix-run/remix/templates/remix...
      ✔  Template copied

 overwrite   Your project directory contains files that will be overwritten by
             this template (you can force with `--overwrite`)

             Files that would be overwritten:
               .eslintrc.cjs
               .gitignore
               app/entry.client.tsx
               app/entry.server.tsx
               app/root.tsx
               and 6 more...

             Do you wish to continue?

             Yes
      ◼  Nice! Git has already been initialized

  deps   Install dependencies with yarn? (recommended)
         ● Yes  ○ No

ブラウザでhttp://localhost:3000にアクセスして表示されればOK

1
2
3
4
 $ yarn start

[remix-serve] http://localhost:3000 (http://172.17.0.2:3000)
GET / 200 - - 14.999 ms

prettierの設定

VSCで保存時にコードフォーマットが実行されるようにする

prettierパッケージインストール

1
$ yarn add -D prettier eslint-config-prettier

.eslintrc.cjsにprettierを追加

.eslintrc.cjs
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/**
 * This is intended to be a basic starting point for linting in your app.
 * It relies on recommended configs out of the box for simplicity, but you can
 * and should modify this configuration to best suit your team's needs.
 */

/** @type {import('eslint').Linter.Config} */
module.exports = {
  root: true,
  parserOptions: {
    ecmaVersion: "latest",
    sourceType: "module",
    ecmaFeatures: {
      jsx: true,
    },
  },
  env: {
    browser: true,
    commonjs: true,
    es6: true,
  },
  ignorePatterns: ["!**/.server", "!**/.client"],

  // Base config
  extends: ["eslint:recommended"],

  overrides: [
    // React
    {
      files: ["**/*.{js,jsx,ts,tsx}"],
      plugins: ["react", "jsx-a11y"],
      extends: [
        "plugin:react/recommended",
        "plugin:react/jsx-runtime",
        "plugin:react-hooks/recommended",
        "plugin:jsx-a11y/recommended",
        "prettier",
      ],
      settings: {
        react: {
          version: "detect",
        },
        formComponents: ["Form"],
        linkComponents: [
          { name: "Link", linkAttribute: "to" },
          { name: "NavLink", linkAttribute: "to" },
        ],
        "import/resolver": {
          typescript: {},
        },
      },
    },

    // Typescript
    {
      files: ["**/*.{ts,tsx}"],
      plugins: ["@typescript-eslint", "import"],
      parser: "@typescript-eslint/parser",
      settings: {
        "import/internal-regex": "^~/",
        "import/resolver": {
          node: {
            extensions: [".ts", ".tsx"],
          },
          typescript: {
            alwaysTryTypes: true,
          },
        },
      },
      extends: [
        "plugin:@typescript-eslint/recommended",
        "prettier",
        "plugin:import/recommended",
        "plugin:import/typescript",
      ],
    },

    // Node
    {
      files: [".eslintrc.cjs"],
      env: {
        node: true,
      },
    },
  ],
};

package.jsonはこんな感じ

package.json
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
{
  "name": "your_project",
  "private": true,
  "sideEffects": false,
  "type": "module",
  "scripts": {
    "build": "remix vite:build",
    "dev": "remix vite:dev",
    "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .",
    "start": "remix-serve ./build/server/index.js",
    "typecheck": "tsc"
  },
  "dependencies": {
    "@remix-run/node": "^2.9.2",
    "@remix-run/react": "^2.9.2",
    "@remix-run/serve": "^2.9.2",
    "isbot": "^5.1.6",
    "react": "^18.3.1",
    "react-dom": "^18.3.1"
  },
  "devDependencies": {
    "@remix-run/dev": "^2.9.2",
    "@types/react": "^18.3.1",
    "@types/react-dom": "^18.3.0",
    "@typescript-eslint/eslint-plugin": "^7.8.0",
    "@typescript-eslint/parser": "^7.8.0",
    "eslint": "^8.57.0",
    "eslint-config-prettier": "^9.1.0",
    "eslint-import-resolver-typescript": "^3.6.1",
    "eslint-plugin-import": "^2.29.1",
    "eslint-plugin-jsx-a11y": "^6.8.0",
    "eslint-plugin-react": "^7.34.1",
    "eslint-plugin-react-hooks": "^4.6.2",
    "prettier": "^3.2.5",
    "typescript": "^5.4.5",
    "vite": "^5.2.11",
    "vite-tsconfig-paths": "^4.3.2"
  },
  "engines": {
    "node": ">=20.0.0"
  },
  "packageManager": "yarn@4.2.2"
}