Skip to content

Commit

Permalink
feat: support generate ssr content in devlopment mode (#31)
Browse files Browse the repository at this point in the history
* feat: support generate ssr content in devlopment mode

* chore: remove ssr build when production
  • Loading branch information
ZLY201 authored Feb 8, 2024
1 parent 6b70d73 commit ba7ca12
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 29 deletions.
4 changes: 1 addition & 3 deletions html/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
</head>
<body>
<script>try{if(JSON.parse(localStorage.getItem('__setting_cache__')).theme==='dark'){document.body.setAttribute('arco-theme','dark');}}catch{}</script>
<div id="root">
<%= ROOT_CONTENT %>
</div>
<div id="root">{% ROOT_CONTENT %}</div>
</body>
</html>
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
"reset": "rm -rf node_modules",
"setup": "yarn reset && yarn",
"clean": "rm -rf dist",
"dev": "yarn build:ssr && rspack serve --watch",
"build:ssr": "yarn clean && rspack build --config=rspack.ssr.config.ts",
"build": "yarn build:ssr && rspack build && rm -rf dist/ssr",
"dev": "rspack serve --config=tools/rspack.config.ts --watch",
"build:ssr": "rspack build --config=tools/rspack.ssr.config.ts",
"build": "yarn clean && yarn build:ssr && rspack build --config=tools/rspack.config.ts && rm -rf dist/ssr",
"new": "ts-node tools/addNewProblem.ts",
"lint": "eslint --fix --color --cache --quiet .",
"prepare": "husky install"
Expand Down
2 changes: 1 addition & 1 deletion src/modules/Editor/monaco-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ const MonacoEditor = withAutoResize(
}
for (const filename of Object.keys(this.props.raw)) {
this.models[filename]?.updateOptions(this.props.setting);
if (!filename.includes('/node_modules/')) {
if (!filename.includes('node_modules')) {
validateMonacoModel(this.models[filename]);
}
}
Expand Down
83 changes: 83 additions & 0 deletions tools/RspackSSRPlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import path from 'path';
import childProcess from 'child_process';
import { readFileSync, writeFileSync } from 'fs';
import { RspackPluginInstance, Compiler } from '@rspack/core';

type RspackSSRPluginOptions = {
token: string;
template: string;
};

class RspackSSRPlugin implements RspackPluginInstance {
private readonly templateContent: string;
private readonly options: RspackSSRPluginOptions;
constructor(options: RspackSSRPluginOptions) {
this.options = options;
const { template } = options;
this.templateContent = readFileSync(template, { encoding: 'utf-8' });
}
apply(compiler: Compiler) {
const mode = compiler.options.mode;
const pluginName = RspackSSRPlugin.name;
const tabFunc =
mode === 'development'
? compiler.hooks.watchRun
: compiler.hooks.beforeRun;
tabFunc.tapAsync(pluginName, (compiler, callback) => {
this.runSSRBuild(compiler, callback);
});
tabFunc.tap(pluginName, compiler => {
this.replaceTemplateFile(compiler);
});
compiler.hooks.done.tap(pluginName, () =>
this.recoverTemplateFile(compiler),
);
}
runSSRBuild(compiler: Compiler, callback: () => void) {
const mode = compiler.options.mode;
if (mode !== 'development') {
callback();
return;
}
const buildProcess = childProcess.spawn('yarn', [
'build:ssr',
`--mode=${mode}`,
]);
buildProcess.stdout.on('data', process.stdout.write);
buildProcess.stderr.on('data', process.stderr.write);
buildProcess.on('close', function (code) {
if (code === 0) {
callback();
} else {
throw new Error(`Generate SSR content failed with code ${code}`);
}
});
}
replaceTemplateFile(compiler: Compiler) {
const token = this.options.token;
const context = compiler.context;
const templateContent = this.templateContent;
const ssrFilePath = path.resolve(context, './dist/ssr/ssr.bundle.js');
// eslint-disable-next-line @typescript-eslint/no-var-requires
const getSSRContent = require(ssrFilePath).default;
delete require.cache[require.resolve(ssrFilePath)];
const ssrContent = getSSRContent();
const newTemplateContent = templateContent.replace(token, ssrContent);
writeFileSync(
path.resolve(context, './html/index.html'),
newTemplateContent,
{
encoding: 'utf-8',
},
);
}
recoverTemplateFile(compiler: Compiler) {
const context = compiler.context;
const templateContent = this.templateContent;
writeFileSync(path.resolve(context, './html/index.html'), templateContent, {
encoding: 'utf-8',
});
}
}

export default RspackSSRPlugin;
13 changes: 5 additions & 8 deletions rspack.base.config.ts → tools/rspack.base.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,18 @@ import type { Configuration } from '@rspack/cli';

export default function createBaseRspackConfig(): Configuration {
return {
context: __dirname,
entry: {
main: './src/main.tsx',
},
context: path.resolve(__dirname, '..'),
output: {
path: path.resolve(__dirname, 'dist'),
path: './dist',
filename: '[name].[contenthash:8].bundle.js',
chunkFilename: '[name].[contenthash:8].bundle.js',
cssChunkFilename: '[name].[contenthash:8].bundle.js',
},
resolve: {
alias: {
'@config': path.resolve(__dirname, './config'),
'@problems': path.resolve(__dirname, './problems'),
'@src': path.resolve(__dirname, './src'),
'@config': './config',
'@problems': './problems',
'@src': './src',
},
},
builtins: {
Expand Down
24 changes: 12 additions & 12 deletions rspack.config.ts → tools/rspack.config.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import path from 'path';
import type { Configuration } from '@rspack/cli';
import { ArcoDesignPlugin } from '@arco-plugins/unplugin-react';
import { CopyRspackPlugin, DefinePlugin } from '@rspack/core';
import HtmlRspackPlugin from '@rspack/plugin-html';
import { CopyRspackPlugin, DefinePlugin } from '@rspack/core';
import { ArcoDesignPlugin } from '@arco-plugins/unplugin-react';
import RspackSSRPlugin from './RspackSSRPlugin';
import createBaseRspackConfig from './rspack.base.config';

export default function createRspackConfig(): Configuration {
const baseConfig = createBaseRspackConfig();
const mode = process.env.NODE_ENV as Configuration['mode'];
// eslint-disable-next-line @typescript-eslint/no-var-requires
const getSSRContent = require(
path.resolve(__dirname, 'dist/ssr/ssr.bundle.js'),
).default;
const ssrContent = getSSRContent();
const template = './html/index.html';
return {
...baseConfig,
mode,
Expand All @@ -21,17 +17,21 @@ export default function createRspackConfig(): Configuration {
main: './src/main.tsx',
},
devtool: mode === 'production' ? false : 'source-map',
watchOptions: {
ignored: template,
},
plugins: [
new RspackSSRPlugin({
template,
token: '{% ROOT_CONTENT %}',
}),
new HtmlRspackPlugin({
template,
minify: true,
sri: 'sha256',
inject: 'body',
scriptLoading: 'defer',
favicon: './assets/favicon.png',
template: './html/index.html',
templateParameters: {
ROOT_CONTENT: ssrContent,
},
}),
new CopyRspackPlugin({
patterns: [
Expand Down
3 changes: 1 addition & 2 deletions rspack.ssr.config.ts → tools/rspack.ssr.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import path from 'path';
import type { Configuration } from '@rspack/cli';
import { HtmlRspackPlugin, DefinePlugin } from '@rspack/core';
import createBaseRspackConfig from './rspack.base.config';
Expand All @@ -14,7 +13,7 @@ export default function createSSRRspackConfig(): Configuration {
ssr: './src/ssr.tsx',
},
output: {
path: path.resolve(__dirname, 'dist/ssr'),
path: './dist/ssr',
filename: 'ssr.bundle.js',
library: {
type: 'commonjs',
Expand Down

0 comments on commit ba7ca12

Please sign in to comment.