ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Instagram] 프로젝트 설정(2) - Webpack 적용
    Clone Coding/Instagram 2021. 7. 10. 23:00

    [ Webpack ]

    • 모던 JavaScript 어플리케이션을 위한 정적 모듈 번들러
    • JavaScript 모듈을 컴파일할 때 사용
    • Webpack이 어플리케이션을 처리할 때, 내부적으로는 프로젝트에 필요한 모든 모듈을 매핑하고 하나 이상의
      번들을 생성하는 디펜던시 그래프를 만든다.

     

    ※ 디펜던시 그래프(Dependency Graph)

    하나의 파일이 다른 파일에 의존할 때 마다 webpack은 이것을 의존성으로 취급한다.이를 통해 webpack은 이미지 또는 웹 폰트와 같은 비 코드 자산을 가져와 어플리케이션에 대한 종속성으로 제공할 수 있다.

    webpack은 어플리케이션을 처리할 때 커맨드 라인 또는 설정 파일에 정의된 모듈 목록에서 시작한다.엔트리 포인트에서 시작하여 webpack은 어플리케이션에서 필요한 모든 모듈을 포함하는 디펜던시 그래프를 재귀적으로 빌드한 다음, 모든 모듈을 브라우저에 의해 로드 되는 작은 수(보통 하나)의 번들로 묶는다.

     

    - Webpack 적용하는 이유. Why ?

    • 파일 단위의 JavaScript 모듈 관리의 필요성
    • 웹 개발 작업 자동화 도구
    • 웹 어플리케이션의 빠른 로딩 속도와 높은 성능

    - Webpack 핵심 개념

    Entry

    • 파일을 읽어들이기 시작하는 진입점
    • webpack이 내부의 디펜던시 그래프를 생성하기 위해 사용해야 하는 모듈
    • webpack은 엔트리 포인트가 직간접적으로 의존하는 다른 모듈과 라이브러리를 찾는다.
    • 기본값은 ./src/index.js 이지만, webpack 설정에서 entry 속성을 설정하여 다르게 지정할 수 있다.
    // webpack.config.js
    module.exports = {
      entry: './path/to/my/entry/file.js',
    };

     

     

    Output

    • 생성된 번들을 내보낼 위치이 파일의 이름을 지정하는 방법을 webpack에 알려주는 역할
    • 기본 출력 파일의 경우에는 ./dist/main.js로, 생성된 기타 파일의 경우에는 ./dist 폴더로 설정된다.
    • output.filenameoutput.path 속성을 사용하여 webpack에 번들의 이름과 내보낼 위치를 알려준다.

    ※ path module : 파일 경로를 지정하기 위해 사용되는 core Node.js module

    // webpack.config.js
    const path = require('path');
    
    module.exports = {
      entry: './path/to/my/entry/file.js',
      output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'my-first-webpack.bundle.js',
      },
    };

     

     

    Loaders

    • webpack은 기본적으로 JavaScript와 JSON 파일만 이해할 수 있다.
    • Loader를 사용하여 webpack이 다른 유형의 파일을 처리하거나, 그들을 유효한 모듈로 변환하여 어플리케이션에 사용하거나 디펜던시 그래프에 추가한다.
    • 상위 수준에서 Loader는 webpack 설정에 두가지 속성을 가진다.
      • test 속성 : 변환이 필요한 파일을 식별
      • use 속성 : 변환을 수행하는데 사용되는 Loader
    // webpack.config.js
    const path = require('path');
    
    module.exports = {
      output: {
        filename: 'my-first-webpack.bundle.js',
      },
      module: {
        rules: [{ test: /\.txt$/, use: 'raw-loader' }],
      },
    };
    • 위의 설정은 webpack에게 'require() / import 문 내에서 .txt 파일로 확인되는 경로를 발견하면 번들에 추가하기 전에 raw-loader 를 사용하여 변환해' 라는 의미
    • webpack 설정에서 규칙을 정의할 때 module.rules 아래에 정의해야 한다.

     

     

    Plugins

    • Loader는 특정 유형의 모듈을 변환하는데 사용되지만, 플러그인을 활용하여 번들을 최적화하거나, asset을 관리하고 환경 변수 주입 등과 같은 광범위한 작업을 수행
    • 플러그인을 사용하려면
      • require()를 통해 플러그인을 요청
      • plugins 배열에 추가
      • 다른 목적으로 플러그인을 여러번 사용하도록 설정할 수 있으므로 new 연산자를 호출하여 플러그인의 인스턴스를 만들어야 한다.
    // webpack.config.js
    const HtmlWebpackPlugin = require('html-webpack-plugin'); // npm을 통해 설치
    const webpack = require('webpack'); // 내장 plugin에 접근하는 데 사용
    
    module.exports = {
      module: {
        rules: [{ test: /\.txt$/, use: 'raw-loader' }],
      },
      plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })],
    };
    • 위의 예제에서 html-webpack-plugin은 생성된 모든 번들을 자동으로 삽입하여 어플리케이션용 HTML 파일을 생성
    ※ html-webpack-plugin

    HTML 파일이 build 시 자동으로 포함되도록 설정하기 위해 플러그인 적용위 예시에서는 index.html 파일을 자동으로 dist 폴더에 추가한다.

    - package 설치 : npm i -D html-webpack-plugin

     

     

    Mode

    • development, production, none으로 설정하면 webpack에 내장된 환경별 최적화를 활성화 할 수 있다.
    • 기본값은 production
    // webpack.config.js
    module.exports = {
      mode: 'production',
    };

     

     

    Browser Compatibility(브라우저 호환성)

    • webpack은 ES5가 호환되는 모든 브라우저를 지원(IE8 이하는 지원되지 않는다.)
    • webpack은 import() 및 require.ensure() 을 위한 Promise를 요구한다.
    • 구형 브라우저를 지원하려면 이러한 표현식을 사용하기 전에 polyfill을 로드해야 한다.

    - 프로젝트에 Webpack 적용

    • Webpack Package 설치
    npm i -D webpack webpack-cli webpack-dev-server@next

     

    • webpack.config.js 파일 생성 및 설정
      • webpack은 JavaScript 와 JSON 만 해석할 수 있기 때문에 CSS 관련 loader 추가 필요
      • CSS 모듈 설치
        • npm i -D css-loader style-loader

      • SCSS 모듈 설치
        • npm i -D sass sass-loader

      • PostCSS 모듈 설치(Autoprefixer)
        • npm i -D postcss autoprefixer postcss-loader

        • display: flex; display: -webkit-box; display: -ms-flexbox; 와 같이 브라우저마다 값이 다른 CSS 속성의 경우 package.json의 browserslist에 설정된 브라우저에 맞는 속성값을 자동으로 적용

    // webpack.config.js
    const path = require('path');
    const HtmlPlugin = require('html-webpack-plugin');
    
    module.exports = {
      entry: './src/js/index.js',
      output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'index.js',
        clean: true, // 재빌드 시, 필요없는 파일들 제거
      },
      module: {
        rules: [
          {
            test: /\.s?css$/,
            use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'],
          },
        ],
      },
      plugins: [new HtmlPlugin({ template: './src/html/index.html' })],
    };
    // .postcssrc.js
    module.exports = {
      plugins: [require('autoprefixer')],
    };
    
    • package.json 설정
      • npm run dev : 개발서버 실행
      • npm run build : 빌드
      • browsersList : postcss autoprefiexer에서 참고해야 할 브라우저 목록 정의
    // package.json
    {
      "name": "instagram-clone",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "dev": "webpack-dev-server --mode development",
        "build": "webpack --mode production"
      },
      "license": "ISC",
      "devDependencies": {
        "autoprefixer": "^10.3.0",
        "css-loader": "^5.2.6",
        "eslint": "^7.2.0",
        "eslint-config-airbnb-base": "^14.2.1",
        "eslint-plugin-import": "^2.22.1",
        "html-webpack-plugin": "^5.3.2",
        "postcss": "^8.3.5",
        "postcss-loader": "^6.1.1",
        "sass": "^1.35.2",
        "sass-loader": "^12.1.0",
        "style-loader": "^3.0.0",
        "webpack": "^5.44.0",
        "webpack-cli": "^4.7.2",
        "webpack-dev-server": "^4.0.0-beta.3"
      },
      "browserslist": [
        "> 1%",
        "last 2 versions"
      ]
    }

    [ 참고자료 ]

    https://joshua1988.github.io/webpack-guide/

    https://webpack.kr/concepts/

    https://msko.tistory.com/26

    댓글

Designed by Tistory.