Skip to content

Commit

Permalink
feat(vite): add tsconfig paths resolution plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
barbados-clemens committed Jul 17, 2023
1 parent 187842e commit 8ba6349
Show file tree
Hide file tree
Showing 16 changed files with 417 additions and 125 deletions.
70 changes: 69 additions & 1 deletion e2e/vite/src/vite.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { names } from '@nx/devkit';
import {
cleanupProject,
createFile,
Expand Down Expand Up @@ -240,6 +241,74 @@ describe('Vite Plugin', () => {
100_000;
});

describe.only('incremental building', () => {
const app = uniq('demo');
const lib = uniq('my-lib');
beforeAll(() => {
proj = newProject({ name: uniq('vite-incr-build') });
runCLI(`generate @nx/react:app ${app} --bundler=vite --no-interactive`);

// only this project will be directly used from dist
runCLI(
`generate @nx/react:lib ${lib}-buildable --unitTestRunner=none --bundler=vite --importPath="@acme/buildable" --no-interactive`
);

runCLI(
`generate @nx/react:lib ${lib} --unitTestRunner=none --bundler=none --importPath="@acme/non-buildable" --no-interactive`
);

// because the default js lib builds as cjs it cannot be loaded from dist
// so the paths plugin should always resolve to the libs source
runCLI(
`generate @nx/js:lib ${lib}-js --bundler=tsc --importPath="@acme/js-lib" --no-interactive`
);
const buildableLibCmp = names(`${lib}-buildable`).className;
const nonBuildableLibCmp = names(lib).className;
const buildableJsLibFn = names(`${lib}-js`).propertyName;

updateFile(`apps/${app}/src/app/app.tsx`, () => {
return `// eslint-disable-next-line @typescript-eslint/no-unused-vars
import styles from './app.module.css';
import NxWelcome from './nx-welcome';
import { ${buildableLibCmp} } from '@acme/buildable';
import { ${buildableJsLibFn} } from '@acme/js-lib';
import { ${nonBuildableLibCmp} } from '@acme/non-buildable';
export function App() {
return (
<div>
<${buildableLibCmp} />
<${nonBuildableLibCmp} />
<p>{${buildableJsLibFn}()}</p>
<NxWelcome title="${app}" />
</div>
);
}
export default App;
`;
});
});

afterAll(() => {
cleanupProject();
});

it('should build app from libs source', () => {
const results = runCLI(`build ${app} --buildLibsFromSource=true`);
expect(results).toContain('Successfully ran target build for project');
// this should be more modules than build from dist
expect(results).toContain('40 modules transformed');
});

it('should build app from libs dist', () => {
const results = runCLI(`build ${app} --buildLibsFromSource=false`);
expect(results).toContain('Successfully ran target build for project');
// this should be less modules than building from source
expect(results).toContain('38 modules transformed');
});
});

describe('should be able to create libs that use vitest', () => {
const lib = uniq('my-lib');
beforeEach(() => {
Expand All @@ -255,7 +324,6 @@ describe('Vite Plugin', () => {
`Successfully ran target test for project ${lib}`
);

// TODO(caleb): run tests from project root and make sure they still work
const nestedResults = await runCLIAsync(`test ${lib} --skip-nx-cache`, {
cwd: `${tmpProjPath()}/libs/${lib}`,
});
Expand Down
6 changes: 6 additions & 0 deletions packages/vite/migrations.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@
"description": "Changes the testFile config in the vite:test exectutor from a string to an array of strings",
"cli": "nx",
"implementation": "./src/migrations/update-16-4-1-update-test-file-config/update-16-4-1-test-file-config"
},
"16-6-0-change-ts-paths-plugin": {
"version": "16.6.0-beta.4",
"description": "Change vite-tsconfig-paths plugin for first party nx-vite-tsconfig-paths plugin",
"cli": "nx",
"implementation": "./src/migrations/update-16-6-0-change-ts-paths-plugin/change-ts-paths-plugin"
}
},
"packageJsonUpdates": {
Expand Down
6 changes: 4 additions & 2 deletions packages/vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
"dotenv": "~10.0.0",
"enquirer": "~2.3.6",
"@nx/devkit": "file:../devkit",
"@nx/js": "file:../js"
"@nx/js": "file:../js",
"tsconfig-paths": "^4.1.2"
},
"peerDependencies": {
"vite": "^4.3.4",
Expand All @@ -53,6 +54,7 @@
"./executors": "./executors.js",
"./src/executors/*/schema.json": "./src/executors/*/schema.json",
"./src/executors/*.impl": "./src/executors/*.impl.js",
"./src/executors/*/compat": "./src/executors/*/compat.js"
"./src/executors/*/compat": "./src/executors/*/compat.js",
"./plugins/nx-tsconfig-paths.plugin": "./plugins/nx-tsconfig-paths.plugin.js"
}
}
89 changes: 89 additions & 0 deletions packages/vite/plugins/nx-tsconfig-paths.plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { stripIndents, workspaceRoot } from '@nx/devkit';
import { existsSync } from 'node:fs';
import { relative, join, resolve } from 'node:path';
import { loadConfig, createMatchPath, MatchPath } from 'tsconfig-paths';

export function nxViteTsPaths() {
let matchTsPathEsm: MatchPath;
let matchTsPathFallback: MatchPath | undefined;

return {
name: 'nx-vite-ts-paths',
configResolved(config: any) {
const projectRoot = config.root;
const projectRootFromWorkspaceRoot = relative(workspaceRoot, projectRoot);

const foundTsConfigPath = getTsConfig(
join(
workspaceRoot,
'tmp',
projectRootFromWorkspaceRoot,
'tsconfig.generated.json'
)
);
if (!foundTsConfigPath) {
throw new Error(stripIndents`Unable to find a tsconfig in the workspace!
There should at least be a tsconfig.base.json or tsconfig.json in the root of the workspace ${workspaceRoot}`);
}
const parsed = loadConfig(foundTsConfigPath);

logIt('first parsed tsconfig: ', parsed);
if (parsed.resultType === 'failed') {
throw new Error(`Failed loading tsonfig at ${foundTsConfigPath}`);
}

matchTsPathEsm = createMatchPath(parsed.absoluteBaseUrl, parsed.paths, [
['exports', '.', 'import'],
'module',
'main',
]);

const rootLevelTsConfig = getTsConfig(
join(workspaceRoot, 'tsconfig.base.json')
);
const rootLevelParsed = loadConfig(rootLevelTsConfig);
logIt('fallback parsed tsconfig: ', rootLevelParsed);
if (rootLevelParsed.resultType === 'success') {
matchTsPathFallback = createMatchPath(
rootLevelParsed.absoluteBaseUrl,
rootLevelParsed.paths,
['main', 'module']
);
}
},
resolveId(source: string) {
let resolvedFile: string;
try {
resolvedFile = matchTsPathEsm(source);
} catch (e) {
logIt('Using fallback path matching.');
resolvedFile = matchTsPathFallback?.(source);
}

if (!resolvedFile) {
logIt(`Unable to resolve ${source} with tsconfig paths`);
}

return resolvedFile;
},
};
}

function getTsConfig(preferredTsConfigPath: string): string {
return [
resolve(preferredTsConfigPath),
resolve(join(workspaceRoot, 'tsconfig.base.json')),
resolve(join(workspaceRoot, 'tsconfig.json')),
].find((tsPath) => {
if (existsSync(tsPath)) {
logIt('Found tsconfig at', tsPath);
return tsPath;
}
});
}

function logIt(...msg: any[]) {
if (process.env.NX_VERBOSE_LOGGING === 'true') {
console.debug('[Nx Vite TsPaths]', ...msg);
}
}
7 changes: 5 additions & 2 deletions packages/vite/src/executors/build/build.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ import {
import { existsSync, writeFileSync } from 'fs';
import { resolve } from 'path';
import { createAsyncIterable } from '@nx/devkit/src/utils/async-iterable';
import { registerPaths, validateTypes } from '../../utils/executor-utils';
import {
createBuildableTsConfig,
validateTypes,
} from '../../utils/executor-utils';

export async function* viteBuildExecutor(
options: ViteBuildExecutorOptions,
Expand All @@ -30,7 +33,7 @@ export async function* viteBuildExecutor(
const projectRoot =
context.projectsConfigurations.projects[context.projectName].root;

registerPaths(projectRoot, options, context);
createBuildableTsConfig(projectRoot, options, context);

const normalizedOptions = normalizeOptions(options);

Expand Down
4 changes: 2 additions & 2 deletions packages/vite/src/executors/dev-server/dev-server.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {

import { ViteDevServerExecutorOptions } from './schema';
import { ViteBuildExecutorOptions } from '../build/schema';
import { registerPaths } from '../../utils/executor-utils';
import { createBuildableTsConfig } from '../../utils/executor-utils';

export async function* viteDevServerExecutor(
options: ViteDevServerExecutorOptions,
Expand All @@ -20,7 +20,7 @@ export async function* viteDevServerExecutor(
const projectRoot =
context.projectsConfigurations.projects[context.projectName].root;

registerPaths(projectRoot, options, context);
createBuildableTsConfig(projectRoot, options, context);

// Retrieve the option for the configured buildTarget.
const buildTargetOptions: ViteBuildExecutorOptions = getNxTargetOptions(
Expand Down
Loading

0 comments on commit 8ba6349

Please sign in to comment.