Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: custom include paths and esbuild jest config #5

Merged
merged 10 commits into from
Jan 18, 2021
57 changes: 50 additions & 7 deletions packages/craco-esbuild/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,20 @@ module.exports = {
context: { paths },
}) => {
const useTypeScript = fs.existsSync(paths.appTsConfig);
const esbuildLoaderOptions = pluginOptions.esbuildLoaderOptions;

// add includePaths custom option, for including files/components in other folders than src
// Used as in addition to paths.appSrc, optional parameter.
const optionalIncludes = esbuildLoaderOptions && esbuildLoaderOptions.includePaths || [];

// add esbuild-loader
addAfterLoader(webpackConfig, loaderByName("babel-loader"), {
test: /\.(js|mjs|jsx|ts|tsx)$/,
include: paths.appSrc,
include: [paths.appSrc, ...optionalIncludes],
loader: require.resolve("esbuild-loader"),
options:
pluginOptions && pluginOptions.esbuildLoaderOptions
? pluginOptions.esbuildLoaderOptions
esbuildLoaderOptions
? esbuildLoaderOptions
: {
loader: useTypeScript ? "tsx" : "jsx",
target: "es2015",
Expand Down Expand Up @@ -48,11 +53,49 @@ module.exports = {
* To process the js/ts files we replace the babel-loader with the esbuild jest loader
*/
overrideJestConfig: ({ jestConfig }) => {
// TODO add back once https://github.com/aelbore/esbuild-jest/issues/7 is fixed
// // Replace babel transform with esbuild
// const key = Object.keys(jestConfig.transform)[0];
// jestConfig.transform[key] = [require.resolve("esbuild-jest")];
const options = {
loaders: {
'.js': 'jsx',
'.test.js': 'jsx',
'.ts': 'tsx',
'.test.ts': 'tsx'
},
};

// Replace babel transform with esbuild
// babelTransform is first transformer key
/*
transform:
{
'^.+\\.(js|jsx|mjs|cjs|ts|tsx)$': 'node_modules\\react-scripts\\config\\jest\\babelTransform.js',
'^.+\\.css$': 'node_modules\\react-scripts\\config\\jest\\cssTransform.js',
'^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': 'node_modules\\react-scripts\\config\\jest\\fileTransform.js'
}
*/
const babelKey = Object.keys(jestConfig.transform)[0];

// We replace babelTransform and add loaders to esbuild-jest
jestConfig.transform[babelKey] = [require.resolve("esbuild-jest"), options];

// Adds loader to all other transform options (2 in this case: cssTransform and fileTransform)
// Reason for this is esbuild-jest plugin. It considers only loaders or other options from the last transformer
// You can see it for yourself in: /node_modules/esbuild-jest/esbuid-jest.js:21 getOptions method
// also in process method line 32 gives empty loaders, because options is already empty object
Object.keys(jestConfig.transform).forEach(key => {
if (babelKey === key) return; // ebuild-jest transform, already has loader

// Checks if value is array, usually it's not
// Our example is above on 70-72 lines. Usually default is: {"\\.[jt]sx?$": "babel-jest"}
// (https://jestjs.io/docs/en/configuration#transform-objectstring-pathtotransformer--pathtotransformer-object)
// But we have to cover all the cases
if (Array.isArray(jestConfig.transform[key]) && jestConfig.transform[key].length === 1) {
jestConfig.transform[key].push(options)
} else {
jestConfig.transform[key] = [jestConfig.transform[key], options]
}
});

return jestConfig;

},
};