Webpack 'Cannot GET /' 삽질기 ⛏️

1TBhard·2020년 11월 11일
2

문제점 🧨

typescript, react를 함께 사용할 겸 프로젝트를 진행하여 실습처럼 공부하려고 했었다.
이를 위해 webpack을 설정하던 중 계속 devserver을 통해 해당 프로젝트를 돌려도 Cannot GET / 이라는 텍스트와 함께 돌아가지 않았다.

문제를 해결하다보니 될때도 있고 안될 때도 있고 왔다갔다하는 이상한 상황이 되버렸다.

내 자신이 설정을 잘못 건드는 것이 확실한데 어떠한 것이 확실한지 몰라서 먼저 리스트를 만들어서 해결해 보기로 하였다.

  • tsconfig.json 문제
  • pakage.json(버전 호환)
  • webpack 설정 문제

해결책 🎉

결국 문제는 webpack 설정 이였다.

Cannot GET /로 페이지가 표시되는 이유는 devServer가 참조해야할 index.html 파일이index_bundle.html으로 되어있기 때문이었다.

일단 당시 webpack의 설정은 아래와 같았다.

// webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

module.exports = {
  entry: "./src/index.tsx",
  resolve: {
    extensions: [".ts", ".tsx", ".js"],
  },
  output: {
    path: path.join(__dirname, "public"),
	filename: "main.js",
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        loader: "ts-loader",
      },
    ],
  },

  devServer: {
    contentBase: path.join(__dirname, "public"), // 콘텐츠를 제공할 경로지정
    compress: true, // 모든 항목에 대해 gzip압축 사용
    hot: true,      // HRM(새로 고침 안해도 변경된 모듈 자동으로 적용)
    port: 9000,     // 접속 포트 설정
  },
  
  plugins: [
    new CleanWebpackPlugin({
      cleanAfterEveryBuildPatterns: ["dist", "public"],
    }),
    new HtmlWebpackPlugin({
      template: "./src/index.html",     // 적용될 html 경로
      filename: "./index_bundled.html", // 결과 파일명
      meta: {
        // meta 태그를 추가
        viewport: "width=device-width, initial-scale=1, shrink-to-fit=no",
      },
      hash: true,       // 모든 스크립트, css 파일에 고유한 컴파일 해시 추가하여 캐시를 무효화
      showErrors: true, // 오류 정보가 html에 기록됨
    }),
  ],
};

여기에서 잘못된 것은 htmlWebpackPlugin의 설정중 filenameindex_bundled.html인 것이다.

new HtmlWebpackPlugin({
      template: "./src/index.html",     // 적용될 html 경로
      filename: "./index_bundled.html", // 결과 파일명
  ...
)}

filename은 내보낼 HTML 파일명으로 index_bundled.html로 값을 설정하면 index_bundled.html이 생성된다.

그리고 devserver를 보면 아래와 같다.

  devServer: {
    contentBase: path.join(__dirname, "public"), // 콘텐츠를 제공할 경로지정
    compress: true, // 모든 항목에 대해 gzip압축 사용
    hot: true, // HRM(새로 고침 안해도 변경된 모듈 자동으로 적용)
    port: 9000, // 접속 포트 설정
  },

이는 webpack-dev-server 명령어 실행시 Webpack으로 번들링된 결과물이contentBase에 의해서 루트 폴더를 public으로 저장되게 된다.

따라서, 이 설정으로는 Webpack으로 번들링된 결과물이 index_bundled.html로 나오며 devServer는 public 폴더를 루트로 잡아 스크립트를 참조하게 된다.
그러나, devServer는 기본으로 index.html 파일을 참조하므로 index_bundled.html를 찾지 못해 Cannot GET / 만을 내보내는 것이었다. 💡💡

아래와 같이 HtmlWebpackPlugin 설정에서 filename 부분을 삭제 혹은 filename: ./index.html을 해서 해결할 수 있었다.

new HtmlWebpackPlugin({
    template: "./src/index.html",     // 적용될 html 경로
    filename: "./index.html"
    // 혹은 아예 filename 부분을 삭제하면됨
    ...
)}

💡 webpack-dev-server로 번들링한 결과물이 파일 탐색기에서 보이진 않지만 정상적으로 애플리케이션에 로딩된다.

📖 추가로 Webpack 공식문서를 찾아 htmlWebpackPlugin 을 보니 아래와 같은 내용을 찾을 수 있었다.

구글 번역기(구글 번역기 최고다)를 돌려 위의 사진을 번역하면 아래와 같다.

번들을 제공하려면 HTML 템플릿이 필요하며 일반적으로 index.html 파일입니다. 스크립트 참조가 HTML에 추가되었는지 확인하십시오. webpack-dev-server는 이를 자동으로 삽입하지 않습니다.



느낀점

조금 더 효율적으로 찾을 수 있었던 문제였는데 여러가지를 시도해보고 않되서 중간중간에 딴 짓을 많이 했었다.

문서를 좀 더 찾아볼 걸이라는 생각이 드는 삽질이였다.

profile
기억을 넘어 습관으로

0개의 댓글