-
webpack 직접 설정을 위한 기본 개념FrontEnd/JavaScript 2024. 4. 5. 17:22
1. 기본
브라우저는 자바스크립트의 발전 속도를 따라오지 못함.
때문에 es2015에서 표준 모듈 시스템을 내놓았지만 몇 몇 브라우저는 이를 사용하지 못했고, 브라우저에 무관하게 모듈을 사용하고 싶다는 욕구하에 모듈 번들러인 웹팩이 등장했다.
웹팩은 모든 파일을 모듈로 바라보고 이것들을 하나의 파일(혹은 소수)로 합쳐주는 번들러이다.
하나의 시작점인 entry 포인트로부터 의존적인 모듈을 전부 차장내어 output을 만들어낸다.
npm install -D webpack webpack-cli
패지키 매니저를 통해 웹팩과 커맨드라인으로 웹팩을 실행시킬 수 있게 하는 webpack-cli를 설치해준다.
node_modules/.bin/webpack // webpack
위와 같은 명령어를 통해 (같은 동작) 웹팩의 기능들을 사용할 수 있다.
우선 모듈 번들링을 위해 웹팩에서 필요한 필수 옵션은 3가지이다.
--mode : development / product (개발/배포)
--entry : 시작점 경로를 지정하는 옵션
--output: 번들링 결과물이 위치할 경로이다.
webpack --mode development --entry ./src/app.js --output ./dist
개발 모드로 소스 폴더에 있는 app.js를 시작점으로 번들링 결과물은 dist 폴더로 지정한 것이다.
위와 같은 커맨드 명령어를 통해 번들링을 시작 할 수 있지만, 개발자 경험을 살리기 위해 루트 경로에
webpack.config.js 파일을 생성한 후 옵션들을 지정한 뒤 터미널에서 webpack을 입력해주는 것이 좋다.
(터미널에 webpack을 실행하는 것은 webpack --config path를 입력한 것과 같은 것이다. )
// webpack.config.js const path = require("path") module.exports = { mode: "development", entry: { main: "./src/app.js", }, output: { filename: "[name].js", path: path.resolve("./dist"), }, }
번들링을 cli를 통해 실행한 것과 다르게 config를 사용한다면 entry에 여러 개의 시작점을 넣어줄 수 있다.
output.filename 에서의 [name] 은 엔트리에서 정해준 키값이 name으로 지정된다.
결과물은 ./dist/main.js로 나온다는 뜻.
2. 로더
웹팩은 모든 파일을 모듈로 본다는 것은 js 뿐만 아니라 이미지 파일, css 등등 또한 모듈로 인식한다는 뜻이다.
이를 통해 js 파일 안에서 css 스타일링을 직접 가져올 수 있다는 뜻. (리액트나 next.js에서 import "main.css" 와 같은 행위 가능)
위와 같은 기능을 위해 Loader가 존재.
(로더는 ts를 js로 변환해주는 역할도 해줌: ts-loader // awesome-typescript-loader) - 단, 더 확장성이 넓은 바벨(트랜스파일러)을 많이 사용함
로더의 기본 사용법을 보자면 myloader.js 라는 파일을 생성한 후 아래와 같이 코드를 작성해보자.
module.exports = function myloader(content) { console.log("myloader가 동작함") return content }
이것을 webpack.config.js에 등록해주면 번들러 대상인 모듈들은 content로 들어간다.
module: { rules: [{ test: /\.js$/, // .js 확장자로 끝나는 모든 파일 use: [path.resolve('./myloader.js')] // 방금 만든 로더를 적용한다 }], }
myloader.js는 단순하게 content를 리턴하면서 콘솔에 메시지만 띄우지만 content.replace("console.log","alert") 처럼 직접적으로 코드에 대해 수정할 수 도 있다.
자주 사용하는 로더들로는
css 파일을 모듈로 불러와 js에 직접적으로 불러오기 위한 css-loader,style-loader
( css-loader를 통해 css 파일을 js에 입력되도록 하고, 이것을 동적으로 웹페이지 DOM에 적용하기 위해 style-loader를 사용)
모든 파일(이미지 등등)을 모듈로 사용할 file-loader
네트워크 성능을 위해 파일을 직접 사용하는 것이 아닌 url을 사용할 url-loader
가 있다.
위 로더들은 npm install -D을 통해 설치한 후 webpack.config.js에서 적용시켜주면 됨
const path = require('path'); module.exports = { mode: 'development', entry: { main: './src/app.js', }, output: { filename: '[name].js', path: path.resolve('./dist'), }, module: { rules: [ { test: /\.css$/, use: ['style-loader', 'css-loader'], }, { test: /\.(png|jpg|gif|svg)$/, loader: 'file-loader', options: { filename: '[name].[ext]?[hash]', publicPath: './dist', }, }, ], }, };
cf) 2개 이상의 로더를 적용시킬거라면 use 키워드를, 단일 로드라면 loader 키워드를 사용. (use 키워드 사용시 로더 순서 중요함 )
3. 플러그인
로더가 모듈들을 번들링 하는 과정에서 모듈들에 대해 옵션을 붙이는 거라면 플러그인은 번들링 결과물에 대해서 처리하는 것이다.
(번들된 자바스크립트를 난독화 한다거나 특정 텍스트를 추출하는 용도로 사용한다.)
자주 사용되는 플러그인은 5가지이다.
BannerPlugin
-번들링 결과물에 빌드 정보나 커밋 버전 같은 것을 배너(상단)에 주석으로 추가함
DefinePlugin
- 개발/운영 환경에 따라 API 서버 주소가 다를 수 있는데 같은 코드를 두 환경 모두에 호환되게 하기 위해서는 환경 의존적인 정보를 소스가 아닌 곳에서 관리하는 것이 좋음.
new webpack.DefinePlugin({ VERSION: JSON.stringify("v.1.2.3"), PRODUCTION: JSON.stringify(false), MAX_COUNT: JSON.stringify(999), "api.domain": JSON.stringify("http://dev.api.domain.com"), })
// app.js console.log(VERSION) // 'v.1.2.3' console.log(PRODUCTION) // true console.log(MAX_COUNT) // 999 console.log(api.domain) // 'http://dev.api.domain.com'
HtmlWebpackPlugin
- HTML 파일을 후처리하는데 사용됨.
CleanWebpackPlugin
- 파일 모듈과 같이 번들 결과물이 해시 이름으로 아웃풋 될 경우 번들 할 때마다 이전 파일이 덮어지지 않고 남아 있을 수 있다. 이러한 낭비를 없애기 위해 빌드 이전에 결과물을 제거하는 용도로 존재하는 플러그인
MiniCssExtractPlugin
- 번들링 결과물에 css 요소가 너무 많으면 product 환경에서는 js에 부담이 될 수 있음. 때문에 스타일시트 코드만 따로 뽑아서 별도의 css 파일로 만들어 역할에 따라 파일 분리하기 좋다는 점에 착안하여 나온 플러그인. ( 하나의 큰 파일을 내려받는 것보단, 여러 개의 작은 파일을 동시에 다운 )
const MiniCssExtractPlugin = require("mini-css-extract-plugin") module.exports = { plugins: [ process.env.NODE_ENV === "production" ? [new MiniCssExtractPlugin({ filename: `[name].css` })] : [], ], }
'FrontEnd > JavaScript' 카테고리의 다른 글
Security Vulnerability: SSRF(Server-Side Request Forgery in axios) (0) 2024.08.14 babel 직접 설정해보기 (0) 2024.04.06 내가 JSON Viewer를 짠 방식 (1) 2023.11.04 [javascript] Custom event (1) 2023.10.30 [JS] url 다루기 (0) 2023.08.19