Setting up babel/webpack
npm install @babel/core @babel/cli @babel/preset-env --save-dev
바벨은 아무일도 하지 않는다. Transpile을 하는 것은 babel plugins. 어떤게 있을까:
- @babel/plugin-transform-arrow-functions
여러가지 플러그인을 일일히 설치하는 것을 피곤하니까 그걸 한데 묶어 누가 만든 것이 preset이다:
- @babel/preset-env
- @babel/preset-react
- @babel/preset-typescript 등등...
@babel/preset-env를 설치하고 설정하자:
npm install --save-dev @babel/preset-env
.babelrc 파일에서
{
"presets": ["@babel/preset-env"]
}
그런데 @babel/preset-env이 하는 일이 너무 많아서 번들파일이 과도하게 커 질 수 있다. @babel/preset-env
에서 어디까지 브라우저 지원을 할 지 설정할 수 있다.
{
"presets": [
[
"@babel/preset-env",
{
"targets": "last 2 versions, > 1%"
}
]
]
}
위 설정은 각 브라우저의 마지막 두버전과 점유율이 1%를 넘는 브라우저를 지원한다. browserl.ist를 통해 확인할 수 있다.
Webpack
이제 webpack을 설정해보자
npm install --save-dev webpack webpack-cli
Webpack이 번들링을 할 때 babel을 사용하기 위해 babel-loader도 사용한다.
npm install --save-dev babel-loader
이제 webpack.config.js
파일에서 웹펙 설정을 해보자:
const path = require("path")
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "dist/static"),
filename: "bundle.js",
},
module: {
rules: [
{
test: /\.js$/,
include: [path.resolve(__dirname, "src")],
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: [
[
"@babel/preset-env",
{
target: "last 2 versions, > 1%",
},
],
],
},
},
},
],
},
devtool: "source-map",
mode: "development",
}
웹팩은 entry point에서 시작해 의존성이 있는 것들을 한데 모아 합쳐준다. 결과물을 저장하는 경로와 파일명을 정해줄 수 있다.(dist/static/bundle.js
)
Entry point에서 시작해 의존성이 있는 파일들을 읽으면서 확장자에 따라 알맞은 처리를 한다. 위의 설정에서는 ./src/
안에 있는 자바스크립트파일들을 바벨을 이용해 트랜스파일해준다.
다음으로 css를 임포트하려면 어떻게 해야 할까?
npm i -D css-loader sass-loader mini-css-extract-plugin
webpack.config.js
에서
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
module.exports = {
module: {
rules: [
...{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
{
test: /\.s[ac]ss$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "style.css",
}),
],
}
이제 웹팩은 파일을 읽어나가다가 css나 sass를 만나면 정리해서 ./dist/static/style.css
로 저장을 해 준다.
그런데 살다보니까 매번 브라우저를 열고 새로고침을 하는 것이 힘들 때가 있다. 이런 사람을 위해 누군가가 webpack-dev-server
라는 것을 만들어 놨다.
npm i -D webpack-dev-server
module.exports = {
...
devServer: {
contentBase: path.join(__dirname, "./dist"),
publicPath: "/static/",
compress: true,
port: 5500,
hot: true,
},
}
contentBase
에 있는 파일들을 static file로 제공해주고 번들링을 한 결과는 따로 파일로 저장하지 않지만 /static/
에서 제공한다. 예를들면 localhost:5500/static/bundle.js
가 번들된 자바스크립트파일이다.
그런데 html 파일은 어떻게 할까? 이 역시 플러그인을 사용하자
npm i -D html-webpack-plugin html-webpack-harddisk-plugin
const HtmlWebpackPlugin = require("html-webpack-plugin");
const HtmlWebpackHarddiskPlugin = require("html-webpack-harddisk-plugin")
module.exports = {
...
plugin: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "./public/index.html"),
filename: path.resolve(__dirname, "./dist/index.html"),
inject: true, // inject built script in the end of body tag
alwaysWriteToDisk: true,
}),
new HtmlWebpackHarddiskPlugin(),
]
}
이제 웹팩은 ./public/index.html
파일을 여러가지 작업(minify, 헤더에 css 파일 추가, 바디 태그 끝에 번들된 자바스크립트 추가)을 한 후 ./dist/index.html
파일로 저장한다.
그리고 쓰다보니 빌드를 하기 전에 배포파일을 저장하는 폴더를 다 지워주었으면 좋겠다는 생각이 들 수도 있다.
npm i -D clean-webpack-plugin
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
...
plugins: [
new CleanWebpackPlugin({
cleanAfterEveryBuildPatterns: ["dist"],
}),
...
]
}
더불어 package.json
에 스크립트를 만들자:
{
"scripts": {
"build": "webpack --config webpack.config.production.js",
"dev": "webpack-dev-server --open --config webpack.config.dev.js"
}
}
위에는 안썼는데 사실 개발용 설정과 배포용 설정 파일을 나눠놨다. 이것은 숙제 ㅎㅎ
참고문헌
Jest를 사용해보자
Jest는 테스팅 라이브러리이다.
npm i -D jest
package.json
에서
{
"scripts": {
"test": "jest --watch"
}
}
이제 npm run test
를 하면 테스트를 실행시켜준다. --watch
는 파일 변경이 있으면 자동으로 테스트를 다시 하라는 의미. 테스트는 __tests__
폴더 안에 있는 .js
파일이다. 이게 싫으면 그냥 확장자 앞에 .test
또는 .spec
을 붙일 수도 있다. 예를들면 Component.test.js
. 사실 더 자세하고 설정도 할 수 있는데 이건 숙제.
하나 만들어 보자:
tt.js
import "./style.css"
export default function tt() {
return 1
}
테스트 파일은 tt.test.js
import tt from "./tt"
describe("tt", () => {
it("returns 1", () => {
expect(tt()).toBe(1)
})
})
이제 실행시켜보자.
npm run test
어라? 오류가 난다. import "./style.css"
를 어떻게 이해할지 모르기 때문. 테스트할때는 스타일이 필요 없으니 대충 속이자.
jest.config.js
module.exports = {
moduleNameMapper: {
"\\.(css|less|sass|scss)$": "<rootDir>/src/lib/__mocks__/styleMock.js",
},
}
그리고 위의 해당 파일(styleMock.js)는 빈 모듈이다:
module.exports = {}
이러면 jest는 css 파일을 빈 모듈로 착각해 신경쓰지 않고 아무 문제 없이 테스트를 진행한다.
Dom 테스트가 힘들 때
위의 세팅을 다 해놓고 dom을 테스트하려하는데 막막한가? jest는 기본적인 검사함수밖에 주지 않는다. 이를 불편하게 여긴 어떤 사람이 또 패키지를 만들었다.
npm i -D @testing-library/dom
이 패키지는 getByText(dom, "aaa")과 같은 편리한 함수들을 제공해준다. 사용법은 숙제.