What is causing my tsx to render properly without babel in react app?

Viewed 684

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"
    }
}
1 Answers

Pretty much the same as was already commented, ts-loader is going to compile your .ts .tsx files into targeted versions of javascript from your tsconfig. Babel isn't necessary for typescript projects, but can come with some additional features like being able to transpile for specific browser versions, as well as some performance gains because it doesn't actually type check.

Related