繁体   English   中英

SWC with JavaScript:如何处理CSS导入以及如何绝对导入?

[英]SWC with JavaScript: How to handle CSS imports and how to absolute imports?

长话短说

  • 你怎么能告诉SWC去编译React组件中导入的CSS个文件呢?
  • 你如何告诉 SWC 在测试和 React 组件中编译绝对导入?

这是一个最小的可重现示例。


语境

我们正在从 Babel 迁移到SWC (我刚才问了一个问题。我正在改进那个问题的答案。)

我们从以下位置迁移了命令:

"test": "NODE_ENV=test riteway -r @babel/register 'src/**/*.test.js' | tap-nirvana",

"test": "SWC_NODE_PROJECT=./jsconfig.json riteway -r @swc-node/register src/**/*.test.js | tap-nirvana",

其中jsconfig.json看起来像这样:

{
  "compilerOptions": {
    "allowJs": true,
    "baseUrl": "./src",
    "jsx": "react-jsx"
  }
}

如果我们尝试为独立组件(没有绝对导入,没有 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,
  });
});

测试编译正常。

使用 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 }]
  ]
}

其中 styles 由 styled-components 处理,而绝对导入是通过module-resolver插件定义的。 (我们从 styled-components 切换到 CSS 模块,这就是我们从.module.css CSS 文件导入的原因。无论如何......)

如果我们编写测试,我们希望如何使用他们的实际导入来编写它,如下所示:

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,
  });
});

它失败了:

$ 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 '.'

当我们离开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

分别,当我们摆脱 CSS 进口。

我们如何帮助 SWC 理解 CSS(或模拟 CSS 模块)以及我们如何帮助它理解绝对导入?

我们已经在jsconfig.json baseUrl

  1. 我们如何帮助 SWC 理解 CSS(或模拟 CSS 模块)? - SWC 本身不理解 css,Babel 也不理解。 正如你所提到的,当你使用 Babel 时,插件styled-components会处理这个问题。 您需要对 SWC 执行相同的操作。 我找不到执行此操作的现有 SWC 插件,但您可以推出自己的. 显然这是一种痛苦,但这就是使用新工具的成本。
  2. 我们如何帮助 SWC 了解绝对进口? - baseUrlpaths.swrc选项应该做你想做的事,但这似乎也有一些问题

直接在@swc-node GitHub 存储库中创建问题可能会更好,但鉴于那里的评论,感觉你可能会成为 SOL 一段时间。 使用Next 开箱即用支持的库之一可能会更快/更容易地重写您的测试。

关于绝对路径

您已经在jsconfig.json文件中添加了baseUrl但没有添加路径,您应该像我一样修改您的配置文件:

{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@screens": ["./screens"],
      "@shared": ["./shared"],
      "@shared/*": ["./shared/*"]
    },

路径是module-resolveralias ,我猜你的root不应该是"." ,它应该与您的jsconfig.json文件完全相同,我的意思是baseUrl值。

  "plugins": [
    [
      "module-resolver",
      {
        "root": ["./src"],
        "extensions": [".ts", ".tsx", ".js", ".jsx", ".json"],
        "alias": {
          "@screens": "./src/screens",
          "@shared": "./src/shared"
        }
      }
    ]
  ],

如果你有 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'],
};

关于CSS

实际上,您使用 CSS 文件作为 CSS-Modules 不像推荐的 NexJS doc ,在文档中开发人员应该像import './styles.css'一样导入 CSS ,然后在 JSX 中将其用作string ,如<div className="main"

您正在像模块(CSS-Module)一样导入它:

// you did it

import styles from './styles.css';

<div className={styles.main}

如您所知,它是这个文档的内置支持,NextJS 支持它,但 SWC 无法理解它。 我花了几个小时来寻找一种方法,但似乎 SWC 还不支持 CSS-Module。 您应该为 SWC 创建自己的插件以支持 CSS-Module。

我能够在不编写任何插件的情况下解决所有问题。 我从问题中将解决方案推到了我的示例回购中。

首先,使用官方的 SWC 项目的 register 这意味着,您必须像这样编译测试:

"test": "riteway -r @swc/register 'src/**/*.test.js' | tap-nirvana",

您可以通过运行以下命令来安装它:

yarn add --dev @swc/core @swc/register

我们需要这个版本的寄存器,因为它考虑了一个.swcrc文件,而另一个没有。

其次,您需要"path""baseUrl"来修复绝对导入,因为出于某种原因,SWC 不会仅提供"baseUrl"来推断所有路径。 你需要调整你的.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"
  }
}

第三,要解决.css ,您需要将所有对.css文件的导入重新映射到身份 object 代理,您可以在上面的.swcrc示例中看到。 身份 object 代理是一个 object,当您引用任何属性时,它会返回您尝试引用的字符串化键。 你可以像这样自己创建一个:

const identityObjectProxy = new Proxy(
  {},
  {
    get: function getter(target, key) {
      if (key === '__esModule') {
        return false;
      }
      return key;
    },
  },
);

export default identityObjectProxy;

要使.css重新映射到 go 生效,您需要将所有导入到.css文件的文件绝对导入。 import styles from './styles.module.css不会工作!)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM