Skip to content

Commit 57d1a7f

Browse files
authored
fix(angular-rspack): ssg should not run on serve (#75)
1 parent 8cb7641 commit 57d1a7f

File tree

6 files changed

+86
-36
lines changed

6 files changed

+86
-36
lines changed

e2e/fixtures/rspack-ssg-css/src/app/app.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ import { FooComponent } from './foo.component';
1010
styleUrl: './app.component.css',
1111
})
1212
export class AppComponent {
13-
title = 'rspack-ssr-css';
13+
title = 'rspack-ssg-css';
1414
}

packages/angular-rspack/src/lib/config/config-utils/browser-config.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,10 @@ export async function getBrowserConfig(
1717
defaultConfig: Configuration
1818
): Promise<Configuration> {
1919
const isProduction = process.env['NODE_ENV'] === 'production';
20-
const isDevServer = !!process.env['WEBPACK_SERVE'];
2120

2221
return {
2322
...defaultConfig,
2423
name: 'browser',
25-
...(normalizedOptions.hasServer && isDevServer
26-
? { dependencies: ['server'] }
27-
: {}),
2824
target: 'web',
2925
entry: {
3026
main: {

packages/angular-rspack/src/lib/config/config-utils/server-config.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ export async function getServerConfig(
1616
i18n: I18nOptions,
1717
defaultConfig: Configuration
1818
): Promise<Configuration> {
19+
const isDevServer = !!process.env['WEBPACK_SERVE'];
1920
const { root } = normalizedOptions;
2021

2122
return {
2223
...defaultConfig,
24+
dependencies: ['browser'],
2325
name: 'server',
2426
target: 'node',
2527
entry: {
@@ -86,7 +88,7 @@ export async function getServerConfig(
8688
i18nOptions: i18n,
8789
platform: 'server',
8890
}),
89-
...(normalizedOptions.prerender
91+
...(normalizedOptions.prerender && !isDevServer
9092
? [new PrerenderPlugin(normalizedOptions, i18n)]
9193
: []),
9294
],
Lines changed: 60 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,88 @@
1-
import { Compiler, RspackPluginInstance } from '@rspack/core';
1+
import {
2+
Compilation,
3+
Compiler,
4+
RspackPluginInstance,
5+
sources,
6+
} from '@rspack/core';
27
import { ChildProcess, fork } from 'child_process';
38
import { SsrReloadServer } from './server/ssr-reload-server';
4-
import { OutputPath } from '../models';
9+
import { NormalizedAngularRspackPluginOptions } from '../models';
510
import { join } from 'node:path';
6-
import { existsSync } from 'node:fs';
11+
import { existsSync, readFileSync } from 'node:fs';
12+
import { getIndexOutputFile } from '../utils/index-file/get-index-output-file';
13+
import { addBodyScript } from '../utils/index-file/add-body-script';
714

815
const PLUGIN_NAME = 'AngularSsrDevServer';
16+
917
export class AngularSsrDevServer implements RspackPluginInstance {
1018
#devServerProcess: ChildProcess | undefined;
1119
#wsServer: SsrReloadServer;
12-
#outputPath: OutputPath;
20+
#options: NormalizedAngularRspackPluginOptions;
1321

14-
constructor(outputPath: OutputPath) {
15-
this.#outputPath = outputPath;
22+
constructor(options: NormalizedAngularRspackPluginOptions) {
1623
this.#wsServer = new SsrReloadServer();
24+
this.#options = options;
1725
}
1826

1927
apply(compiler: Compiler) {
2028
compiler.hooks.entryOption.tap(PLUGIN_NAME, (context, entry) => {
2129
const keys = Object.keys(entry);
2230
for (const key of keys) {
2331
const entryValue = entry[key];
24-
entryValue.import = [
25-
...entryValue.import,
26-
require.resolve(`${__dirname}/client/ssr-reload-client.js`),
27-
];
32+
entryValue.import = [...entryValue.import];
2833
}
2934
});
3035
compiler.hooks.watchRun.tapAsync(
3136
PLUGIN_NAME,
3237
async (compiler, callback) => {
33-
compiler.hooks.afterEmit.tapAsync(PLUGIN_NAME, async (_, callback) => {
34-
const serverPath = join(this.#outputPath.server, 'server.js');
35-
if (this.#devServerProcess) {
36-
this.#devServerProcess.kill();
37-
this.#devServerProcess = undefined;
38-
await new Promise<void>((res) => setTimeout(res, 50));
39-
}
40-
if (!existsSync(serverPath)) {
41-
await new Promise<void>((res) => setTimeout(res, 50));
38+
compiler.hooks.afterEmit.tapAsync(
39+
PLUGIN_NAME,
40+
async (compilation, callback) => {
41+
await this.#attachSSRReloadClient(compilation);
42+
43+
const serverPath = join(
44+
this.#options.outputPath.server,
45+
'server.js'
46+
);
47+
if (this.#devServerProcess) {
48+
this.#devServerProcess.kill();
49+
this.#devServerProcess = undefined;
50+
await new Promise<void>((res) => setTimeout(res, 50));
51+
}
52+
if (!existsSync(serverPath)) {
53+
await new Promise<void>((res) => setTimeout(res, 50));
54+
}
55+
this.#devServerProcess = fork(serverPath);
56+
this.#devServerProcess.on('spawn', () => {
57+
this.#wsServer.sendReload();
58+
});
59+
callback();
4260
}
43-
this.#devServerProcess = fork(serverPath);
44-
this.#devServerProcess.on('spawn', () => {
45-
this.#wsServer.sendReload();
46-
});
47-
callback();
48-
});
61+
);
4962
callback();
5063
}
5164
);
5265
}
66+
67+
async #attachSSRReloadClient(compilation: Compilation) {
68+
const clientPath = require.resolve(
69+
`${__dirname}/client/ssr-reload-client.js`
70+
);
71+
const pathToIndex = join(
72+
this.#options.outputPath.browser,
73+
getIndexOutputFile(this.#options.index)
74+
);
75+
const html = readFileSync(pathToIndex, 'utf-8');
76+
const updatedHtml = await addBodyScript(
77+
html,
78+
readFileSync(clientPath, 'utf-8')
79+
);
80+
const source = new sources.RawSource(updatedHtml);
81+
82+
const relativePathToIndex = pathToIndex.replace(
83+
this.#options.outputPath.browser,
84+
''
85+
);
86+
compilation.emitAsset(relativePathToIndex, source);
87+
}
5388
}

packages/angular-rspack/src/lib/plugins/ng-rspack.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { getEntryPoints } from '../config/config-utils/entry-points';
1010
import type {
1111
I18nOptions,
1212
NormalizedAngularRspackPluginOptions,
13-
OutputPath,
1413
} from '../models';
1514
import { AngularRspackPlugin } from './angular-rspack-plugin';
1615
import { AngularSsrDevServer } from './angular-ssr-dev-server';
@@ -39,15 +38,13 @@ export class NgRspackPlugin implements RspackPluginInstance {
3938
const root = this.pluginOptions.root;
4039
const isDevServer = process.env['WEBPACK_SERVE'];
4140

42-
if (!this.isPlatformServer && isDevServer) {
41+
if (this.isPlatformServer && isDevServer) {
4342
if (
4443
this.pluginOptions.ssr &&
4544
typeof this.pluginOptions.ssr === 'object' &&
4645
this.pluginOptions.ssr.entry !== undefined
4746
) {
48-
new AngularSsrDevServer(
49-
this.pluginOptions.outputPath as OutputPath
50-
).apply(compiler);
47+
new AngularSsrDevServer(this.pluginOptions).apply(compiler);
5148
}
5249
}
5350
if (!isDevServer) {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { htmlRewritingStream } from './html-rewriting-stream';
2+
3+
export async function addBodyScript(
4+
html: string,
5+
bodyScriptContents: string
6+
): Promise<string> {
7+
const { rewriter, transformedContent } = await htmlRewritingStream(html);
8+
9+
const bodyScript = `<script type="text/javascript">${bodyScriptContents}</script>`;
10+
11+
rewriter.on('startTag', (tag) => {
12+
rewriter.emitStartTag(tag);
13+
14+
if (tag.tagName === 'body') {
15+
rewriter.emitRaw(bodyScript);
16+
}
17+
});
18+
19+
return transformedContent();
20+
}

0 commit comments

Comments
 (0)