Skip to content

Commit 050ac95

Browse files
committed
Fix SSR Errors and implement markdown render on SSR
1 parent 1e6856d commit 050ac95

19 files changed

+309
-139
lines changed

config/webpack.config.server.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const cssRegex = /\.css$/;
77
const cssModuleRegex = /\.module\.css$/;
88
const sassRegex = /\.(scss|sass)$/;
99
const sassModuleRegex = /\.module\.(scss|sass)$/;
10+
const path = require('path');
1011

1112
const imageInlineSizeLimit = parseInt(
1213
process.env.IMAGE_INLINE_SIZE_LIMIT || '10000',
@@ -22,7 +23,7 @@ module.exports = {
2223
output: {
2324
path: paths.ssrBuild,
2425
filename: 'server.js',
25-
chunkFilename: 'js/[name].chuk.js',
26+
chunkFilename: 'js/[name].chunk.js',
2627
publicPath: paths.servedPath,
2728
},
2829
module: {
@@ -133,9 +134,22 @@ module.exports = {
133134
.map(ext => `.${ext}`)
134135
.filter(ext => true || !ext.includes('ts')),
135136
},
136-
plugins: [new webpack.DefinePlugin(env.stringified)],
137+
plugins: [
138+
new webpack.DefinePlugin(env.stringified),
139+
new webpack.NormalModuleReplacementPlugin(
140+
/codemirror/,
141+
path.resolve(paths.appSrc, 'lib/replacedModule.ts'),
142+
),
143+
],
137144
optimization: {
138145
minimize: false,
139146
},
140-
externals: [nodeExternals()],
147+
externals: [
148+
nodeExternals({
149+
whitelist: [/codemirror/, /\.css$/],
150+
}),
151+
],
152+
node: {
153+
__dirname: false,
154+
},
141155
};

package.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"@apollo/react-ssr": "^3.1.3",
99
"@apollo/react-testing": "^3.1.3",
1010
"@babel/core": "7.7.4",
11+
"@koa/router": "^8.0.5",
1112
"@loadable/babel-plugin": "^5.11.0",
1213
"@loadable/component": "^5.11.0",
1314
"@loadable/server": "^5.11.0",
@@ -19,10 +20,13 @@
1920
"@types/date-fns": "^2.6.0",
2021
"@types/jest": "^24.0.0",
2122
"@types/koa": "^2.11.0",
23+
"@types/koa-bodyparser": "^4.3.0",
2224
"@types/koa-static": "^4.0.1",
25+
"@types/koa__router": "^8.0.2",
2326
"@types/loadable__component": "^5.10.0",
2427
"@types/loadable__server": "^5.9.1",
2528
"@types/node": "^12.0.0",
29+
"@types/node-fetch": "^2.5.4",
2630
"@types/qs": "^6.9.0",
2731
"@types/ramda": "^0.26.38",
2832
"@types/react": "^16.9.0",
@@ -70,8 +74,11 @@
7074
"jest-resolve": "24.9.0",
7175
"jest-watch-typeahead": "0.4.2",
7276
"koa": "^2.11.0",
77+
"koa-better-http-proxy": "^0.2.4",
78+
"koa-bodyparser": "^4.2.1",
7379
"koa-static": "^5.0.0",
7480
"mini-css-extract-plugin": "0.8.0",
81+
"node-fetch": "^2.6.0",
7582
"optimize-css-assets-webpack-plugin": "5.0.3",
7683
"pnp-webpack-plugin": "1.5.0",
7784
"postcss-flexbugs-fixes": "4.1.0",
@@ -126,6 +133,7 @@
126133
"start": "node scripts/start.js",
127134
"build": "node scripts/build.js",
128135
"build:server": "node scripts/build.server.js",
136+
"start:server:local": "node ./dist/server.js",
129137
"test": "node scripts/test.js"
130138
},
131139
"eslintConfig": {
@@ -200,7 +208,9 @@
200208
"presets": [
201209
"react-app"
202210
],
203-
"plugins": ["@loadable/babel-plugin"]
211+
"plugins": [
212+
"@loadable/babel-plugin"
213+
]
204214
},
205215
"proxy": "http://localhost:5000",
206216
"devDependencies": {

scripts/build.server.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Do this as the first thing so that any code reading it knows the right env.
22
process.env.BABEL_ENV = 'production';
33
process.env.NODE_ENV = 'production';
4+
process.env.REACT_APP_SSR = 'enabled';
45

56
// Makes the script crash on unhandled rejections instead of silently
67
// ignoring them. In the future, promise rejections that are not handled will
@@ -17,15 +18,14 @@ const config = require('../config/webpack.config.server');
1718
const paths = require('../config/paths');
1819

1920
function build() {
20-
const compiler = webpack(config);
21+
const compiler = webpack({ ...config });
2122
fs.emptyDirSync(paths.ssrBuild);
2223
return new Promise((resolve, reject) => {
2324
compiler.run((err, stats) => {
2425
if (err) {
2526
console.log(err);
2627
return;
2728
}
28-
console.log(stats.toString());
2929
});
3030
});
3131
}

src/App.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,31 +11,31 @@ import PageTemplate from './components/base/PageTemplate';
1111
import VelogPageFallback from './containers/velog/VelogPageFallback';
1212

1313
const loadableConfig = {
14-
fallback: <PageTemplate />
14+
fallback: <PageTemplate />,
1515
};
1616

1717
const VelogPage = loadable(() => import('./pages/velog/VelogPage'), {
18-
fallback: <VelogPageFallback />
18+
fallback: <VelogPageFallback />,
1919
});
2020
const MainPage = loadable(
2121
() => import('./pages/main/MainPage'),
22-
loadableConfig
22+
loadableConfig,
2323
);
2424
const EmailLoginPage = loadable(
2525
() => import('./pages/EmailLoginPage'),
26-
loadableConfig
26+
loadableConfig,
2727
);
2828
const WritePage = loadable(() => import('./pages/WritePage'), loadableConfig);
2929
const SearchPage = loadable(() => import('./pages/SearchPage'), loadableConfig);
3030
const SavesPage = loadable(() => import('./pages/SavesPage'), loadableConfig);
3131
const TagsPage = loadable(
3232
() => import('./pages/tags/TagsPage'),
33-
loadableConfig
33+
loadableConfig,
3434
);
3535
const PolicyPage = loadable(() => import('./pages/PolicyPage'), loadableConfig);
3636
const SettingPage = loadable(
3737
() => import('./pages/SettingPage'),
38-
loadableConfig
38+
loadableConfig,
3939
);
4040

4141
interface AppProps {}

src/components/common/MarkdownEditor.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
import React, { CSSProperties, useRef, useEffect, useCallback } from 'react';
22
import styled from 'styled-components';
33
import CodeMirror, { EditorFromTextArea, Editor } from 'codemirror';
4-
5-
import 'codemirror/lib/codemirror.css';
64
import './atom-one-light.css';
5+
import 'codemirror/lib/codemirror.css';
76
import palette from '../../lib/styles/palette';
8-
9-
// conditional require later on
10-
require('codemirror/mode/markdown/markdown');
11-
require('codemirror/addon/display/placeholder');
7+
import 'codemirror/mode/markdown/markdown';
8+
import 'codemirror/addon/display/placeholder';
129

1310
const MarkdownEditorBlock = styled.div`
1411
.CodeMirror {

src/components/common/MarkdownRender.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import prismThemes from '../../lib/styles/prismThemes';
88
import breaks from 'remark-breaks';
99
import Typography from './Typography';
1010
import embedPlugin from '../../lib/remark/embedPlugin';
11-
import { loadScript } from '../../lib/utils';
11+
import { loadScript, ssrEnabled } from '../../lib/utils';
1212
import media from '../../lib/styles/media';
1313

1414
export interface MarkdownRenderProps {
@@ -83,11 +83,22 @@ const MarkdownRender: React.FC<MarkdownRenderProps> = ({
8383
codeTheme = 'atom-one-light',
8484
onConvertFinish,
8585
}) => {
86-
const [html, setHtml] = useState('');
86+
const initialHtml = ssrEnabled
87+
? remark()
88+
.use(breaks)
89+
.use(prismPlugin)
90+
.use(htmlPlugin)
91+
.use(embedPlugin)
92+
.use(slug)
93+
.processSync(markdown)
94+
.toString()
95+
: '';
96+
97+
const [html, setHtml] = useState(initialHtml);
8798
useEffect(() => {
8899
remark()
89100
.use(breaks)
90-
.use(prismPlugin)
101+
// .use(prismPlugin)
91102
.use(htmlPlugin)
92103
.use(embedPlugin)
93104
.use(slug)

src/containers/etc/EmailLogin.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import { connect } from 'react-redux';
33
import { withRouter, RouteComponentProps } from 'react-router';
44
import qs from 'qs';
55
import { emailCodeLogin } from '../../lib/api/auth';
6-
import client from '../../lib/graphql/client';
76
import { GET_CURRENT_USER, CurrentUser } from '../../lib/graphql/user';
87
import storage from '../../lib/storage';
98
import { RootState } from '../../modules';
109
import { setUser } from '../../modules/core';
10+
import { useApolloClient } from '@apollo/react-hooks';
1111

1212
const mapStateToProps = (state: RootState) => ({});
1313
const mapDispatchToProps = {
@@ -29,6 +29,7 @@ const { useEffect, useCallback } = React;
2929
*/
3030
const EmailLogin: React.FC<EmailLoginProps> = ({ location, history }) => {
3131
const query = qs.parse(location.search, { ignoreQueryPrefix: true });
32+
const client = useApolloClient();
3233
const processLogin = useCallback(async () => {
3334
try {
3435
await emailCodeLogin(query.code);
@@ -43,7 +44,7 @@ const EmailLogin: React.FC<EmailLoginProps> = ({ location, history }) => {
4344
// TODO: show 401
4445
history.replace('/');
4546
}
46-
}, [history, query.code]);
47+
}, [client, history, query.code]);
4748
useEffect(() => {
4849
if (!query.code) {
4950
// TODO: show 404

src/containers/velog/ConfigLoader.tsx

Lines changed: 0 additions & 80 deletions
This file was deleted.
Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,14 @@
11
import React from 'react';
22
import VelogPageTemplate from '../../components/velog/VelogPageTemplate';
3-
import { useDispatch } from 'react-redux';
43
import { useParams } from 'react-router';
5-
import ConfigLoader from './ConfigLoader';
4+
import useApplyVelogConfig from './hooks/useApplyVelogConfig';
65

76
export type VelogPageFallbackProps = {};
87

98
function VelogPageFallback(props: VelogPageFallbackProps) {
10-
const dispatch = useDispatch();
119
const params = useParams<{ username: string }>();
12-
13-
return (
14-
<VelogPageTemplate>
15-
<ConfigLoader username={params.username} />
16-
</VelogPageTemplate>
17-
);
10+
useApplyVelogConfig(params.username);
11+
return <VelogPageTemplate></VelogPageTemplate>;
1812
}
1913

2014
export default VelogPageFallback;

0 commit comments

Comments
 (0)