是什么导致我的tsx渲染正确没有babel在react应用程序?



最近我尝试使用typescript和webpack制作一个react应用程序,在摆弄了设置之后,我发现我能够运行我的应用程序(在浏览器中显示hello world)而不安装任何我通常会安装的babel安装(babel-loader/core/preset-env)

给更多的上下文,我的大部分文件.tsx .jsx,我使用ES6语法,我意识到我的应用程序无法识别jsx文件,我想是因为我没有安装巴别塔,但这让我想知道为什么.tsx文件能够正常工作时显示在浏览器上,我确实需要安装在webpack.config.js ts-loader和做了一些配置文件设置.tsx作为文件扩展名来解决(webpack.config.js如下所示),但这仍然让我怀疑这是否是我不需要巴别塔的原因。

我想我的主要困惑是,我一直认为babel是需要解释jsx,我知道,tsx是一个不同的文件扩展名类型,但它是不是有点像一个超集的jsx像ts是js?我只是好奇为什么我的react应用程序在我的组件中有类似html的语法,而不安装babel。我也没有在node modules文件夹中找到任何babel安装,所以看起来我使用的库都没有使用babel。

在我的场景中,tsx渲染似乎不需要babel, babel提供的任何功能可能会让我想要使用它吗?我知道babel可以将ES6转换为旧版本的javascript,但我也可以通过配置设置来完成。(我问这个后续问题主要是因为我仍然看到有些人在他们的typescript react应用程序中有它,我也只是在浏览器上做了一个文本显示,所以我不确定如果我没有安装babel,我是否会遇到任何其他问题)

感谢所有能回答我问题的人。

为了提供更多信息,我在

下面有我的应用程序设置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()]
}
};

示例代码:

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')
);

头。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;

包。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"
}
}

与已经注释的基本相同,ts-loader将从tsconfig中将.ts .tsx文件编译为目标版本的javascript。Babel对于typescript项目来说并不是必需的,但是它可以带来一些额外的特性,比如能够针对特定的浏览器版本进行编译,以及一些性能提升,因为它实际上并不进行类型检查。

您可能希望将babel保留在混合中的一个原因是使用@babel/preset-env添加目标浏览器版本所需的填充。Ts-loader显然不会这样做。

使用babel来做与typescript无关的事情,ts-loader也不会做,使用ts-loader来做typescript编译对我来说是有意义的。ts-loader文档甚至指出它可以很好地与babel-loader一起工作。

babel.config.json (注释是无效的json!)

{
"presets": [
[
"@babel/preset-env",
{
"targets": "defaults", // > 0.5%, last 2 versions, Firefox ESR, not dead
"modules": false,
"corejs": "3.29", // keep in sync w/ package.json core-js dependency
"debug": false,
"useBuiltIns": "usage",
"shippedProposals": true
}
],
[
"@babel/preset-react",
{
"useBuiltIns": true
}
]
],
"plugins": []
}

webpack.config.js只是模块配置部分

const config = {
/* ... */
module: {
rules: [
{
test: /.(js|jsx|ts|tsx)$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: true,
// Babel configuration is in babel.config.json
},
},
{
loader: 'ts-loader',
},
],
},
],
},
/* ... */
};

tsconfig.json

{
"compilerOptions": {
"target": "esnext",
"baseUrl": "./",
"paths": {
"@/*": ["src/*"]
},
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"strictNullChecks": true,
"forceConsistentCasingInFileNames": true,
"module": "commonjs",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"experimentalDecorators": true,
"jsx": "react"
},
"include": [
"src",
"tests"
],
"exclude": [
"dist",
"node_modules",
"!node_modules/@types"
]
}

这来自于我试图简化一个现有的项目。我没有审查这3个配置文件中的每个选项,但它们似乎正确地一起工作。