[英]SWC with JavaScript: How to handle CSS imports and how to absolute imports?
Here is a minimal reproducible example.这是一个最小的可重现示例。
We're migrating from Babel to SWC .我们正在从 Babel 迁移到SWC 。 (I asked a question a little while ago. I'm improving on that question's answer.)
(我刚才问了一个问题。我正在改进那个问题的答案。)
We're migrated the command from:我们从以下位置迁移了命令:
"test": "NODE_ENV=test riteway -r @babel/register 'src/**/*.test.js' | tap-nirvana",
to到
"test": "SWC_NODE_PROJECT=./jsconfig.json riteway -r @swc-node/register src/**/*.test.js | tap-nirvana",
where the jsconfig.json
looks like this:其中
jsconfig.json
看起来像这样:
{
"compilerOptions": {
"allowJs": true,
"baseUrl": "./src",
"jsx": "react-jsx"
}
}
If we write try to compile a test for a self-contained component (no absolute imports, no CSS) it works:如果我们尝试为独立组件(没有绝对导入,没有 CSS)编译测试,它会起作用:
import { describe } from 'riteway';
import render from 'riteway/render-component';
function HomePageComponent({ user: { email } }) {
return <p>{email}</p>;
}
describe('home page component', async assert => {
const user = { email: 'foo' };
const $ = render(<HomePageComponent user={user} />);
assert({
given: 'a user',
should: 'render its email',
actual: $('p').text(),
expected: user.email,
});
});
The test compiles fine.测试编译正常。
With Babel we had a .babelrc
like this:使用 Babel,我们有一个像这样的
.babelrc
:
{
"env": {
"test": {
"plugins": [
[
"module-resolver",
{
"root": [
"."
],
"alias": {
"components": "./src/components",
"config": "./src/config",
"features": "./src/features",
"hocs": "./src/hocs",
"hooks": "./src/hooks",
"pages": "./src/pages",
"redux": "./src/redux",
"styles": "./src/styles",
"tests": "./src/tests",
"utils": "./src/utils"
}
}
]
]
}
},
"presets": [
[
"next/babel",
{
"ramda": {}
}
]
],
"plugins": [
["styled-components", { "ssr": true }]
]
}
Where the styles where taken care of by styled-components and the absolute imports where defined via the module-resolver
plugin.其中 styles 由 styled-components 处理,而绝对导入是通过
module-resolver
插件定义的。 (We switched away from styled-components to CSS modules, which is why we import from .module.css
CSS files. Anyways...) (我们从 styled-components 切换到 CSS 模块,这就是我们从
.module.css
CSS 文件导入的原因。无论如何......)
If we write the test how we wanted to write it with their actual imports like this:如果我们编写测试,我们希望如何使用他们的实际导入来编写它,如下所示:
import { describe } from 'riteway';
import render from 'riteway/render-component';
import { createPopulatedUserProfile } from 'user-profile/user-profile-factories';
import HomePageComponent from './home-page-component';
describe('home page component', async assert => {
const user = createPopulatedUserProfile();
const $ = render(<HomePageComponent user={user} />);
assert({
given: 'a user',
should: 'render its email',
actual: $('p').text(),
expected: user.email,
});
});
It fails with:它失败了:
$ SWC_NODE_PROJECT=./jsconfig.json riteway -r @swc-node/register src/features/home/home-page-component.test.js | tap-nirvana
/Users/janhesters/dev/my-project/src/features/home/home.module.css:1
(function (exports, require, module, __filename, __dirname) { .container {
^
SyntaxError: Unexpected token '.'
when we leave in the CSS import in home-page-component.js
, or with:当我们离开
home-page-component.js
中的 CSS 导入时,或者:
$ SWC_NODE_PROJECT=./jsconfig.json riteway -r @swc-node/register src/features/home/home-page-component.test.js | tap-nirvana
node:internal/modules/cjs/loader:936
throw err;
^
Error: Cannot find module 'user-profile/user-profile-factories'
Require stack:
- /Users/janhesters/dev/my-project/src/features/home/home-page-component.test.js
- /Users/janhesters/dev/my-project/node_modules/riteway/bin/riteway
respectively, when we get rid of the CSS import.分别,当我们摆脱 CSS 进口。
How can we help SWC understand CSS (or mock CSS modules) and how can we help it understand absolute imports?我们如何帮助 SWC 理解 CSS(或模拟 CSS 模块)以及我们如何帮助它理解绝对导入?
We already set the baseUrl
in jsconfig.json
...我们已经在
jsconfig.json
baseUrl
styled-components
took care of this.styled-components
会处理这个问题。 You'll need to do the same with SWC..swrc
options for baseUrl
and paths
should do what you want, but that, too, seems to have some issues . baseUrl
和paths
的.swrc
选项应该做你想做的事,但这似乎也有一些问题。 You may have better luck creating issues directly in the @swc-node
GitHub repo, but given the comments there it feels like you might be SOL for a while.直接在
@swc-node
GitHub 存储库中创建问题可能会更好,但鉴于那里的评论,感觉你可能会成为 SOL 一段时间。 Might be faster/easier to rewrite your tests using one of the libraries that Next supports out of the box.使用Next 开箱即用支持的库之一可能会更快/更容易地重写您的测试。
About absolute path关于绝对路径
You already add baseUrl
in the jsconfig.json
file but didn't add the paths, you should modify your config file like mine:您已经在
jsconfig.json
文件中添加了baseUrl
但没有添加路径,您应该像我一样修改您的配置文件:
{
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"@screens": ["./screens"],
"@shared": ["./shared"],
"@shared/*": ["./shared/*"]
},
The paths are the alias
of module-resolver
, and I guess your root
shouldn't be "."
路径是
module-resolver
的alias
,我猜你的root
不应该是"."
, it should be exactly like your jsconfig.json
file, I mean the baseUrl
value. ,它应该与您的
jsconfig.json
文件完全相同,我的意思是baseUrl
值。
"plugins": [
[
"module-resolver",
{
"root": ["./src"],
"extensions": [".ts", ".tsx", ".js", ".jsx", ".json"],
"alias": {
"@screens": "./src/screens",
"@shared": "./src/shared"
}
}
]
],
If you have Webpack, you should have alias
config in your resolve
key off Webpack config object, like mine:如果你有 Webpack,你应该在你的
resolve
键中有alias
配置关闭 Webpack 配置 object,就像我的:
const resolve = {
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
alias: {
'@screens': path.join(__dirname, 'src/screens/'),
'@shared': path.join(__dirname, 'src/shared/'),
},
modules: ['src', 'node_modules'],
descriptionFiles: ['package.json'],
};
About CSS关于CSS
Actually, you are using CSS file as CSS-Modules not like recommended NexJS doc , in docs developer should import CSS like import './styles.css'
and then use it as string
in JSX like <div className="main"
实际上,您使用 CSS 文件作为 CSS-Modules 不像推荐的 NexJS doc ,在文档中开发人员应该像
import './styles.css'
一样导入 CSS ,然后在 JSX 中将其用作string
,如<div className="main"
But但
You are importing it like a module (CSS-Module):您正在像模块(CSS-Module)一样导入它:
// you did it
import styles from './styles.css';
<div className={styles.main}
As you know it is built-in support by this doc , it is supported by NextJS, but SWC cannot understand it.如您所知,它是这个文档的内置支持,NextJS 支持它,但 SWC 无法理解它。 I put in hours to find a way for it, but it seems SWC doesn't support CSS-Module yet.
我花了几个小时来寻找一种方法,但似乎 SWC 还不支持 CSS-Module。 you should create your own plugin for SWC to support CSS-Module.
您应该为 SWC 创建自己的插件以支持 CSS-Module。
I was able to solve all issues without writing any plugins.我能够在不编写任何插件的情况下解决所有问题。 I pushed the solution to my example repo from the question.
我从问题中将解决方案推到了我的示例回购中。
Firstly, use the official SWC project's register .首先,使用官方的 SWC 项目的 register 。 This means, you have to compile your tests like this:
这意味着,您必须像这样编译测试:
"test": "riteway -r @swc/register 'src/**/*.test.js' | tap-nirvana",
You can install it by running:您可以通过运行以下命令来安装它:
yarn add --dev @swc/core @swc/register
We need this version of register, because it takes into account an .swcrc
file, which the other one did not.我们需要这个版本的寄存器,因为它考虑了一个
.swcrc
文件,而另一个没有。
Secondly, you need both "path"
and "baseUrl"
to fix the absolute imports because for some reason SWC doesn't infer all paths with only a "baseUrl"
provided.其次,您需要
"path"
和"baseUrl"
来修复绝对导入,因为出于某种原因,SWC 不会仅提供"baseUrl"
来推断所有路径。 And you need to adapt your .swcrc
to handle React.你需要调整你的
.swcrc
来处理 React。
{
"jsc": {
"baseUrl": "./src",
"paths": {
"*.css": ["utils/identity-object-proxy.js"],
"utils/*": ["utils/*"]
},
"parser": {
"jsx": true,
"syntax": "ecmascript"
},
"transform": {
"react": {
"runtime": "automatic"
}
}
},
"module": {
"type": "commonjs"
}
}
Thirdly, to solve .css
you need to remap all imports to .css
files to an identity object proxy, which you can see in the .swcrc
example above.第三,要解决
.css
,您需要将所有对.css
文件的导入重新映射到身份 object 代理,您可以在上面的.swcrc
示例中看到。 An identity object proxy is an object that, when you reference any property, returns the stringified key that you're trying to reference.身份 object 代理是一个 object,当您引用任何属性时,它会返回您尝试引用的字符串化键。 You can create one yourself like this:
你可以像这样自己创建一个:
const identityObjectProxy = new Proxy(
{},
{
get: function getter(target, key) {
if (key === '__esModule') {
return false;
}
return key;
},
},
);
export default identityObjectProxy;
For the .css
remap to go into effect you need to make all your imports to .css
files absolute imports.要使
.css
重新映射到 go 生效,您需要将所有导入到.css
文件的文件绝对导入。 ( import styles from './styles.module.css
won't work!) (
import styles from './styles.module.css
不会工作!)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.