Open allomov opened 1 year ago
Can process
and processAsync
be specified at the same time?
@AkifumiSato I tried to do it, but all my attempts failed. It looks like the easiest way to achieve it is fixing it on jest side, but I do not hear anything from their side (here is the question)
I do not yet know if this can be solved.
I'm working on this as well. The AsyncTransformer
type allows you to specify both process
and processAsync
, but currently I'm not having any luck triggering processAsync
by enabling the async mode through the methods listed here: https://jestjs.io/docs/ecmascript-modules. Running node --experimental-vm-modules node_modules/jest/bin/jest.js
is still triggering the process
method in my transformer.
I'll keep hacking on it for a while, but the documentation on writing transformers is very light.
@AkifumiSato I was able to get this working asynchronously with the following code changes. I tried to keep it as backwards compatible as possible. I did move external
before the options spread, because I needed to clear it on my project. Otherwise, I'd get this error.
Dynamic require of "some-package-name-in-the-file-being-tested" is not supported
I don't know if that is a configuration issue on my end or not, but it was the only way I could get it to work.
// index.ts
import * as esbuild from "esbuild";
import { builtinModules } from "module";
import * as path from "path";
import type { AsyncTransformer, TransformedSource, Transformer } from "@jest/transform";
const pkg = require(path.resolve("package.json"));
const external = [
...builtinModules,
...Object.keys(pkg.dependencies ?? {}),
...Object.keys(pkg.devDependencies ?? {}),
...Object.keys(pkg.peerDependencies ?? {}),
];
function createOptions(options: esbuild.BuildOptions, sourcePath: string): esbuild.BuildOptions {
return {
bundle: true,
external,
minify: false,
outdir: "./dist",
sourcemap: true,
target: "esnext",
write: false,
...options,
entryPoints: [sourcePath],
}
}
function transformSource(outputFiles: esbuild.OutputFile[] | undefined): TransformedSource {
return outputFiles!.reduce((result, outputFile) => {
const key = outputFile.path.includes(".map") ? "map" : "code";
result[key] = Buffer.from(outputFile.contents).toString();
return result;
}, {} as Exclude<TransformedSource, string>);
}
const transformer: Transformer<esbuild.BuildOptions> = {
process(_sourceText, sourcePath, { transformerConfig }) {
const { outputFiles } = esbuild.buildSync(createOptions(transformerConfig, sourcePath));
return transformSource(outputFiles);
},
};
function createAsyncTransformer(plugins?: esbuild.Plugin[]): AsyncTransformer<esbuild.BuildOptions> {
return {
...transformer,
async processAsync(_sourceText, sourcePath, { transformerConfig }) {
const options = { plugins, ...createOptions(transformerConfig, sourcePath) };
const { outputFiles } = await esbuild.build(options);
return transformSource(outputFiles);
},
}
}
module.exports = {
createAsyncTransformer,
default: transformer,
}
You can't specify functions in the jest config transformer config, because it strips them out. I had to create an external file like this. Otherwise, the plugin setup function would get striped, and esbuild would throw an error.
// esbuild-transform.js
import { createAsyncTransformer } from 'esbuild-jest-transform';
const transformer = createAsyncTransformer([
{
name: 'ignore-sass',
setup(build) {
build.onLoad({ filter: /\.scss$/ }, () => ({ contents: '' }));
},
},
]);
export default transformer;
and reference it from my jest config
/** @type { import('@jest/types').Config.InitialOptions } */
module.exports = {
// ...
transform: {
'^.+\\.(js|tsx|ts)$': [
'<rootDir>/esbuild-transform.mjs',
{
external: [],
tsconfig: 'tsconfig.test.json',
},
],
},
// ...
};
I am looking for a solution that will allow me to use
ImportGlobPlugin
. When I try to run the following codeI get an error message
error: Cannot use plugins in synchronous API calls
, which makes sense taking into account that plugins work in async mode. I tried to change the implementation of the Transformer to an AsyncTransformer but got an error from jest telling me that the Transformer should implement theprocess
function, which should be synchronous.Here is how I tried to update it:
and here is an error message that I receive from jest:
Do you have thoughts of how it can be fixed?