CSS 및 ASSETS
이 챕터에서는 웹팩에서 CSS 로더를 설정하고 PostCSS와 SCSS 로더를 추가적으로 설정합니다.
기존 웹팩 4 버전에서 사용하던 url-loader나 file-loader가 웹팩 5 에서는 사용하지 않아도 되기 때문에
이러한 부분을 추가적으로 설명합니다.
- Terminal
npm install css-loader style-loader mini-css-extract-plugin -D
css-loader
- js 파일에서 css 파일을 불러오기 위해 사용하는 패키지
style-loader
- css-loader를 이용해 웹팩 의존성 트리에 추가된 string 값들을 돔에 삽입해주는 패키지
mini-css-extract-plugin
- CSS 파일을 별도 파일로 추출하는 패키지
npm install postcss-loader postcss-preset-env postcss-import -D
postcss-loader
- PostCSS를 사용하여 CSS를 처리하는 패키지
postcss-preset-env
- 최신 CSS를 대부분의 브라우저로 변환할 수 있게해주는 패키지
postcss-import
- @import를 사용할 수 있게 해주는 패키지
npm install sass-loader sass resolve-url-loader -D
sass-loader
- Sass/SCSS 파일을 로드하고 CSS로 컴파일하는 패키지
resolver-url-loader
- 분산된 SCSS 파일 및 리소스들을 SCSS 파일과 함께 배치할 수 있는 패키지
npm install classnames -D
CSS Module을 사용 할 때에는 styles.icon 이런 식으로 객체안에 있는 값을 조회하게 됩니다.
만약 클래스 이름에 - 가 들어가 있다면 다음과 같이 사용 → styles['my-class']
만약에 여러개가 있다면 다음과 같이 작성 → ${styles.one} ${styles.two}
조건부 스타일링을 해야 한다면 → ${styles.one} ${condition ? styles.two : ''}
이러한 점을 개선해 모듈을 바인딩해서 사용하는 classnames 패키지를 사용합니다.
- Asset Modules
애셋 모듈은 로더를 추가로 구성하지 않아도 애셋 파일(폰트, 아이콘 등)을 사용할 수 있도록 해주는 모듈입니다.
webpack 5 이전에는 아래의 로더를 사용하는 것이 일반적이었습니다.
raw-loader: 파일을 문자열로 가져올 때
url-loader: 파일을 data URI 형식으로 번들에 인라인 추가 할 때
file-loader: 파일을 출력 디렉터리로 내보낼 때
이러한 로더를 대체하기 위해서 에셋 모듈에는 4개의 새로운 모듈 유형이 추가되었습니다.
- asset/resource는 별도의 파일을 내보내고 URL을 추출합니다.
이전에는file-loader를 사용하여 처리할 수 있었습니다.
- asset/inline은 애셋의 data URI를 내보냅니다.
이전에는url-loader를 사용하여 처리할 수 있었습니다.
- asset/source는 애셋의 소스 코드를 내보냅니다.
이전에는raw-loader를 사용하여 처리할 수 있었습니다.
- asset은 data URI와 별도의 파일 내보내기 중에서 자동으로 선택합니다.
이전에는 애셋 크기 제한이 있는url-loader를 사용했습니다.
자세한 설명은Asset Modules를 참고해주세요.
전 챕터에서 설정했던 파일들 중 달라지거나 추가된 내용을 설명합니다.
기본적인 설명 방식은 동일합니다.
- SRC
// App.tsx import Layout from 'components/Layout'; const App = () => { return ( <div> <Layout /> </div> ); }; export default App;
declare module '.png'; declare module '.jpg'; declare module '.ico'; declare module '.svg'; declare module '*.scss':
* src/components
프로젝트 세팅을 설명하기위한 샘플 컴포넌트이며, 빌드 후 확인하시고 난 뒤엔 삭제하셔도 무방합니다.
// Layout.tsx import React from 'react'; import scss from './Layout.module.scss'; import classNames from 'classnames'; const cx = classNames.bind(scss); const Layout = () => { return <p className={cx('box')}>REACT WEBPACK BOILER PLATE</p>; }; export default Layout;
// Layout.module.scss .box{ width: 100px; height: 100px; color: red; }
- ROOT
// webpack.config.js const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); module.exports = { entry: path.resolve(__dirname, '..', './src/index'), output: { path: path.resolve(__dirname, '..', './build'), filename: 'bundle.js', }, resolve: { extensions: ['.tsx', '.ts', '.js'], }, module: { rules: [ { test: /\.(ts|js)x?$/, exclude: /node_modules/, use: [ { loader: 'babel-loader', }, ], }, { test: /\.(s[ac]|c)ss$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'resolve-url-loader', 'sass-loader', 'postcss-loader', ], }, { test: /\.(?:ico|gif|png|jpg|jpeg)$/i, type: 'asset/resource', }, { test: /\.(woff(2)?|eot|ttf|otf|svg|)$/, type: 'asset/inline', }, ], }, plugins: [ new HtmlWebpackPlugin({ template: path.resolve(__dirname, '..', './public/index.html'), }), new MiniCssExtractPlugin(), ], stats: 'errors-only', };
// postcss.config.js module.exports = { plugins: [ 'postcss-import', [ 'postcss-preset-env', { browsers: '> 5% in KR, defaults, not IE < 11', autoprefixer: { grid: 'autoplace' }, }, ], ], };