특정 미디어를 구분해 스타일링 하는 CSS 미디어쿼리 구문이 포함된 CSS 파일이, 모바일 또는 데스크톱 사용자 환경에서 모두 읽히는 것은 비 효율적입니다. 모바일 사용자는 모바일 스타일만, 데스크톱 사용자는 데스크톱 스타일만 적용되어야 하지 않을까요?
그렇게 생각한다면 MediaQueryPlugin 플러그인을 사용해보세요. 이 플러그인을 사용하면 작성된 CSS 코드에서 미디어쿼리를 추출해 비동기(Async) 로드 할 수 있도록 만들어 줍니다.
예를 들어 다음과 같은 스타일 코드를 작성했을 때 모바일 환경에서 미디어쿼리 구문은 필요하지 않습니다.
.sentence { color: #2e2d10; }
@media (min-width: 64em) {
.sentence { color: #26cb7c; }
}
.context { font-size: 1.2rem; }
모바일 환경에 최적화 된 스타일 코드는 아래처럼 작성되어야 합니다.
.sentence { color: #2e2d10; }
.context { font-size: 1.2rem; }
반면 데스크톱 환경에서 접속했다면? 다음 코드를 비동기 방식으로 가져오면 효과적일 것입니다.
@media (min-width: 64em) {
.sentence { color: #26cb7c; }
}
패키지 설치 & 로더 구성
npm i media-query-plugin -D
const MediaQueryPlugin = require('media-query-plugin');
module.exports = {
module: {
rules: [
// 1. 로더 설정
{
test: /\.(sa|sc|c)ss$/i,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
MediaQueryPlugin.loader, /* MediaQueryPlugin 로더 설정 */
'postcss-loader',
'sass-loader'
]
}
]
},
plugins: [
// 2. 플러그인 설정
new MediaQueryPlugin({
// 생성 될 파일 이름 [name][query].scss 설정
include: [ 'style' ], // [name]
queries: { '(min-width: 60em)': 'desktop' } // [query]
})
]
}
플러그인에 의해 추출된 CSS를 가져 올 경우(동적 가져오기), Webpack은 동적으로 가져오기를 시도하고 파일이 없으면 오류를 발생시킵니다. 그러므로 Webpack을 실행하기 전에 해당 파일을 손수 만들어야 합니다. (빈 파일, 코드 자동 생성)
import './style.scss';
if (window.innerWidth >= 960) {
import(/* webpackChunkName: 'style-desktop' */ './style-desktop.scss');
}
.sentence { color: #2e2d10; }
@media (min-width: 64em) {
.sentence { color: #26cb7c; }
}
.context { font-size: 1.2rem; }
CSSMQPacker 플러그인
npm i css-mqpacker-webpack-plugin -D
const CSSMQPackerPlugin = require('css-mqpacker-webpack-plugin');
module.exports = {
// ...
optimization: {
minimize: isDevMode ? false : true,
minimizer: [
// 플러그인 인스턴스 생성
new CSSMQPackerPlugin({
sort: true // 정렬 활성화
}),
],
},
}
미디어 쿼리 병합을 테스트 할 간단한 스타일 코드를 준비합니다. 실습 파일(sass
, scss
) 파일을 테스트 해봅니다.
@use 'sass:map';
/* -------------------------------------------------------------------------- */
// 컬러 맵(Map) 변수
$colors: (
light: (
bg: #efefef,
fg: #010101,
shadow: #8f8f8f,
),
dark: (
bg: #111,
fg: #fff,
shadow: #737373,
),
);
// 중단점 맵 변수
$breakpoints: (
sm: 480px,
md: 768px,
lg: 960px,
xl: 1024px,
2xl: 1280px,
3xl: 1440px,
4xl: 1980px,
);
/* -------------------------------------------------------------------------- */
// 중단점 값 가져오기 함수
@function getBreakpoint($keyword) {
@return map.get($breakpoints, $keyword);
}
// 컬러 값 가져오기 함수
@function getColor($color-name, $theme: light) {
$theme: map.get($colors, $theme);
@return map.get($theme, $color-name);
}
/* -------------------------------------------------------------------------- */
// 테마 설정 믹스인
@mixin setTheme($theme) {
$theme: $theme !global;
}
/* -------------------------------------------------------------------------- */
// 기본 테마 변수
$theme: light !default;
참고