inflearn - 프론트엔드 개발환경의 이해와 실습 (webpack, babel, eslint..) - 김정환 님
강의를 들으며 기록한 내용이다.
Babel
- 바벨의 배경, 바벨은?
- 브라우저에서도 사용하는 자바스크립트 언어가 조금씩 달라 코드가 일관적이지 못할때가 있음
- 예를 들어, 사파리에서 Promise.prototype.finally 메소드를 사용할 수 없었다
- 크로스 브라우징으로 인한 문제를 해결하기 위해 바벨리 등장함
- ECMAScript2015+, TypeScript, JSX 등 언어도 브라우저에서 동작하게 만들어줌
실습 준비
- 바벨 설치
- npm install @babel/core @babel/cli node_modules/.bin/babel src/app.js
- npx babel src/app.js
Babel 동작
- 바벨 빌드 단계
- 파싱 parsing
- 변환 transforming : 플러그인에서 처리, 플러그인의 세트 = 프리셋
- 출력 printing
- 바벨의 플러그인이 변환을 담당함
실습
- 커스텀 바벨 플러그인
- 커스텀 플러그인을 만들때는 visitor 라는 객체를 반환해야함
- Identifier 메소드가 visitor 객체에 들어 있음
// my-babel-plugin.js 에 작성한다
module.exports = function myBabelPlugin(){
return {
visitor: {
Identifier(path) {
const name = path.node.name;
// 바벨이 만든 AST 노드를 출력한다
console.log('Identifier() name:', name)
// 변환작업: 코드 문자열을 역순으로 반환한다
// path.node.name = name
// .split('')
// .reverse()
// .join('');
}
}
}
}
- npx babel ./src/app.js --plugins './src/my-babel-plugin.js' 실행 결과
Identifier() name: alert
Identifier() name: msg
Identifier() name: window
Identifier() name: alert
Identifier() name: msg
// console.log('test');
const alert = msg => window.alert(msg);
- 위 소스에서 주석을 해제 하면 파싱된 토큰들이 역순으로 배열된다
- npx babel ./src/app.js --plugins './src/my-babel-plugin.js' 실행 결과
Identifier() name: alert
Identifier() name: msg
Identifier() name: window
Identifier() name: alert
Identifier() name: msg
// console.log('test');
const trela = gsm => wodniw.trela(gsm);
- const 를 var 로 변환하는 플러그인을 만들어 보자
// my-babel-plugin.js 에 작성한다
module.exports = function myBabelPlugin(){
return {
visitor: {
VariableDeclaration(path) {
console.log('VariableDeclaration() kind:', path.node.kind);
// const => var 로 변환
if(path.node.kind === 'const'){
path.node.kind = 'var'
}
}
}
}
}
- npx babel ./src/app.js --plugins './src/my-babel-plugin.js' 실행 결과 const > var
VariableDeclaration() kind: const
// console.log('test');
var alert = msg => window.alert(msg);
- babel 플러그인 사용하기
- plugin-transform-block-scoping 을 사용하여 let 등을 var로 변환해보자
- npm install @babel/plugin-transform-block-scoping 실행하여 설치한다
- npx babel ./src/app.js --plugins @babel/plugin-transform-block-scoping 실행 결과
- const > var 변환됨
// console.log('test');
var alert = msg => window.alert(msg);
- plugin-transform-arrow-functions 을 사용하여 arrow function을 변환해보자
- npm install @babel/plugin-transform-arrow-functions 실행하여 설치한다
- npx babel ./src/app.js --plugins @babel/plugin-transform-block-scoping --plugins @babel/plugin-transform-arrow-functions 실행 결과
- arrow functions이 변환됨
// console.log('test');
var alert = function (msg) {
return window.alert(msg);
};
- plugin-transform-strict-mode 를 사용하여 엄격모드로 사용하게 변환하자
- npm install @babel/plugin-transform-strict-mode npx babel ./src/app.js --plugins @babel/plugin-transform-block-scoping --plugins @babel/plugin-transform-arrow-functions --plugins @babel/plugin-transform-strict-mode 실행 결과
"use strict";
// console.log('test');
var alert = function (msg) {
return window.alert(msg);
};
- babel 도 config 파일로 관리하자 프로젝트 루트에 babel.config.js 파일 생성
// 아래 작성
module.exports = {
plugins: [
"@babel/plugin-transform-block-scoping",
"@babel/plugin-transform-strict-mode",
"@babel/plugin-transform-arrow-functions"
]
}
- npm run build 로 빌드 npx babel ./src/app.js 실행 결과
"use strict";
// console.log('test');
var alert = function (msg) {
return window.alert(msg);
};
- 커스텀 프리셋 만들기
- ES6 로 코딩시 플러그인을 일일이 설정하는 것은 불가능하여 프리셋을 만들어 활용함
- src 하위에 my-babel-preset.js 파일 생성
// 아래 작성
module.exports = function myBabelPreset() {
return {
plugins: [
"@babel/plugin-transform-block-scoping",
"@babel/plugin-transform-strict-mode",
"@babel/plugin-transform-arrow-functions"
]
}
}
- babel.config.js 에 아래 작성
module.exports = {
presets: [
'./src/my-babel-preset.js'
]
}
- npx babel ./src/app.js 실행 결과
"use strict";
// console.log('test');
var alert = function (msg) {
return window.alert(msg);
};
- 바벨 제공 프리셋 사용 (실무에서 가장 많이 사용)
- npm i @babel/preset-env 설치
- npx babel ./src/app.js 실행 결과
// const alert = msg => window.alert(msg); 원래 소스가 아래 ES5에 맞게 변환됨
"use strict";
var alert = function alert(msg) {
return window.alert(msg);
};
- 프리셋 옵션 타겟 브라우저 설정 가능
module.exports = {
presets: [
['@babel/preset-env', {
targets: {
chrome: '79'
}
}]
]
}
// npx babel ./src/app.js 실행결과
"use strict";
const alert = msg => window.alert(msg);
- chrome 79에서는 const, arrow function 사용가능하여 babel preset에서 굳이 변환하지 않는다
- https://caniuse.com/?search=const 사이트에서 브라우저에서 지원여부 확인 가능함
- Promise 는 ES5 로 대체될 수 없다
- 대체 방법으로 core.js promise 를 사용한다
- 대체 하지 못한다를 확인 하는 방법은 아래와 같다
// app.js 에 작성
new Promise();
// babel.config.js 에 작성
module.exports = {
presets: [
['@babel/preset-env', {
targets: {
chrome: '79',
ie: '11'
}
}]
]
}
// npx babel ./src/app.js 실행 결과 new Promise()가 변환되지 못함을 확인할 수 있다
"use strict";
new Promise();
// https://caniuse.com/?search=Promise 사이트에서도 IE11 은 Promise를 지원하지 않음을 확인할 수 있다
// babel.config.js 에 수정
module.exports = {
presets: [
['@babel/preset-env', {
targets: {
chrome: '79',
ie: '11'
},
useBuiltIns: 'usage', //'entry', false
corejs: {
version: 2
}
}]
]
}
- ES5에서 Promise 사용되게 변환하는 방법
// babel.config.js 에 작성
module.exports = {
presets: [
['@babel/preset-env', {
targets: {
chrome: '79',
ie: '11'
},
useBuiltIns: 'usage', //'entry', false // 폴리필 사용을 위해 import될 라이브러리(=corejs)를 사용함을 설정
corejs: {
version: 2
}
}]
]
}
// npx babel ./src/app.js 실행 결과 아래와 같이 core-js 가 로드되어 있어야 함
"use strict";
require("core-js/modules/es6.object.to-string.js");
require("core-js/modules/es6.promise.js");
new Promise();
- 바벨을 웹팩으로 통합하기
- 바벨은 웹팩의 로더 형태로 제공됨
- npm i babel-loader 설치하기
// webpack.config.js 에 아래 작성하기
...
module.exports = {
... ,
module:{
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node-modules/
}
]
},
plugins: [
...
]
}
// npm run build 하면 아래의 에러가 나옴
Module not found: Error: Can't resolve 'core-js/modules/es6.object.to-string.js' in '/Users/choise/Downloads/my_gitlab/_mine/basic_babel/src'
// corejs 설치해줘야함
npm i core-js@2
- 다시 npm run build 하면 성공
정리
- 바벨은 일반적인 방식으로 코딩하면서, 다양한 브라우저에서 돌아가는 어플리케이션을 만들기 위한 도구임
- 바벨의 코어는 파싱과 출력만 담당하고 변환작업은 플러그인에서 처리함
- 여러개의 플러그인들을 모아놓은 세트를 프리셋이라고 하는데, env프리셋을 가장 많이 사용함
- 바벨이 변환하지 못하는 코드는 폴리필이라고 부르는 코드조각으로 불러와 결과물에 로딩해서 해결함 (ex. Promise > corejs)
- babel-loader로 웹팩과 함께 사용하면 훨씩 단순하고 자동화된 프론트엔드 개발환경을 갖출 수 있음
- 실습 중 async ~ await 변환 중 에러 해결방법
- webpack이 js코드에 대해 babel loader를 실행하고 babel은 babel.config.js 파일을 보고 변환 작업을 수행
- 변환 수준은 ie 11 에서 돌아가는 코드로 변환할 것임
- corejs로는 async ~ await 변환 불가능하여 regenerator-runtime 패키지가 필요함
- npm i regenerator-runtime 설치하여 사용 필요
실습
- 사스 적용 실습
- 사스 파일 내에 $span 은 사스에서 변수를 나타냄
// $span 예제
.container {
margin-left: $span * 2;
margin-right: $span * 2;
}
- 사스를 변환하기 위한 사스가 있고, 사스를 웹팩에서 사용하기 위한 사스로더가 있음
- npm i sass-loader node-sass 실행
// webpack.config.js 에 아래 작성
module.exports = {
... ,
module: {
rules: [
{
test: /\.(css|scss)$/,
use: [
process.env.NODE_ENV === "production"
? MiniCssExtractPlugin.loader // 프로덕션 환경
: "style-loader", // 개발 환경
"css-loader",
"sass-loader"
]
},
...
]
},
...
};
- npm run build 실행
- open dist/index.html 로 적용여부 확인
'client > web' 카테고리의 다른 글
Webstorm에 Eslint 적용하기(설정) (0) | 2022.03.24 |
---|---|
[기록] lint - ESLint, prettier, husky, ... (0) | 2022.03.16 |
[기록] Webpack 기본과 실습 - loader, plugin, ... (0) | 2022.03.16 |
[react 설치 중 오류] dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.67.dylib (0) | 2021.07.03 |
엔진과 브라우저 (0) | 2018.11.18 |