Skip to content

Commit

Permalink
fix(js): adjust .swcrc so that it works with swc/jest and no temp .sw…
Browse files Browse the repository at this point in the history
…crc needed (with migrations) (#9198)

* fix(js): remove hardcoded source-maps and add default value to sourceMaps in swcrc

ISSUES CLOSED: #9187

* fix(js): rename .swcrc to .lib.swcrc (with migrations)

* fix(js): revert jest config js tmpl in jest generator and replace jest config manually in JS generator

* chore(js): update snapshot

Co-authored-by: Chau Tran <ctran@Chaus-MacBook-Pro.local>
  • Loading branch information
nartc and Chau Tran committed Mar 7, 2022
1 parent 6efcfee commit 7d5988b
Show file tree
Hide file tree
Showing 20 changed files with 205 additions and 51 deletions.
6 changes: 6 additions & 0 deletions packages/js/migrations.json
Expand Up @@ -5,6 +5,12 @@
"version": "13.8.5-beta.1",
"description": "Renames @nrwl/js:node to @nrwl/node:node",
"factory": "./src/migrations/update-13-8-5/update-node-executor"
},
"update-swcrc": {
"cli": "nx",
"version": "13.8.5-beta.1",
"description": "Adjust .swcrc to .lib.swcrc",
"factory": "./src/migrations/update-13-8-5/update-swcrc"
}
},
"packageJsonUpdates": {}
Expand Down
4 changes: 1 addition & 3 deletions packages/js/src/executors/swc/swc.impl.ts
Expand Up @@ -12,7 +12,6 @@ import {
NormalizedSwcExecutorOptions,
SwcExecutorOptions,
} from '../../utils/schema';
import { addTempSwcrc } from '../../utils/swc/add-temp-swcrc';
import { compileSwc, compileSwcWatch } from '../../utils/swc/compile-swc';
import { updatePackageJson } from '../../utils/update-package-json';
import { watchForSingleFileChanges } from '../../utils/watch-for-single-file-changes';
Expand Down Expand Up @@ -49,7 +48,7 @@ function normalizeOptions(
srcPath: projectDir,
destPath: relative(join(contextRoot, swcCwd), outputPath),
swcCwd,
swcrcPath: join(projectRoot, '.swcrc'),
swcrcPath: join(contextRoot, projectRoot, '.lib.swcrc'),
};

return {
Expand Down Expand Up @@ -93,7 +92,6 @@ export async function* swcExecutor(
) {
const { sourceRoot, root } = context.workspace.projects[context.projectName];
const options = normalizeOptions(_options, context.root, sourceRoot, root);
options.swcCliOptions.swcrcPath = addTempSwcrc(options);
const { tmpTsConfig, projectRoot, target, dependencies } = checkDependencies(
context,
options.tsConfig
Expand Down
Expand Up @@ -43,7 +43,7 @@ describe('convert to swc', () => {
).toEqual('@nrwl/js:swc');
expect(
tree.exists(
join(readProjectConfiguration(tree, 'tsc-lib').root, '.swcrc')
join(readProjectConfiguration(tree, 'tsc-lib').root, '.lib.swcrc')
)
).toEqual(true);
expect(tree.read('package.json', 'utf-8')).toContain('@swc/core');
Expand Down
4 changes: 3 additions & 1 deletion packages/js/src/generators/convert-to-swc/convert-to-swc.ts
Expand Up @@ -61,7 +61,9 @@ function checkSwcDependencies(
tree: Tree,
projectConfiguration: ProjectConfiguration
) {
const isSwcrcPresent = tree.exists(join(projectConfiguration.root, '.swcrc'));
const isSwcrcPresent = tree.exists(
join(projectConfiguration.root, '.lib.swcrc')
);

const packageJson = readJson(tree, 'package.json');
const hasSwcDependency =
Expand Down
@@ -0,0 +1,17 @@
const fs = require('fs');

// Reading the SWC compilation config and remove the "exclude"
// for the test files to be compiled by SWC
const { exclude: _, ...swcJestConfig } = JSON.parse(
fs.readFileSync(`${__dirname}/.lib.swcrc`, 'utf-8')
);

module.exports = {
displayName: '<%= project %>',
preset: '<%= offsetFromRoot %>jest.preset.js',
transform: {
'^.+\\.[tj]s$': ['@swc/jest', swcJestConfig],
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '<%= offsetFromRoot %>coverage/<%= projectRoot %>'
};
2 changes: 1 addition & 1 deletion packages/js/src/generators/library/library.spec.ts
Expand Up @@ -706,7 +706,7 @@ describe('lib', () => {
compiler: 'swc',
});

expect(tree.exists('libs/my-lib/.swcrc')).toBeTruthy();
expect(tree.exists('libs/my-lib/.lib.swcrc')).toBeTruthy();
});

it('should setup jest project using swc', async () => {
Expand Down
30 changes: 25 additions & 5 deletions packages/js/src/generators/library/library.ts
Expand Up @@ -13,13 +13,13 @@ import {
Tree,
updateJson,
} from '@nrwl/devkit';
import { jestProjectGenerator } from '@nrwl/jest';
import { Linter, lintProjectGenerator } from '@nrwl/linter';
import { runTasksInSerial } from '@nrwl/workspace/src/utilities/run-tasks-in-serial';
import { join } from 'path';
import { LibraryGeneratorSchema } from '../../utils/schema';
import { runTasksInSerial } from '@nrwl/workspace/src/utilities/run-tasks-in-serial';
import { Linter, lintProjectGenerator } from '@nrwl/linter';
import { jestProjectGenerator } from '@nrwl/jest';
import { addSwcDependencies } from '../../utils/swc/add-swc-dependencies';
import { addSwcConfig } from '../../utils/swc/add-swc-config';
import { addSwcDependencies } from '../../utils/swc/add-swc-dependencies';

export async function libraryGenerator(
tree: Tree,
Expand All @@ -37,7 +37,7 @@ export async function projectGenerator(
) {
const options = normalizeOptions(tree, schema, destinationDir);

createFiles(tree, options, filesDir);
createFiles(tree, options, `${filesDir}/lib`);

addProject(tree, options, destinationDir);

Expand All @@ -54,6 +54,9 @@ export async function projectGenerator(
if (options.unitTestRunner === 'jest') {
const jestCallback = await addJest(tree, options);
tasks.push(jestCallback);
if (options.compiler === 'swc') {
replaceJestConfig(tree, options, `${filesDir}/jest-config`);
}
}

if (!options.skipFormat) {
Expand Down Expand Up @@ -222,6 +225,23 @@ async function addJest(
});
}

function replaceJestConfig(
tree: Tree,
options: NormalizedSchema,
filesDir: string
) {
// remove the generated jest config by Jest generator
tree.delete(join(options.projectRoot, 'jest.config.js'));

// replace with JS:SWC specific jest config
generateFiles(tree, filesDir, options.projectRoot, {
tmpl: '',
project: options.name,
offsetFromRoot: offsetFromRoot(options.projectRoot),
projectRoot: options.projectRoot,
});
}

function normalizeOptions(
tree: Tree,
options: LibraryGeneratorSchema,
Expand Down
95 changes: 95 additions & 0 deletions packages/js/src/migrations/update-13-8-5/update-swcrc.spec.ts
@@ -0,0 +1,95 @@
import {
ProjectConfiguration,
readJson,
readProjectConfiguration,
Tree,
updateProjectConfiguration,
} from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { libraryGenerator } from '@nrwl/workspace';
import { defaultExclude } from '../../utils/swc/add-swc-config';
import update from './update-swcrc';

describe('Migration: adjust .swcrc', () => {
let tree: Tree;
let projectConfiguration: ProjectConfiguration;

beforeEach(() => {
tree = createTreeWithEmptyWorkspace();
libraryGenerator(tree, {
name: 'swc',
buildable: true,
linter: 'none',
unitTestRunner: 'none',
});
projectConfiguration = readProjectConfiguration(tree, 'swc');
updateProjectConfiguration(tree, 'swc', {
...projectConfiguration,
targets: {
...projectConfiguration.targets,
build: {
...projectConfiguration.targets['build'],
executor: '@nrwl/js:swc',
},
},
});
// re-read the project configuration
projectConfiguration = readProjectConfiguration(tree, 'swc');
});

it('should rename .swcrc to .lib.swcrc', async () => {
addSwcrc();
await update(tree);

expect(tree.exists('libs/swc/.swcrc')).toEqual(false);
expect(tree.exists('libs/swc/.lib.swcrc')).toEqual(true);
});

it('should assign default exclude if swcrc does not already have exclude', async () => {
addSwcrc();
await update(tree);

expect(readJson(tree, 'libs/swc/.lib.swcrc')['exclude']).toEqual(
defaultExclude
);
});

it('should use swcExclude (deprecated) to assign to exclude', async () => {
const swcExclude = ['./src/**/.*.spec.ts$'];
updateProjectConfiguration(tree, 'swc', {
...projectConfiguration,
targets: {
...projectConfiguration.targets,
build: {
...projectConfiguration.targets['build'],
options: {
...projectConfiguration.targets['build']['options'],
swcExclude,
},
},
},
});

addSwcrc();
await update(tree);

expect(readJson(tree, 'libs/swc/.lib.swcrc')['exclude']).toEqual(
swcExclude
);
});

it('should skip updating "exclude" if swcrc already has "exclude" field', async () => {
addSwcrc(true);
await update(tree);
expect(readJson(tree, 'libs/swc/.lib.swcrc')['exclude']).toEqual([
'./**/.*.spec.ts$',
]);
});

function addSwcrc(withExclude = false) {
tree.write(
'libs/swc/.swcrc',
JSON.stringify(withExclude ? { exclude: ['./**/.*.spec.ts$'] } : {})
);
}
});
39 changes: 39 additions & 0 deletions packages/js/src/migrations/update-13-8-5/update-swcrc.ts
@@ -0,0 +1,39 @@
import {
formatFiles,
getProjects,
readJson,
Tree,
updateJson,
} from '@nrwl/devkit';
import { join } from 'path';
import { defaultExclude } from '../../utils/swc/add-swc-config';

export default async function update(host: Tree) {
const projects = getProjects(host);

for (const config of projects.values()) {
if (config?.targets?.build?.executor !== '@nrwl/js:swc') continue;

const swcrcPath = join(config.root, '.swcrc');
if (!host.exists(swcrcPath)) continue;

// rename
const libSwcrcPath = join(config.root, '.lib.swcrc');
host.rename(swcrcPath, libSwcrcPath);

const swcrcContent = readJson(host, libSwcrcPath);

// skip if swcrc already has "exclude" field
if (swcrcContent['exclude']) continue;

// check swcExclude build options
const exclude =
config?.targets?.build?.options['swcExclude'] || defaultExclude;
updateJson(host, libSwcrcPath, (swcrc) => {
swcrc['exclude'] = exclude;
return swcrc;
});
}

await formatFiles(host);
}
3 changes: 3 additions & 0 deletions packages/js/src/utils/schema.d.ts
Expand Up @@ -51,6 +51,9 @@ export interface NormalizedExecutorOptions extends ExecutorOptions {

export interface SwcExecutorOptions extends ExecutorOptions {
skipTypeCheck?: boolean;
/**
* @deprecated
*/
swcExclude?: string[];
}

Expand Down
17 changes: 13 additions & 4 deletions packages/js/src/utils/swc/add-swc-config.ts
Expand Up @@ -3,6 +3,14 @@
import { Tree } from '@nrwl/devkit';
import { join } from 'path';

export const defaultExclude = [
'./src/**/.*.spec.ts$',
'./**/.*.spec.ts$',
'./src/**/jest-setup.ts$',
'./**/jest-setup.ts$',
'./**/.*.js$',
];

const swcOptionsString = () => `{
"jsc": {
"target": "es2017",
Expand All @@ -23,13 +31,14 @@ const swcOptionsString = () => `{
"type": "commonjs",
"strict": true,
"noInterop": true
}
},
"sourceMaps": true,
"exclude": ${JSON.stringify(defaultExclude)}
}`;

export function addSwcConfig(tree: Tree, projectDir: string) {
const swcrcPath = join(projectDir, '.swcrc');
const isSwcConfigExist = tree.exists(swcrcPath);
if (isSwcConfigExist) return;
const swcrcPath = join(projectDir, '.lib.swcrc');
if (tree.exists(swcrcPath)) return;

tree.write(swcrcPath, swcOptionsString());
}
35 changes: 0 additions & 35 deletions packages/js/src/utils/swc/add-temp-swcrc.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/js/src/utils/swc/compile-swc.ts
Expand Up @@ -10,7 +10,7 @@ function getSwcCmd(
{ swcrcPath, srcPath, destPath }: SwcCliOptions,
watch = false
) {
let swcCmd = `npx swc ${srcPath} -d ${destPath} --source-maps --no-swcrc --config-file=${swcrcPath}`;
let swcCmd = `npx swc ${srcPath} -d ${destPath} --no-swcrc --config-file=${swcrcPath}`;
return watch ? swcCmd.concat(' --watch') : swcCmd;
}

Expand Down

0 comments on commit 7d5988b

Please sign in to comment.