LoginSignup
1
0

Next.js & jest & ESM & Vanilla-extractで詰まったところ

Last updated at Posted at 2024-03-07

Next.js & jestのプロジェクトにvanilla-extract & esm形式のライブラリを採用しました。
その際にunit testで引っかかった問題の備忘録です。

環境

Next.js: 14.1.0
jest: 29.1.2
node: 21.4.0
environment: jest-environment-jsdom

esm対応

エラー内容

    ./node_modules/some-library/components/button/index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export { Button } from './button';
                                                                                      ^^^^^^
 
    SyntaxError: Unexpected token 'export'

https://jestjs.io/ja/docs/ecmascript-modules
jestはesmを実験的サポートしているものの、node_modules配下はトランスパイルされないので
transformIgnorePatternsに対象のライブラリ(foo-library)を追加する必要あり。

ただし普通に設定してもnext/jestはその設定を上書きしてしまうので、nextJest後に無理やり置き換える。
また、node_modulesに適用させるためbabelの設定ファイルを.babelrcではなく.babel.config.jsに変更する必要がある。

import nextJest from 'next/jest';

const createJestConfig = nextJest({
  dir: './',
});

/** @type {import('@jest/types').Config.InitialOptions} */
const customJestConfig: Config = {
  // 省略
};

module.exports = async () => ({
  ...(await createJestConfig(customJestConfig)()),
  transformIgnorePatterns: [
    'node_modules/(?!(foo-library)/)',
  ],
});

vanilla-extract対応

エラー内容

   Styles were unable to be assigned to a file. This is generally caused by one of the following:
 
    - You may have created styles outside of a '.css.ts' context
    - You may have incorrect configuration. See https://vanilla-extract.style/documentation/getting-started
 
      at Object.getFileScope (node_modules/@vanilla-extract/css/fileScope/dist/vanilla-extract-css-fileScope.cjs.dev.js:35:11)

https://vanilla-extract.style/documentation/integrations/next/
公式の設定手順を試すも反映されず。

https://vanilla-extract.style/documentation/test-environments/#remove-style-mocking
追加でmoduleNameWrappersからcssへのstyleMock.jsの設定を削除。

ただし、こちらもesm同様にnext/jestに上書きされてしまったので最後に上書き。
また、その際に自プロジェクトのcss(my-css-folder)のみは従来通りのstyleMock.jsを適用するよう設定。

import nextJest from 'next/jest';

const createJestConfig = nextJest({
  dir: './',
});

/** @type {import('@jest/types').Config.InitialOptions} */
const customJestConfig: Config = {
  // 省略
};

module.exports = async () => {
  const config = await createJestConfig(customJestConfig)();

  if (config.moduleNameMapper) {
    const backupModuleNameMapper = config.moduleNameMapper['^.+\\.(css|sass|scss)$'];
    delete config.moduleNameMapper['^.+\\.(css|sass|scss)$'];
    config.moduleNameMapper['my-css-folder/.+\\.css$'] = backupModuleNameMapper;
  }
  config.transform = {
    '\\.css\\.[tj]s$': '@vanilla-extract/jest-transform',
    ...config.transform
  };
  return config;
};

以上で動作は確認できました。
ただ何分強引なやり方なのでもう少しスマートな対応も模索していきたいと思います。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0