🎁 Module bundler/📖 Webpack
CRA 없이 TS react 환경 구성
DarrenKwonDev
2020. 9. 28. 03:08
보통 cra를 이용하면 빠르게 ts 기반 react 환경을 만들 수 있습니다.
npx create-react-app [원하는 이름] --template typescript
설치 및 tsconfig.json 구성
직접 webpack 부터 react 환경을 구축해나가봅시다. 우선 최소한 설치해야 할 것들입니다.
Definitely Typed에서 제공하는 @types/react와 @types/react-dom을 설치해야 하는 것을 잊지 맙시다.
"dependencies": {
"@types/react": "^16.9.49",
"@types/react-dom": "^16.9.8",
"dotenv": "^8.2.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"typescript": "^4.0.3"
},
"devDependencies": {
"awesome-typescript-loader": "^5.2.1",
"webpack": "^4.44.2",
"webpack-cli": "^3.3.12"
}
ts 로더에 대해서는 webpack 측에서 ts-loader를 예시로 들었으나 awesome-typescript-loader(atl)가 더 좋은 편이다. atl쪽이 왜 좋냐는 데에 대해서는 github 문서에 적혀 있으니 살펴보자.
github.com/s-panferov/awesome-typescript-loader
tsconfig.json 구성
darrengwon.tistory.com/109?category=867626
tsc --init
{
"compilerOptions": {
"target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
"lib": [
"es5",
"ES2015",
"ES2016",
"ES2017",
"ES2020",
"DOM"
] /* Specify library files to be included in the compilation. */,
"jsx": "react" /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */,
"strict": true /* Enable all strict type-checking options. */,
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
}
}
추가로, dom을 돌릴 root div 하나를 만들고, 빌드된 웹팩 내용물을 script로 돌릴 HTML도 하나 두자.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="root"></div>
<script src="./dist/index.js"></script>
</body>
</html>
webpack 구성
webpack을 구성해봅시다.
이게 참 로더는 그렇다 치는데 devtool에서 뭘 사용할 지 고민이 됩니다. 우선 개발 시 가장 빠른 eval로 고쳐놓긴 했습니다.
require("dotenv").config();
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
const appHtml = path.resolve(__dirname, "public", "index.html");
const appPublic = path.resolve(__dirname, "public");
const webpackEnv = process.env.NODE_ENV;
const PORT = process.env.PORT;
module.exports = (webpackEnv) => {
const isProd = webpackEnv === "production";
const isDev = webpackEnv === "development";
return {
module: webpackEnv,
// webpack의 https://webpack.js.org/configuration/devtool/ 확인 요망
devtool: isProd ? "cheap-module-source-map" : "eval", // 속도를 위해 개발시 eval로 교체, 배포시 가장 가벼운 cheap-module-source-map을 쓸 것인가, hidden-source-map이나 다른 걸 쓸 것인가 모르겠음
resolve: {
extensions: [".tsx", ".ts", ".jsx", ".js"],
},
entry: {
app: "./src/index.tsx",
}, // output [name]에 app으로 들어감
module: {
rules: [
{
oneOf: [
{
test: /\.(ts|tsx)$/,
use: [
"cache-loader",
{
loader: "awesome-typescript-loader", // ts-loader보다 이게 좋더라
options: {
transpileOnly: isDev ? true : false, // 빠른 개발을 위해 개발 시에는 tanspile하지 않도록. prod 환경은 transpile을 항상 하도록
},
},
],
},
{
loader: "file-loader",
exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
options: {
outputPath: "static/media",
name: "static/media/[name].[hash:8].[ext]",
esModule: false,
},
},
],
},
],
},
plugins: [
new HtmlWebpackPlugin({ template: appHtml }), // index.html을 public 폴더로 옮기기
new ForkTsCheckerWebpackPlugin(), // Webpack plugin that runs TypeScript type checker on a separate process.
],
output: {
filename: "[name].js", // 여기서 name은 entry에 정한 이름이 들어감. entry에서 정하지 않으면 그냥 main이 기본값
path: path.join(__dirname, "dist"), // dist 폴더에 넣으세요
publicPath: "/",
},
cache: {
type: isProd ? "filesystem" : "memory", // 개발시 memory, 배포시 filesystem 캐쉬
},
devServer: {
host: "localhost",
port: PORT,
contentBase: appPublic,
open: true, // broswer open
hot: true, // hot-reload 활성화
compress: true,
historyApiFallback: true,
overlay: true,
stats: "errors-only",
after: function (app, server, compiler) {
console.log(`server on : http://localhost:${PORT}`);
},
},
// stats : https://webpack.js.org/configuration/stats/ 참고
// stats: {
// builtAt: false,
// children: false,
// entrypoints: false,
// hash: false,
// modules: false,
// version: false,
// publicPath: true,
// excludeAssets: [/\.(map|txt|html|jpg|png)$/, /\.json$/],
// warningsFilter: [/exceed/, /performance/],
// },
};
};
github.com/Kunune/ts-react-without-cra/blob/master/webpack.config.js