Skip to content

Commit 7a300e2

Browse files
feat(qwik-nx): add qwikNxVite plugin
1 parent 87d8941 commit 7a300e2

File tree

15 files changed

+276
-46
lines changed

15 files changed

+276
-46
lines changed

e2e/qwik-nx-e2e/project.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"executor": "@nrwl/nx-plugin:e2e",
99
"options": {
1010
"target": "qwik-nx:build",
11-
"jestConfig": "e2e/qwik-nx-e2e/jest.config.ts"
11+
"jestConfig": "e2e/qwik-nx-e2e/jest.config.ts",
12+
"maxWorkers": 1
1213
}
1314
}
1415
},

e2e/qwik-nx-e2e/tests/qwik-nx.spec.ts renamed to e2e/qwik-nx-e2e/tests/application.spec.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
killPort,
1212
} from '@qwikifiers/e2e/utils';
1313

14-
describe('qwik-nx e2e', () => {
14+
describe('appGenerator e2e', () => {
1515
// Setting up individual workspaces per
1616
// test can cause e2e runs to take a long time.
1717
// For this reason, we recommend each suite only
@@ -22,10 +22,10 @@ describe('qwik-nx e2e', () => {
2222
ensureNxProject('qwik-nx', 'dist/packages/qwik-nx');
2323
});
2424

25-
afterAll(() => {
25+
afterAll(async () => {
2626
// `nx reset` kills the daemon, and performs
2727
// some work which can help clean up e2e leftovers
28-
runNxCommandAsync('reset');
28+
await runNxCommandAsync('reset');
2929
});
3030

3131
describe('Basic behavior', () => {
@@ -36,6 +36,7 @@ describe('qwik-nx e2e', () => {
3636
`generate qwik-nx:app ${project} --no-interactive`
3737
);
3838
}, 200000);
39+
3940
it('should create qwik-nx', async () => {
4041
const result = await runNxCommandAsync(`build-ssr ${project}`);
4142
expect(result.stdout).toContain(
@@ -64,5 +65,21 @@ describe('qwik-nx e2e', () => {
6465
// ignore
6566
}
6667
}, 200000);
68+
69+
it('should serve application in preview mode with custom port', async () => {
70+
const port = 4232;
71+
const p = await runCommandUntil(
72+
`run ${project}:preview --port=${port}`,
73+
(output) => {
74+
return output.includes('Local:') && output.includes(`:${port}`);
75+
}
76+
);
77+
try {
78+
await promisifiedTreeKill(p.pid, 'SIGKILL');
79+
await killPort(port);
80+
} catch {
81+
// ignore
82+
}
83+
}, 200000);
6784
});
6885
});
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import {
2+
checkFilesExist,
3+
ensureNxProject,
4+
readFile,
5+
renameFile,
6+
runNxCommandAsync,
7+
uniq,
8+
updateFile,
9+
} from '@nrwl/nx-plugin/testing';
10+
11+
import {
12+
runCommandUntil,
13+
promisifiedTreeKill,
14+
killPort,
15+
removeFile,
16+
} from '@qwikifiers/e2e/utils';
17+
18+
describe('qwikNxVite plugin e2e', () => {
19+
// Setting up individual workspaces per
20+
// test can cause e2e runs to take a long time.
21+
// For this reason, we recommend each suite only
22+
// consumes 1 workspace. The tests should each operate
23+
// on a unique project in the workspace, such that they
24+
// are not dependant on one another.
25+
beforeAll(() => {
26+
ensureNxProject('qwik-nx', 'dist/packages/qwik-nx');
27+
});
28+
29+
afterAll(async () => {
30+
// `nx reset` kills the daemon, and performs
31+
// some work which can help clean up e2e leftovers
32+
await runNxCommandAsync('reset');
33+
});
34+
35+
describe('should be able to import components from libraries', () => {
36+
let project: string;
37+
let libName: string;
38+
beforeAll(async () => {
39+
project = uniq('qwik-nx');
40+
libName = uniq('qwik-nx');
41+
await runNxCommandAsync(
42+
`generate qwik-nx:app ${project} --no-interactive`
43+
);
44+
await runNxCommandAsync(
45+
`generate qwik-nx:library ${libName} --unitTestRunner=none --no-interactive`
46+
);
47+
48+
// move header component into the library
49+
50+
// update import in layout.tsx
51+
const layoutFilePath = `apps/${project}/src/routes/layout.tsx`;
52+
let layoutFile = readFile(layoutFilePath);
53+
layoutFile = layoutFile.replace(
54+
`import Header from '../components/header/header';`,
55+
`import { Header } from '@proj/${libName}';`
56+
);
57+
updateFile(layoutFilePath, layoutFile);
58+
59+
// move header component files
60+
const headerFolderOldPath = `apps/${project}/src/components/header`;
61+
const headerFolderNewPath = `libs/${libName}/src/lib`;
62+
removeFile(`${headerFolderNewPath}/${libName}.tsx`);
63+
removeFile(`${headerFolderNewPath}/${libName}.css`);
64+
renameFile(
65+
`${headerFolderOldPath}/header.tsx`,
66+
`${headerFolderNewPath}/header.tsx`
67+
);
68+
renameFile(
69+
`${headerFolderOldPath}/header.css`,
70+
`${headerFolderNewPath}/header.css`
71+
);
72+
updateFile(
73+
`libs/${libName}/src/index.ts`,
74+
`export * from './lib/header';`
75+
);
76+
77+
// remove icon from header.tsx
78+
let headerTsx = readFile(`${headerFolderNewPath}/header.tsx`);
79+
headerTsx = headerTsx.replace(
80+
`import { QwikLogo } from '../icons/qwik';`,
81+
''
82+
);
83+
headerTsx = headerTsx.replace(`<QwikLogo />`, '');
84+
headerTsx = headerTsx.replace(
85+
'export default component$(() => {',
86+
'export const Header = component$(() => {'
87+
);
88+
updateFile(`${headerFolderNewPath}/header.tsx`, headerTsx);
89+
}, 200000);
90+
91+
it('should be able to successfully build the application', async () => {
92+
const result = await runNxCommandAsync(`build-ssr ${project}`);
93+
expect(result.stdout).toContain(
94+
`Successfully ran target build-ssr for project ${project}`
95+
);
96+
expect(() =>
97+
checkFilesExist(`dist/apps/${project}/client/q-manifest.json`)
98+
).not.toThrow();
99+
expect(() =>
100+
checkFilesExist(`dist/apps/${project}/server/entry.preview.mjs`)
101+
).not.toThrow();
102+
}, 200000);
103+
104+
it('should serve application in preview mode with custom port', async () => {
105+
const port = 4212;
106+
const p = await runCommandUntil(
107+
`run ${project}:preview --port=${port}`,
108+
(output) => {
109+
return output.includes('Local:') && output.includes(`:${port}`);
110+
}
111+
);
112+
try {
113+
await promisifiedTreeKill(p.pid, 'SIGKILL');
114+
await killPort(port);
115+
} catch {
116+
// ignore
117+
}
118+
}, 200000);
119+
});
120+
});

e2e/utils/index.ts

Lines changed: 3 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@ export const promisifiedTreeKill: (
3434
) => Promise<void> = promisify(treeKill);
3535

3636
export function getNxVersion(): string {
37-
const version = readJsonFile(
37+
const { dependencies } = readJsonFile(
3838
join(workspaceRoot, `./dist/packages/qwik-nx/package.json`)
39-
).peerDependencies.nx;
39+
);
40+
const version = dependencies['@nrwl/vite'];
4041
if (!version) {
4142
throw new Error('Could not retrieve Nx version');
4243
}
@@ -217,44 +218,6 @@ export function expectTestsPass(v: { stdout: string; stderr: string }) {
217218
expect(v.stderr).not.toContain('fail');
218219
}
219220

220-
export function createFile(f: string, content: string = ''): void {
221-
const path = tmpProjPath(f);
222-
createFileSync(path);
223-
if (content) {
224-
updateFile(f, content);
225-
}
226-
}
227-
228-
export function updateFile(
229-
f: string,
230-
content: string | ((content: string) => string)
231-
): void {
232-
ensureDirSync(path.dirname(tmpProjPath(f)));
233-
if (typeof content === 'string') {
234-
writeFileSync(tmpProjPath(f), content);
235-
} else {
236-
writeFileSync(
237-
tmpProjPath(f),
238-
content(readFileSync(tmpProjPath(f)).toString())
239-
);
240-
}
241-
}
242-
243-
export function renameFile(f: string, newPath: string): void {
244-
ensureDirSync(path.dirname(tmpProjPath(newPath)));
245-
renameSync(tmpProjPath(f), tmpProjPath(newPath));
246-
}
247-
248-
export function updateJson<T extends object = any, U extends object = T>(
249-
f: string,
250-
updater: (value: T) => U
251-
) {
252-
updateFile(f, (s) => {
253-
const json = JSON.parse(s);
254-
return JSON.stringify(updater(json), null, 2);
255-
});
256-
}
257-
258221
export function checkFilesDoNotExist(...expectedFiles: string[]) {
259222
expectedFiles.forEach((f) => {
260223
const ff = f.startsWith('/') ? f : tmpProjPath(f);

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
},
1313
"private": true,
1414
"devDependencies": {
15+
"@builder.io/qwik": "0.17.4",
1516
"@commitlint/cli": "^17.3.0",
1617
"@commitlint/config-angular": "^17.3.0",
1718
"@commitlint/config-conventional": "^17.3.0",
@@ -55,7 +56,8 @@
5556
"tree-kill": "1.2.2",
5657
"ts-jest": "28.0.5",
5758
"ts-node": "10.9.1",
58-
"typescript": "~4.8.2"
59+
"typescript": "~4.8.2",
60+
"vite": "4.1.1"
5961
},
6062
"dependencies": {
6163
"@swc/helpers": "~0.4.11",

packages/qwik-nx/generators.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './src/generators';

packages/qwik-nx/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
export * from './src/generators';
1+
// This is explicitly empty, but serves as a primary compilation entry-point.
2+
export default {};

packages/qwik-nx/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,9 @@
2323
"executors": "./executors.json",
2424
"dependencies": {
2525
"@nrwl/vite": "~15.6.0"
26+
},
27+
"peerDependencies": {
28+
"@builder.io/qwik": "^0.16.0",
29+
"vite": "~4.1.1"
2630
}
2731
}

packages/qwik-nx/plugins.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './src/plugins';

packages/qwik-nx/src/generators/application/files/vite.config.ts__template__

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ import { qwikVite } from '@builder.io/qwik/optimizer';
22
import { qwikCity } from '@builder.io/qwik-city/vite';
33
import { defineConfig } from 'vite';
44
import tsconfigPaths from 'vite-tsconfig-paths';
5+
import { qwikNxVite } from 'qwik-nx/plugins';
56

67
export default defineConfig({
78
plugins: [
9+
qwikNxVite(),
810
qwikCity(),
911
qwikVite({
1012
client: {

0 commit comments

Comments
 (0)