제어 유지: Webpack 및 React 가이드, Pt. 2

게시 됨: 2022-03-11

이 React-Webpack 튜토리얼의 첫 번째 부분에서 로더를 구성하고 최적화를 수행하는 방법에 대해 논의했습니다. 이제 특정 React/Webpack 구성 사용 사례와 관련된 고급 기술에 대해 알아보겠습니다.

Webpack을 사용한 TypeScript 및 React: Babel 입력

React 프로젝트에서 TypeScript를 사용할 수 있는 방법에는 여러 가지가 있습니다. ts-loader 가 좋은 옵션이지만 많은 라이브러리가 컴파일 시간 최적화를 수행하기 위해 Babel 플러그인을 게시하고 있기 때문에 @babel/preset-typescript 를 사용하여 TypeScript를 변환하는 방법에 중점을 두고 싶습니다. TypeScript 파일을 처리하는 것 외에도 styled-components 또는 react-intl과 같은 다양한 라이브러리에서 제공하는 Babel 플러그인을 사용할 수 있습니다.

가장 먼저 해야 할 일은 TypeScript와 Babel 종속성을 설치하는 것입니다.

 npm install -D typescript @babel/preset-typescript @types/react @types/react-dom

그런 다음 명령줄 프로그램 tsc 를 사용하여 TypeScript 구성 파일을 생성합니다.

 ./node_modules/.bin/tsc -init --lib dom --jsx react --isolatedModules

위의 명령은 브라우저 환경용 코드 작성에 적합한 tsconfig.json 을 생성합니다. --isolatedModules 옵션은 작성한 코드가 @babel/plugin-transform-typescript 와 호환되도록 하는 몇 가지 제약 조건을 적용합니다. 이 옵션은 Babel이 변환할 수 없는 방식으로 코드를 작성할 때 IDE에서 경고하도록 하는 데 유용합니다.

다음으로 새로운 사전 설정을 도입하여 babel.config.js 를 업데이트할 것입니다.

 @@ -6,7 +6,8 @@ module.exports = { modules: false } ], - "@babel/preset-react" + "@babel/preset-react", + "@babel/preset-typescript" ], plugins: [ "@babel/plugin-transform-runtime",

webpack.config.js 에서 .ts 파일 확장자를 활성화합니다.

 @@ -11,7 +11,7 @@ module.exports = function(_env, argv) { return { devtool: isDevelopment && "cheap-module-source-map", - entry: "./src/index.js", + entry: "./src/index.tsx", output: { path: path.resolve(__dirname, "dist"), filename: "assets/js/[name].[contenthash:8].js", @@ -20,7 +20,7 @@ module.exports = function(_env, argv) { module: { rules: [ { - test: /\.jsx?$/, + test: /\.(js|jsx|ts|tsx)$/, exclude: /node_modules/, use: { loader: "babel-loader", @@ -61,6 +61,9 @@ module.exports = function(_env, argv) { } ] }, + resolve: { + extensions: [".js", ".jsx", ".ts", ".tsx"] + }, plugins: [ isProduction && new MiniCssExtractPlugin({

위의 구성은 코드를 트랜스파일할 수 있기에 충분하지만 실제로 유효성을 검사하지는 않습니다. fork-ts-checker-webpack-plugin 사용하여 별도의 병렬 프로세스에서 유형 검사를 수행해야 합니다.

먼저 다음을 설치해야 합니다.

 npm install -D fork-ts-checker-webpack-plugin

그런 다음 webpack.config.jsplugins 섹션에 추가합니다.

 @@ -4,6 +4,7 @@ const HtmlWebpackPlugin = require("html-webpack-plugin"); const webpack = require("webpack"); const TerserWebpackPlugin = require("terser-webpack-plugin"); const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin"); +const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin"); module.exports = function(_env, argv) { const isProduction = argv.mode === "production"; @@ -78,6 +79,9 @@ module.exports = function(_env, argv) { "process.env.NODE_ENV": JSON.stringify( isProduction ? "production" : "development" ) + }), + new ForkTsCheckerWebpackPlugin({ + async: false }) ].filter(Boolean), optimization: {

async: false 를 지정하면 Webpack이 잘못된 코드를 내보내는 것을 방지하고 개발 서버를 실행할 때 오버레이에 컴파일 오류가 표시됩니다.

참고: 관심을 끌고 있는 Babel 매크로에도 관심이 있을 수 있습니다.

CSS, Webpack을 통해 향상

이전 글에서 css-loader 를 사용한 기본적인 스타일 지정을 다루었습니다. 이 구성을 개선할 수 있는 몇 가지 방법이 있습니다.

제안된 구성은 CSS 모듈, Sass 및 PostCSS 기술을 활용합니다. 그것들은 어떤 면에서 서로를 보완하지만 동시에 모두 사용할 필요는 없습니다. 최종 설정에서는 위의 모든 플러그인이 활성화되며 "필요하지 않을 것"이라고 확신하는 경우 일부를 생략하는 것은 사용자의 몫입니다.

CSS 모듈

CSS 모듈은 각 CSS 클래스에 대해 무작위로 고유한 이름을 생성하여 CSS 파일의 전역 범위 문제를 해결합니다. CSS 모듈을 사용하는 JavaScript 파일의 관점에서 원래 클래스 이름과 임의의 클래스 이름 간의 연관은 로더에서 내보낸 객체로 표시됩니다. 우연한 충돌을 거의 불가능하게 만드는 방식으로 CSS 파일에 지정된 클래스를 찾고 사용할 수 있습니다.

CSS 모듈 지원은 이미 css-loader 에 포함되어 있습니다. 이제 CSS 모듈이 사용 중일 때 명시적으로 새 규칙을 추가해야 합니다.

 @@ -33,11 +33,25 @@ module.exports = function(_env, argv) { }, { test: /\.css$/, use: [ isProduction ? MiniCssExtractPlugin.loader : "style-loader", "css-loader" ] }, + { + test: /\.module.css$/, + use: [ + isProduction ? MiniCssExtractPlugin.loader : "style-loader", + { + loader: "css-loader", + options: { + modules: true + } + } + ] + }, { test: /\.(png|jpg|gif)$/i, use: {

이를 통해 .module.css 로 끝나는 모든 파일은 CSS 모듈이 활성화된 상태로 처리됩니다.

포스트 CSS

PostCSS는 CSS 구문을 확장하거나 최적화를 수행하거나 이전 브라우저에 대한 대체를 제공하는 데 사용할 수 있는 방대한 플러그인 라이브러리가 있는 확장 가능한 CSS 처리 프레임워크입니다.

먼저 필요한 종속성을 설치합니다.

 npm install -D postcss-loader postcss-import postcss-preset-env

CSS 구성을 업데이트합니다.

 @@ -47,9 +47,11 @@ module.exports = function(_env, argv) { { loader: "css-loader", options: { - modules: true + modules: true, + importLoaders: 1 } - } + }, + "postcss-loader" ] }, {

다음 플러그인을 사용하여 PostCSS를 구성할 것입니다.

  • postcss-import : PostCSS가 @import 문을 처리할 수 있도록 합니다.
  • postcss-preset-env : 대부분의 브라우저에서 최신 CSS 기능을 지원하기 위해 폴리필을 적용합니다.

postcss.config.js 라는 파일을 만들고 다음으로 채웁니다.

 module.exports = { plugins: { "postcss-import": {}, "postcss-preset-env": {} } };

PostCSS 플러그인 디렉토리에서 유용할 수 있는 다른 확장을 확인하고 구성에 추가할 수 있습니다.

사스/SCSS

Sass는 또 다른 인기 있는 CSS 처리 프레임워크입니다. PostCSS와 달리 Sass는 "배터리 포함"과 함께 제공됩니다. 기본적으로 Sass는 중첩 규칙, 믹스인 및 이전 버전과의 호환성을 위한 다시 작성 규칙에 대한 지원을 제공합니다. PostCSS는 표준 CSS 구문을 유지하는 것을 목표로 하지만 Sass 구문은 CSS 사양과 다를 수 있습니다. 그럼에도 불구하고 Sass는 CSS 작성에 사용하는 것이 더 쉬운 옵션일 수 있는 유비쿼터스 솔루션이지만 요구 사항에 따라 다릅니다.

먼저 필요한 종속성을 설치합니다.

 npm install -D sass-loader node-sass resolve-url-loader

그런 다음 Webpack 구성에 새 로더를 추가합니다.

 @@ -38,6 +38,25 @@ module.exports = function(_env, argv) { "css-loader" ] }, + { + test: /\.s[ac]ss$/, + use: [ + isProduction ? MiniCssExtractPlugin.loader : "style-loader", + { + loader: "css-loader", + options: { + importLoaders: 2 + } + }, + "resolve-url-loader", + { + loader: "sass-loader", + options: { + sourceMap: true + } + } + ] + }, { test: /\.(png|jpg|gif)$/i, use: {

위의 스니펫과 관련된 몇 가지 문제를 사전에 해결했습니다.

  1. @import ed Sass 파일에서 상대 가져오기가 작동하도록 하기 위해 sass-loader loader 다음 resolve-url-loader 를 도입했습니다.

  2. 뒤에 오는 로더를 사용하여 @import -ed 파일을 처리하기 위해 css-loader 에 대해 importLoaders 옵션을 지정했습니다.

위의 구성으로 이전에 설명한 PostCSS 및 CSS 모듈 외에 Sass/SCSS를 사용하여 스타일 작성을 시작할 수 있습니다. 이 모든 옵션을 동시에 활성화할 수 있지만 동일한 프로젝트 내에서 모두 사용할 필요는 없으므로 요구 사항에 가장 적합한 하나의 도구를 선택할 수 있습니다.

웹 작업자

웹 작업자 는 현대 웹의 강력한 개념입니다. 이를 통해 메인 스레드에서 값비싼 계산을 오프로드할 수 있습니다. 웹 작업자는 이벤트 루프 내부의 지능적인 스케줄링으로 최적화할 수 없는 것을 위해 드물게 사용하고 예약해야 합니다. 웹 작업자를 사용하는 것은 긴 동기 작업을 최적화하는 데 좋은 후보입니다.

Webpack을 사용하면 작업자 파일을 출력 디렉토리에 묶고 작업자 클래스를 소비자 파일에 제공하는 worker-loader 와 함께 웹 작업자를 쉽게 사용할 수 있습니다.

먼저 worker-loader 를 설치해야 합니다.

 npm install -D worker-loader

그런 다음 구성 파일에 추가합니다.

 @@ -31,6 +31,10 @@ module.exports = function(_env, argv) { } } }, + { + test: /\.worker\.js$/, + loader: "worker-loader" + }, { test: /\.css$/, use: [

이제 웹 작업자 사용을 시작하기 위해 해야 할 일은 일반 작업자 API를 구현하는 .worker.js 로 끝나는 파일에서 가져온 클래스를 인스턴스화하는 것입니다.

서비스 워커

서비스 작업자는 고급 최적화 기술과 사용자 경험 개선을 가능하게 합니다. 사용자가 네트워크 연결을 끊을 때 앱이 오프라인으로 작동하도록 합니다. 또한 업데이트를 푸시한 후에도 앱이 즉시 로드되도록 합니다.

Webpack을 사용하면 workbox-webpack-plugin 모듈을 사용하여 앱에 대한 서비스 작업자를 쉽게 구성할 수 있습니다. 먼저 다음을 설치해야 합니다.

 npm install -D workbox-webpack-plugin

그런 다음 Webpack 구성의 plugins 섹션에 플러그인을 추가합니다.

 @@ -4,6 +4,7 @@ const HtmlWebpackPlugin = require("html-webpack-plugin"); const webpack = require("webpack"); const TerserWebpackPlugin = require("terser-webpack-plugin"); const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin"); +const WorkboxPlugin = require("workbox-webpack-plugin"); module.exports = function(_env, argv) { const isProduction = argv.mode === "production"; @@ -75,6 +76,11 @@ module.exports = function(_env, argv) { "process.env.NODE_ENV": JSON.stringify( isProduction ? "production" : "development" ) + }), + new WorkboxPlugin.GenerateSW({ + swDest: "service-worker.js", + clientsClaim: true, + skipWaiting: true }) ].filter(Boolean), optimization: {

위의 구성은 다음 옵션을 사용합니다.

  • swDest 는 생성된 작업자 파일의 출력 파일 이름을 지정합니다.
  • clientsClaim 은 등록 직후 페이지를 제어하고 다음 페이지 다시 로드를 기다리는 대신 캐시된 리소스를 제공하기 시작하도록 서비스 워커에 지시합니다.
  • skipWaiting 은 모든 활성 인스턴스가 파괴될 때까지 기다리지 않고 서비스 워커에 대한 업데이트가 즉시 적용되도록 합니다.

후자의 두 옵션이 기본값이 아닌 데는 그만한 이유가 있습니다. 동시에 활성화하면 시간에 민감한 상황에서 결함이 발생할 가능성이 있으므로 구성에서 해당 옵션을 활성화할지 여부를 의식적으로 결정하는 것은 사용자의 몫입니다.

마지막으로 사용자가 앱을 열 때 서비스 워커를 등록해야 합니다.

 @@ -2,3 +2,9 @@ import React from "react"; import ReactDOM from "react-dom"; ReactDOM.render(<h3>React App</h3>, document.getElementById("root")); + +if ("serviceWorker" in navigator) { + window.addEventListener("load", () => { + navigator.serviceWorker.register("/service-worker.js"); + }); +}

서비스 워커는 앱에 오프라인 기능을 추가하는 것 이상을 할 수 있습니다. 서비스 워커 동작을 더 많이 제어해야 하는 경우 InjectManifest 플러그인을 대신 사용할 수 있습니다. 자체 서비스 워커 파일을 작성하여 API 요청에 대한 캐싱을 활성화하고 푸시 알림과 같은 서비스 워커가 활성화한 다른 기능을 사용할 수도 있습니다. 공식 문서의 고급 레시피 섹션에서 Workbox의 기능에 대해 자세히 알아볼 수 있습니다.

고급 React Webpack 구성: 프로젝트에 엣지 부여

Webpack 튜토리얼 시리즈의 두 번째 부분은 가장 일반적인 React 사용 사례를 넘어서 Webpack 구성을 확장하는 데 필요한 지식으로 무장해야 합니다. 이 정보가 유용하고 프로젝트에 특정한 목표를 달성하기 위해 개인화된 구성을 자신 있게 확장할 수 있기를 바랍니다.

항상 그렇듯이 GitHub에서 전체 구성 파일을 찾을 수 있으며 Webpack 문서 및 해당 플러그인 섹션을 참조하여 목표에 적용할 수 있는 더 많은 레시피를 찾을 수 있습니다. 읽어 주셔서 감사합니다!