Recently I tried to make a react app using typescript and webpack, after playing around with the setup, I found out I was able to run my app (display hello world in the browser) without installing any babel installations that I would normally install (babel-loader/core/preset-env).
To give more context, most of my files were .tsx instead of .jsx, and I'm using ES6 syntax, I am aware that my app wasn't able to identify jsx files and I assume it was because I didn't install babel, but that made me wonder why the .tsx files were able to work properly when displayed on the browser, I did need to install the ts-loader and did some configurations in the webpack.config.js file setting .tsx as one of the file extensions to resolve(webpack.config.js is shown below), but that still made me wonder if that was the reason I didn't need babel.
I guess my main confusion is that I always thought babel was needed to interpret jsx, I know that tsx is a different file extension type, but isn't it kind of like a superset of jsx like ts is to js? I'm just curious why my react app that has HTML-like syntax in my components was able to work without installing babel. I also couldn't find any babel installations in node modules folder so looks like no library I used is using babel under the hood.
In my scenario, seems like babel is not needed for tsx rendering, are there any features that babel provides that might make me want to use it? I know babel can translate ES6 to older version javascript but I can also accomplish that with config settings.(I asked this follow up question mainly because I still see some people have it in their typescript react app, also I only just made a text display on the browser, so I'm not sure if I will run into any other issues if I do not have babel installed)
Thanks to anyone who can answer my question.
To give more info , I have my app settings below
tsconfig.json :
{
"compilerOptions": {
"module": "commonjs",
"jsx": "react",
"watch": true,
"target": "es5",
"lib": ["es6","dom"],
"esModuleInterop": true
}
}
webpack.config.js :
'use strict';
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
entry: './src/index.tsx',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.tsx$/,
exclude: /node_modules/,
use: 'ts-loader'
}
]
},
resolve: {
extensions: ['.ts', '.tsx', '.js']
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html'
})
],
devServer: {
contentBase: path.join(__dirname, 'dist'),
port: 9000
},
optimization: {
minimizer: [new UglifyJsPlugin()]
}
};
sample code :
index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import Header from './Header';
ReactDOM.render(
<h1>
react-typescript
<Header text={'hello world'} />
</h1>,
document.querySelector('#root')
);
Header.tsx :
import React from 'react';
export interface HeaderProps {
text: string;
num?: number;
}
const Header: React.FC<HeaderProps> = ({ text }) => {
return <div>{text}</div>;
};
export default Header;
package.json :
{
"name": "ts-react",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "./node_modules/.bin/webpack",
"build:watch": "./node_modules/.bin/webpack -w",
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack serve --mode development --env development --hot"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"react": "^17.0.1",
"react-dom": "^17.0.1"
},
"devDependencies": {
"@types/node": "^14.14.28",
"@types/react": "^17.0.2",
"@types/react-dom": "^17.0.1",
"html-webpack-plugin": "^5.1.0",
"ts-loader": "^8.0.17",
"typescript": "^4.1.5",
"uglifyjs-webpack-plugin": "^2.2.0",
"webpack": "^5.22.0",
"webpack-cli": "^4.5.0",
"webpack-dev-server": "^3.11.2"
}
}