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 Jun 30, 2023
1 parent fced370 commit 9510617
Show file tree
Hide file tree
Showing 12 changed files with 419 additions and 105 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-5-0-change-ts-paths-plugin": {
"version": "16.5.0-beta.0",
"description": "Change vite-tsconfig-paths plugin for first party nx-vite-tsconfig-paths plugin",
"cli": "nx",
"implementation": "./src/migrations/update-16-5-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"
}
}
92 changes: 92 additions & 0 deletions packages/vite/plugins/nx-tsconfig-paths.plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { stripIndents, workspaceRoot } from '@nx/devkit';
import { existsSync } from 'node:fs';
import { relative, join, resolve, posix } from 'node:path';
import { loadConfig, createMatchPath, MatchPath } from 'tsconfig-paths';

// TODO(caleb): should we provide a way to override anything for the plugin?

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

return {
name: 'nx-vite-ts-paths',
configResolved(config: any) {
const projectRoot = config.root;
// TODO(caleb): verify on windows to see what type of paths vite returns posix vs win32
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);
}
}
1 change: 1 addition & 0 deletions packages/vite/src/executors/build/build.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export async function* viteBuildExecutor(
const projectRoot =
context.projectsConfigurations.projects[context.projectName].root;

// TODO(caleb): do we need to register the paths anymore or just make tsconfig?
registerPaths(projectRoot, options, context);

const normalizedOptions = normalizeOptions(options);
Expand Down
1 change: 1 addition & 0 deletions packages/vite/src/executors/dev-server/dev-server.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export async function* viteDevServerExecutor(
const projectRoot =
context.projectsConfigurations.projects[context.projectName].root;

// TODO(caleb): do we need to register the paths anymore or just make tsconfig?
registerPaths(projectRoot, options, context);

// Retrieve the option for the configured buildTarget.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ exports[`@nx/vite:configuration library mode should add config for building libr
"/// <reference types="vitest" />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import viteTsConfigPaths from 'vite-tsconfig-paths';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import dts from 'vite-plugin-dts';
import * as path from 'path';
Expand All @@ -18,18 +18,12 @@ export default defineConfig({
skipDiagnostics: true,
}),
react(),
viteTsConfigPaths({
root: '../',
}),
nxViteTsPaths(),
],
// Uncomment this if you are using workers.
// worker: {
// plugins: [
// viteTsConfigPaths({
// root: '../',
// }),
// ],
// plugins: [ nxViteTsPaths() ],
// },
// Configuration for building your library.
Expand Down Expand Up @@ -57,7 +51,7 @@ exports[`@nx/vite:configuration library mode should set up non buildable library
"/// <reference types="vitest" />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import viteTsConfigPaths from 'vite-tsconfig-paths';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import dts from 'vite-plugin-dts';
import * as path from 'path';
Expand All @@ -71,18 +65,12 @@ export default defineConfig({
skipDiagnostics: true,
}),
react(),
viteTsConfigPaths({
root: '../../',
}),
nxViteTsPaths(),
],
// Uncomment this if you are using workers.
// worker: {
// plugins: [
// viteTsConfigPaths({
// root: '../../',
// }),
// ],
// plugins: [ nxViteTsPaths() ],
// },
// Configuration for building your library.
Expand Down Expand Up @@ -301,7 +289,7 @@ exports[`@nx/vite:configuration transform React app to use Vite should create vi
"/// <reference types="vitest" />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import viteTsConfigPaths from 'vite-tsconfig-paths';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
export default defineConfig({
cacheDir: '../../node_modules/.vite/my-test-react-app',
Expand All @@ -316,20 +304,11 @@ export default defineConfig({
host: 'localhost',
},
plugins: [
react(),
viteTsConfigPaths({
root: '../../',
}),
],
plugins: [react(), nxViteTsPaths()],
// Uncomment this if you are using workers.
// worker: {
// plugins: [
// viteTsConfigPaths({
// root: '../../',
// }),
// ],
// plugins: [ nxViteTsPaths() ],
// },
});
"
Expand Down Expand Up @@ -451,7 +430,7 @@ exports[`@nx/vite:configuration transform Web app to use Vite should create vite
"/// <reference types="vitest" />
import { defineConfig } from 'vite';
import viteTsConfigPaths from 'vite-tsconfig-paths';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
export default defineConfig({
cacheDir: '../../node_modules/.vite/my-test-web-app',
Expand All @@ -466,19 +445,11 @@ export default defineConfig({
host: 'localhost',
},
plugins: [
viteTsConfigPaths({
root: '../../',
}),
],
plugins: [nxViteTsPaths()],
// Uncomment this if you are using workers.
// worker: {
// plugins: [
// viteTsConfigPaths({
// root: '../../',
// }),
// ],
// plugins: [ nxViteTsPaths() ],
// },
});
"
Expand Down Expand Up @@ -587,7 +558,7 @@ exports[`@nx/vite:configuration vitest should create a vitest configuration if "
"/// <reference types="vitest" />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import viteTsConfigPaths from 'vite-tsconfig-paths';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
export default defineConfig({
cacheDir: '../../node_modules/.vite/my-test-react-app',
Expand All @@ -602,20 +573,11 @@ export default defineConfig({
host: 'localhost',
},
plugins: [
react(),
viteTsConfigPaths({
root: '../../',
}),
],
plugins: [react(), nxViteTsPaths()],
// Uncomment this if you are using workers.
// worker: {
// plugins: [
// viteTsConfigPaths({
// root: '../../',
// }),
// ],
// plugins: [ nxViteTsPaths() ],
// },
test: {
Expand Down
Loading

0 comments on commit 9510617

Please sign in to comment.