Skip to content

Commit

Permalink
feat(js): inline non-buildable libs for tsc and swc
Browse files Browse the repository at this point in the history
  • Loading branch information
Chau Tran committed Sep 28, 2022
1 parent 09cfbf0 commit 1b623c1
Show file tree
Hide file tree
Showing 12 changed files with 448 additions and 16 deletions.
24 changes: 24 additions & 0 deletions docs/generated/packages/js.json
Expand Up @@ -314,6 +314,18 @@
"description": "When `updateBuildableProjectDepsInPackageJson` is `true`, this adds dependencies to either `peerDependencies` or `dependencies`.",
"enum": ["dependencies", "peerDependencies"],
"default": "peerDependencies"
},
"external": {
"type": "string",
"description": "A list projects to be treated as external.",
"enum": ["all", "none"],
"default": "all"
},
"externalBuildTargets": {
"type": "array",
"items": { "type": "string" },
"description": "List of target names that annotate a build target for a project",
"default": ["build"]
}
},
"required": ["main", "outputPath", "tsConfig"],
Expand Down Expand Up @@ -472,6 +484,18 @@
"description": "When `updateBuildableProjectDepsInPackageJson` is `true`, this adds dependencies to either `peerDependencies` or `dependencies`.",
"enum": ["dependencies", "peerDependencies"],
"default": "peerDependencies"
},
"external": {
"type": "string",
"description": "A list projects to be treated as external.",
"enum": ["all", "none"],
"default": "all"
},
"externalBuildTargets": {
"type": "array",
"items": { "type": "string" },
"description": "List of target names that annotate a build target for a project",
"default": ["build"]
}
},
"required": ["main", "outputPath", "tsConfig"],
Expand Down
74 changes: 74 additions & 0 deletions e2e/js/src/js.test.ts
Expand Up @@ -303,6 +303,80 @@ export function ${lib}Wildcard() {
);
}, 120000);

it('should inline non-buildable libraries with --compiler=tsc', async () => {
const parent = uniq('parent');
runCLI(`generate @nrwl/js:lib ${parent}`);

const buildable = uniq('buildable');
runCLI(`generate @nrwl/js:lib ${buildable}`);

const nonBuildable = uniq('nonbuildable');
runCLI(`generate @nrwl/js:lib ${nonBuildable} --buildable=false`);

updateFile(`libs/${parent}/src/lib/${parent}.ts`, () => {
return `
import { ${buildable} } from '@${scope}/${buildable}';
import { ${nonBuildable} } from '@${scope}/${nonBuildable}';
export function ${parent}() {
${buildable}();
${nonBuildable}();
}
`;
});

expect(runCLI(`build ${parent}`)).toContain(
'Done compiling TypeScript files'
);

checkFilesExist(
`dist/libs/${buildable}/src/index.js`, // buildable
`dist/libs/${parent}/src/index.js`, // parent
`dist/libs/${parent}/${nonBuildable}/src/index.js` // non buildable
);

const fileContent = readFile(`dist/libs/${parent}/src/lib/${parent}.js`);
expect(fileContent).toContain(`${nonBuildable}/src`);
}, 120000);

it('should inline non-buildable libraries with --compiler=swc', async () => {
const parent = uniq('parent');
runCLI(`generate @nrwl/js:lib ${parent} --compiler=swc`);

const buildable = uniq('buildable');
runCLI(`generate @nrwl/js:lib ${buildable} --compiler=swc`);

const nonBuildable = uniq('nonbuildable');
runCLI(
`generate @nrwl/js:lib ${nonBuildable} --buildable=false --compiler=swc`
);

updateFile(`libs/${parent}/src/lib/${parent}.ts`, () => {
return `
import { ${buildable} } from '@${scope}/${buildable}';
import { ${nonBuildable} } from '@${scope}/${nonBuildable}';
export function ${parent}() {
${buildable}();
${nonBuildable}();
}
`;
});

expect(runCLI(`build ${parent}`)).toContain(
'Successfully compiled: 4 files with swc'
);

checkFilesExist(
`dist/libs/${buildable}/src/index.js`, // buildable
`dist/libs/${parent}/src/index.js`, // parent
`dist/libs/${parent}/${nonBuildable}/src/index.js` // non buildable
);

const fileContent = readFile(`dist/libs/${parent}/src/lib/${parent}.js`);
expect(fileContent).toContain(`${nonBuildable}/src`);
}, 120000);

it('should not create a `.babelrc` file when creating libs with js executors (--compiler=tsc)', () => {
const lib = uniq('lib');
runCLI(
Expand Down
3 changes: 1 addition & 2 deletions e2e/node/src/node.test.ts
Expand Up @@ -10,7 +10,6 @@ import {
packageInstall,
promisifiedTreeKill,
readFile,
removeFile,
runCLI,
runCLIAsync,
runCommandUntil,
Expand Down Expand Up @@ -485,7 +484,7 @@ describe('nest libraries', function () {
const nestlib = uniq('nestlib');
runCLI(`generate @nrwl/nest:lib ${nestlib} --buildable`);

packageInstall('@nestjs/swagger', undefined, '~5.0.0');
packageInstall('@nestjs/swagger', undefined, '~6.0.0');

updateProjectConfig(nestlib, (config) => {
config.targets.build.options.transformers = [
Expand Down
14 changes: 14 additions & 0 deletions packages/js/src/executors/swc/schema.json
Expand Up @@ -72,6 +72,20 @@
"description": "When `updateBuildableProjectDepsInPackageJson` is `true`, this adds dependencies to either `peerDependencies` or `dependencies`.",
"enum": ["dependencies", "peerDependencies"],
"default": "peerDependencies"
},
"external": {
"type": "string",
"description": "A list projects to be treated as external.",
"enum": ["all", "none"],
"default": "all"
},
"externalBuildTargets": {
"type": "array",
"items": {
"type": "string"
},
"description": "List of target names that annotate a build target for a project",
"default": ["build"]
}
},
"required": ["main", "outputPath", "tsConfig"],
Expand Down
56 changes: 52 additions & 4 deletions packages/js/src/executors/swc/swc.impl.ts
Expand Up @@ -3,21 +3,26 @@ import {
assetGlobsToFiles,
FileInputOutput,
} from '@nrwl/workspace/src/utilities/assets';
import { join, relative, resolve } from 'path';

import { removeSync } from 'fs-extra';
import { dirname, join, relative, resolve } from 'path';
import { copyAssets } from '../../utils/assets';
import { checkDependencies } from '../../utils/check-dependencies';
import {
getHelperDependency,
HelperDependency,
} from '../../utils/compiler-helper-dependency';
import {
handleInliningBuild,
postProcessInlinedDependencies,
} from '../../utils/inline';
import { copyPackageJson } from '../../utils/package-json';
import {
NormalizedSwcExecutorOptions,
SwcExecutorOptions,
} from '../../utils/schema';
import { compileSwc, compileSwcWatch } from '../../utils/swc/compile-swc';
import { getSwcrcPath } from '../../utils/swc/get-swcrc-path';
import { copyAssets } from '../../utils/assets';
import { copyPackageJson } from '../../utils/package-json';
import { generateTmpSwcrc } from '../../utils/swc/inline';

export function normalizeOptions(
options: SwcExecutorOptions,
Expand All @@ -35,6 +40,10 @@ export function normalizeOptions(
options.watch = false;
}

if (options.external == null) {
options.external = 'all';
}

const files: FileInputOutput[] = assetGlobsToFiles(
options.assets,
contextRoot,
Expand Down Expand Up @@ -67,6 +76,7 @@ export function normalizeOptions(
root: contextRoot,
sourceRoot,
projectRoot,
originalProjectRoot: projectRoot,
outputPath,
tsConfig: join(contextRoot, options.tsConfig),
swcCliOptions,
Expand Down Expand Up @@ -99,6 +109,30 @@ export async function* swcExecutor(
dependencies.push(swcHelperDependency);
}

const { inlinedDependencies, buildableDependencies } = handleInliningBuild(
context,
options,
options.tsConfig
);

if (inlinedDependencies.length > 0) {
options.projectRoot = '.'; // set to root of workspace to include other libs for type check

// remap paths for SWC compilation
options.swcCliOptions.srcPath = options.swcCliOptions.swcCwd;
options.swcCliOptions.swcCwd = '.';
options.swcCliOptions.destPath = options.swcCliOptions.destPath
.split('../')
.at(-1)
.concat('/', options.swcCliOptions.srcPath);

// tmp swcrc with buildable dependencies to exclude
options.swcCliOptions.swcrcPath = generateTmpSwcrc(
buildableDependencies,
options.swcCliOptions.swcrcPath
);
}

if (options.watch) {
let disposeFn: () => void;
process.on('SIGINT', () => disposeFn());
Expand All @@ -113,6 +147,8 @@ export async function* swcExecutor(
},
context
);
removeTmpSwcrc(options.swcCliOptions.swcrcPath);
// postProcessInlinedDependencies(context, options, inlinedDependencies);
disposeFn = () => {
assetResult?.stop();
packageJsonResult?.stop();
Expand All @@ -130,8 +166,20 @@ export async function* swcExecutor(
},
context
);
removeTmpSwcrc(options.swcCliOptions.swcrcPath);
postProcessInlinedDependencies(
options.outputPath,
options.originalProjectRoot,
inlinedDependencies
);
});
}
}

function removeTmpSwcrc(swcrcPath: string) {
if (swcrcPath.startsWith('tmp/')) {
removeSync(dirname(swcrcPath));
}
}

export default swcExecutor;
14 changes: 14 additions & 0 deletions packages/js/src/executors/tsc/schema.json
Expand Up @@ -61,6 +61,20 @@
"description": "When `updateBuildableProjectDepsInPackageJson` is `true`, this adds dependencies to either `peerDependencies` or `dependencies`.",
"enum": ["dependencies", "peerDependencies"],
"default": "peerDependencies"
},
"external": {
"type": "string",
"description": "A list projects to be treated as external.",
"enum": ["all", "none"],
"default": "all"
},
"externalBuildTargets": {
"type": "array",
"items": {
"type": "string"
},
"description": "List of target names that annotate a build target for a project",
"default": ["build"]
}
},
"required": ["main", "outputPath", "tsConfig"],
Expand Down
2 changes: 1 addition & 1 deletion packages/js/src/executors/tsc/tsc.impl.spec.ts
@@ -1,8 +1,8 @@
import { ExecutorContext } from '@nrwl/devkit';
import { ExecutorOptions } from '../../utils/schema';
import {
normalizeOptions,
createTypeScriptCompilationOptions,
normalizeOptions,
} from './tsc.impl';

describe('tscExecutor', () => {
Expand Down
36 changes: 32 additions & 4 deletions packages/js/src/executors/tsc/tsc.impl.ts
Expand Up @@ -3,24 +3,28 @@ import {
assetGlobsToFiles,
FileInputOutput,
} from '@nrwl/workspace/src/utilities/assets';
import { TypeScriptCompilationOptions } from '@nrwl/workspace/src/utilities/typescript/compilation';
import type { TypeScriptCompilationOptions } from '@nrwl/workspace/src/utilities/typescript/compilation';
import { join, resolve } from 'path';
import {
CustomTransformers,
Program,
SourceFile,
TransformerFactory,
} from 'typescript';
import { CopyAssetsHandler } from '../../utils/assets/copy-assets-handler';
import { checkDependencies } from '../../utils/check-dependencies';
import {
getHelperDependency,
HelperDependency,
} from '../../utils/compiler-helper-dependency';
import { CopyAssetsHandler } from '../../utils/assets/copy-assets-handler';
import {
handleInliningBuild,
postProcessInlinedDependencies,
} from '../../utils/inline';
import { updatePackageJson } from '../../utils/package-json/update-package-json';
import { ExecutorOptions, NormalizedExecutorOptions } from '../../utils/schema';
import { compileTypeScriptFiles } from '../../utils/typescript/compile-typescript-files';
import { loadTsTransformers } from '../../utils/typescript/load-ts-transformers';
import { updatePackageJson } from '../../utils/package-json/update-package-json';
import { watchForSingleFileChanges } from '../../utils/watch-for-single-file-changes';

export function normalizeOptions(
Expand All @@ -38,6 +42,10 @@ export function normalizeOptions(
options.watch = false;
}

if (options.external == null) {
options.external = 'all';
}

const files: FileInputOutput[] = assetGlobsToFiles(
options.assets,
contextRoot,
Expand Down Expand Up @@ -141,12 +149,32 @@ export async function* tscExecutor(
process.on('SIGTERM', () => handleTermination());
}

const tsCompilationOptions = createTypeScriptCompilationOptions(
options,
context
);

const { inlinedDependencies } = handleInliningBuild(
context,
options,
tsCompilationOptions.tsConfig
);

if (inlinedDependencies.length > 0) {
tsCompilationOptions.rootDir = '.';
}

return yield* compileTypeScriptFiles(
options,
createTypeScriptCompilationOptions(options, context),
tsCompilationOptions,
async () => {
await assetHandler.processAllAssetsOnce();
updatePackageJson(options, context, target, dependencies);
postProcessInlinedDependencies(
tsCompilationOptions.outputPath,
tsCompilationOptions.projectRoot,
inlinedDependencies
);
}
);
}
Expand Down

0 comments on commit 1b623c1

Please sign in to comment.