Header 样式根据 tsx 或 jsx 扩展而变化
Header style changes depending on tsx or jsx extension
我在 app.tsx
中有这个简单的函数,它呈现 table。 header 清晰可见(黑底白字)。
import React from 'react';
import { Table, Thead, Tbody, Tr, Th, Td } from "@chakra-ui/react"
export default function App() {
return(
<Table variant="simple" size="sm">
<Thead>
<Tr>
<Th>A</Th>
<Th>B</Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>a</Td>
<Td>b</Td>
</Tr>
</Tbody>
</Table>
)
}
但是,如果我将文件名更改为 app.jsx
,将呈现相同的 table,但带有很难看到的 header:
要复制这个:
git clone https://github.com/somguyth/chakra-ui-header-bug.git
cd chakra-ui-header-bug
npm install
npm run dev
然后打开 localhost:9000
并将 app.jsx
更改为 app.tsx
并观察代码重新编译后 header 颜色如何变化。
header 元素清晰可见时 (app.tsx
):
header 元素不存在时(app.jsx
):
编辑:我能够 sort-of 通过将 <ChakraProvider theme={darkTheme}>
放入 app.jsx
来“修复”它(除了 index.tsx
).检查 header 的元素以查看它被修复的原因,th
标签内的 class 返回到正确的 css-4v3u8n
,而不是不正确的 css-r10se1
.我不知道这意味着什么或如何正确修复它(即如何修复它而不必使用 ChakraProvider
两次)。
我的index.tsx
:
import React from "react";
import ReactDOM from "react-dom";
import { ChakraProvider, extendTheme } from "@chakra-ui/react"
import App from "./app"
const darkTheme = extendTheme({
config: {
useSystemColorMode: false,
initialColorMode: "dark"
}
});
ReactDOM.render(
<ChakraProvider theme={darkTheme}>
<App />
</ChakraProvider>,
document.getElementById("root")
);
我的模块规则在 webpack.config.js
:
module: {
rules: [
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/
},
{
test: /\.m?jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', "@babel/preset-react"]
}
},
resolve: {
fullySpecified: false,
},
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
],
},
和我的 .babel.rc
:
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
}
和我的 package.json
:
{
"name": "test",
"version": "1.0.0",
"description": "",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack serve"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@chakra-ui/icons": "^1.0.14",
"@chakra-ui/react": "^1.6.5",
"@emotion/react": "^11.4.0",
"@emotion/styled": "^11.3.0",
"css-loader": "^5.2.7",
"framer-motion": "^4.1.17",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-table": "^7.7.0",
"typescript": "^4.3.5"
},
"devDependencies": {
"@babel/core": "^7.14.6",
"@babel/preset-env": "^7.14.7",
"@babel/preset-react": "^7.14.5",
"@types/react-dom": "^17.0.9",
"@types/react-table": "^7.7.2",
"babel-loader": "^8.2.2",
"html-webpack-plugin": "^5.3.2",
"ts-loader": "^9.2.3",
"webpack": "^5.45.1",
"webpack-cli": "^4.7.2",
"webpack-dev-server": "^3.11.2"
}
}
这是因为您的包中有两个版本的 @chakra-ui/react
包,一个是 cjs
格式,一个是 esm
格式。在使用 React Context 时,同一个文件的两个副本会创建两个不同的 React Context(相当于在两个不同的文件中调用 React.createContext
),因此一个副本中的 Consumer 无法从另一个版本中的 Provider 获取值。
这可以通过 运行 npx webpack build --mode production --profile --json=stats.json
验证并将 stats.json
文件加载到 Webpack stats analyse tool 中,这可以提供有关您的包的许多内部信息:
(Webpack 统计分析工具显示 @chakra-ui/react
包有两个版本)
重复@chakra-ui/react
包的原因是你的配置让TypeScript转译文件为CommonJS格式,Babel转译文件为ESModule格式,而@chakra-ui/react
的package.json
有一个exports
为不同的导入请求指定不同文件的字段:
// @chakra-ui/react/package.json
"exports": {
".": {
"require": "./dist/cjs/index.js",
"default": "./dist/esm/index.js"
}
}
(Webpack's documentation on package exports,基本上,使用require
会导入一个文件,使用import
会导入另一个文件)
// Output of src/index.tsx just after ts-loader
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var react_1 = __importDefault(require("react"));
var react_dom_1 = __importDefault(require("react-dom"));
var react_2 = require("@chakra-ui/react");
var app_1 = __importDefault(require("./app"));
var darkTheme = react_2.extendTheme({
config: {
useSystemColorMode: false,
initialColorMode: "dark"
}
});
react_dom_1.default.render(react_1.default.createElement(react_2.ChakraProvider, { theme: darkTheme },
react_1.default.createElement(app_1.default, null)), document.getElementById("root"));
// Output of src/app.jsx just after babel-loader
import React from 'react';
import { Table, Thead, Tbody, Tr, Th, Td } from "@chakra-ui/react";
export default function App() {
return /*#__PURE__*/React.createElement(Table, {
variant: "simple",
size: "sm"
}, /*#__PURE__*/React.createElement(Thead, null, /*#__PURE__*/React.createElement(Tr, null, /*#__PURE__*/React.createElement(Th, null, "A"), /*#__PURE__*/React.createElement(Th, null, "B"))), /*#__PURE__*/React.createElement(Tbody, null, /*#__PURE__*/React.createElement(Tr, null, /*#__PURE__*/React.createElement(Td, null, "a"), /*#__PURE__*/React.createElement(Td, null, "b"))));
}
(您可以使用 inspect-loader
调试加载器输出)
要解决此问题,您可以将 tsconfig.json
更改为输出 ESModule:
// tsconfig.json
{
"module": "ESNext",
"moduleResolution": "node"
}
我在 app.tsx
中有这个简单的函数,它呈现 table。 header 清晰可见(黑底白字)。
import React from 'react';
import { Table, Thead, Tbody, Tr, Th, Td } from "@chakra-ui/react"
export default function App() {
return(
<Table variant="simple" size="sm">
<Thead>
<Tr>
<Th>A</Th>
<Th>B</Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>a</Td>
<Td>b</Td>
</Tr>
</Tbody>
</Table>
)
}
但是,如果我将文件名更改为 app.jsx
,将呈现相同的 table,但带有很难看到的 header:
要复制这个:
git clone https://github.com/somguyth/chakra-ui-header-bug.git
cd chakra-ui-header-bug
npm install
npm run dev
然后打开 localhost:9000
并将 app.jsx
更改为 app.tsx
并观察代码重新编译后 header 颜色如何变化。
header 元素清晰可见时 (app.tsx
):
header 元素不存在时(app.jsx
):
编辑:我能够 sort-of 通过将 <ChakraProvider theme={darkTheme}>
放入 app.jsx
来“修复”它(除了 index.tsx
).检查 header 的元素以查看它被修复的原因,th
标签内的 class 返回到正确的 css-4v3u8n
,而不是不正确的 css-r10se1
.我不知道这意味着什么或如何正确修复它(即如何修复它而不必使用 ChakraProvider
两次)。
我的index.tsx
:
import React from "react";
import ReactDOM from "react-dom";
import { ChakraProvider, extendTheme } from "@chakra-ui/react"
import App from "./app"
const darkTheme = extendTheme({
config: {
useSystemColorMode: false,
initialColorMode: "dark"
}
});
ReactDOM.render(
<ChakraProvider theme={darkTheme}>
<App />
</ChakraProvider>,
document.getElementById("root")
);
我的模块规则在 webpack.config.js
:
module: {
rules: [
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/
},
{
test: /\.m?jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', "@babel/preset-react"]
}
},
resolve: {
fullySpecified: false,
},
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
],
},
和我的 .babel.rc
:
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
}
和我的 package.json
:
{
"name": "test",
"version": "1.0.0",
"description": "",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack serve"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@chakra-ui/icons": "^1.0.14",
"@chakra-ui/react": "^1.6.5",
"@emotion/react": "^11.4.0",
"@emotion/styled": "^11.3.0",
"css-loader": "^5.2.7",
"framer-motion": "^4.1.17",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-table": "^7.7.0",
"typescript": "^4.3.5"
},
"devDependencies": {
"@babel/core": "^7.14.6",
"@babel/preset-env": "^7.14.7",
"@babel/preset-react": "^7.14.5",
"@types/react-dom": "^17.0.9",
"@types/react-table": "^7.7.2",
"babel-loader": "^8.2.2",
"html-webpack-plugin": "^5.3.2",
"ts-loader": "^9.2.3",
"webpack": "^5.45.1",
"webpack-cli": "^4.7.2",
"webpack-dev-server": "^3.11.2"
}
}
这是因为您的包中有两个版本的 @chakra-ui/react
包,一个是 cjs
格式,一个是 esm
格式。在使用 React Context 时,同一个文件的两个副本会创建两个不同的 React Context(相当于在两个不同的文件中调用 React.createContext
),因此一个副本中的 Consumer 无法从另一个版本中的 Provider 获取值。
这可以通过 运行 npx webpack build --mode production --profile --json=stats.json
验证并将 stats.json
文件加载到 Webpack stats analyse tool 中,这可以提供有关您的包的许多内部信息:
(Webpack 统计分析工具显示 @chakra-ui/react
包有两个版本)
重复@chakra-ui/react
包的原因是你的配置让TypeScript转译文件为CommonJS格式,Babel转译文件为ESModule格式,而@chakra-ui/react
的package.json
有一个exports
为不同的导入请求指定不同文件的字段:
// @chakra-ui/react/package.json
"exports": {
".": {
"require": "./dist/cjs/index.js",
"default": "./dist/esm/index.js"
}
}
(Webpack's documentation on package exports,基本上,使用require
会导入一个文件,使用import
会导入另一个文件)
// Output of src/index.tsx just after ts-loader
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var react_1 = __importDefault(require("react"));
var react_dom_1 = __importDefault(require("react-dom"));
var react_2 = require("@chakra-ui/react");
var app_1 = __importDefault(require("./app"));
var darkTheme = react_2.extendTheme({
config: {
useSystemColorMode: false,
initialColorMode: "dark"
}
});
react_dom_1.default.render(react_1.default.createElement(react_2.ChakraProvider, { theme: darkTheme },
react_1.default.createElement(app_1.default, null)), document.getElementById("root"));
// Output of src/app.jsx just after babel-loader
import React from 'react';
import { Table, Thead, Tbody, Tr, Th, Td } from "@chakra-ui/react";
export default function App() {
return /*#__PURE__*/React.createElement(Table, {
variant: "simple",
size: "sm"
}, /*#__PURE__*/React.createElement(Thead, null, /*#__PURE__*/React.createElement(Tr, null, /*#__PURE__*/React.createElement(Th, null, "A"), /*#__PURE__*/React.createElement(Th, null, "B"))), /*#__PURE__*/React.createElement(Tbody, null, /*#__PURE__*/React.createElement(Tr, null, /*#__PURE__*/React.createElement(Td, null, "a"), /*#__PURE__*/React.createElement(Td, null, "b"))));
}
(您可以使用 inspect-loader
调试加载器输出)
要解决此问题,您可以将 tsconfig.json
更改为输出 ESModule:
// tsconfig.json
{
"module": "ESNext",
"moduleResolution": "node"
}