diff --git a/Routes.js b/Routes.js index 8187706c6..8901b19cd 100644 --- a/Routes.js +++ b/Routes.js @@ -1,6 +1,6 @@ -// import app from './src/App' +import app from './src/App' // import users from './src/forge/users/Index'; -// import Detail from "./src/forge/Main/Detail"; +import Detail from "./src/forge/Main/Detail"; // import Information from "./src/forge/Information/index" // import NewsDetail from './src/forge/Information/Pages/newsDetail'; @@ -18,7 +18,7 @@ export default [ { key:"detail", path: "/:owner/:projectsId", - // component: app, + component: app, } ]; @@ -36,7 +36,7 @@ export const deepRoutes = [ { key: "detail", path: "/:owner/:projectsId", - // component: Detail, + component: Detail, }, { key: "owner", diff --git a/config/webpack.server.js b/config/webpack.server.js index 8b78b83a2..1d1b99eba 100644 --- a/config/webpack.server.js +++ b/config/webpack.server.js @@ -159,12 +159,13 @@ const serverConfig = { { test: /\.scss$/, use: [ - { - loader: MiniCssExtractPlugin.loader, - options: { - publicPath, - }, - }, + 'isomorphic-style-loader', + // { + // loader: MiniCssExtractPlugin.loader, + // options: { + // publicPath, + // }, + // }, { loader: require.resolve("css-loader"), options: { diff --git a/package-lock.json b/package-lock.json index 812eec9a1..09f93831a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11450,7 +11450,7 @@ }, "isomorphic-style-loader": { "version": "5.3.2", - "resolved": "https://registry.npmmirror.com/isomorphic-style-loader/-/isomorphic-style-loader-5.3.2.tgz", + "resolved": "https://registry.npmjs.org/isomorphic-style-loader/-/isomorphic-style-loader-5.3.2.tgz", "integrity": "sha512-5mwHrN2xK5zsKBxSUYF7iDhoU9Kpcpfgn0lFOP0SKk3aKwkl26zi6kh+KDrekjlLzNbYsFnn8o1yWaB3OflVXQ==", "requires": { "hoist-non-react-statics": "^3.0.0", @@ -21603,13 +21603,15 @@ "version": "2.1.1", "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true + "dev": true, + "optional": true }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "optional": true, "requires": { "is-extglob": "^2.1.1" } @@ -21618,7 +21620,8 @@ "version": "3.0.0", "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "dev": true, + "optional": true }, "readdirp": { "version": "3.6.0", diff --git a/server/index.js b/server/index.js index 19427fc64..1e9bab767 100644 --- a/server/index.js +++ b/server/index.js @@ -15,7 +15,7 @@ app.use('/build', express.static('build')); const options = (target) => { return { target: target, - changeOrigin: false, // 允许在请求头中更改主机 + changeOrigin: true, // 允许在请求头中更改主机 timeout: 30000, onProxyRes: (proxyRes, req, res) => { // 代理成功后输出日志 diff --git a/server/render.js b/server/render.js index 4476dbba7..e3e607349 100644 --- a/server/render.js +++ b/server/render.js @@ -1,23 +1,27 @@ -// import React from "react"; -// import {renderToString} from "react-dom/server"; +import React from "react"; +import {renderToString} from "react-dom/server"; import {StaticRouter, matchPath} from "react-router-dom"; -// import {renderRoutes} from "react-router-config"; +import StyleContext from 'isomorphic-style-loader/StyleContext' +import {renderRoutes} from "react-router-config"; import Routes, { deepRoutes, specialRoute } from "../Routes"; -// import { Provider } from "react-redux"; -// import { serverStore } from "../src/redux/stores/configureStore"; +import { Provider } from "react-redux"; +import { serverStore } from "../src/redux/stores/configureStore"; // import App from "../src/App"; // import { Route } from 'react-router-dom'; -// import { setDefaultMeta } from '../src/common/UrlTool' +import { setDefaultMeta } from '../src/common/UrlTool' import Logger from "./log"; import { changeHead } from './setHead' +const css = new Set() // 这个必须在路由函数里面,在外面的话,就会累加出现之前的css +const insertCss = (...styles) => styles.forEach(style => css.add(style._getCss())); + export const render = async (req,res)=>{ let _route = null, _match = null; - // Logger.info(`${req.url} UA:${req.headers['user-agent']}`) + Logger.info(`${req.url} UA:${req.headers['user-agent']}`) - // let store = serverStore(); + let store = serverStore(); function matchSubRoutes(routes, url) { for (const route of routes) { @@ -50,6 +54,44 @@ export const render = async (req,res)=>{ code: 200, }; + + if (_route && _route.component && _route.component.preFetch) { + context = await _route.component.preFetch({ + store, + match: _match, + query: req.path, + }); + } + + const content = renderToString(( + + + + {renderRoutes(Routes)} + {/* */} + + + + )) + + if (!content) { + // 未匹配到详情页恢复默认header + setDefaultMeta() + } else { + // 匹配到服务端渲染页面注入state + let script = domObj.window.document.getElementById('initState') + if (!script) { + script = domObj.window.document.createElement('script') + script.setAttribute('id', 'initState') + } + script.textContent = `window.__initState__ = ${ JSON.stringify(store.getState()) }` + const styleNode = domObj.window.document.createElement('style') + styleNode.type = 'text/css' + styleNode.innerHTML = `${ [...css].join('') }` + domObj.window.document.head.appendChild(script); + domObj.window.document.head.appendChild(styleNode); + } + if (_route && !specialRoute.includes(_match.url && _match.url.replace('/', ''))) { Logger.info(`matchRoot: ${ _match.url }`) await changeHead(_route, _match.params) @@ -58,51 +100,13 @@ export const render = async (req,res)=>{ } - // if (_route && _route.component && _route.component.preFetch) { - // context = await _route.component.preFetch({ - // store, - // match: _match, - // query: req.path, - // }); - // } - - // 暂时不开放ssr,只修改head - // const content = renderToString(( - // - // - // {renderRoutes(Routes)} - // {/* */} - // - // - // )) - - // 暂时不开放ssr,只修改head - // if (!content) { - // // 未匹配到详情页恢复默认header - // setDefaultMeta() - // } else { - // // 匹配到服务端渲染页面注入state - // let script = domObj.window.document.getElementById('initState') - // if (!script) { - // script = domObj.window.document.createElement('script') - // script.setAttribute('id', 'initState') - // } - // script.textContent = `window.__initState__ = ${ JSON.stringify(store.getState()) }` - - // domObj.window.document.head.appendChild(script); - // } - - let html = domObj.serialize() const prepHTML=(data,rootString)=>{ - // 暂时不开放ssr,只修改head - // data=data.replace('
',`
${rootString}
`); + data=data.replace('
',`
${rootString}
`); return data; } - // 暂时不开放ssr,只修改head - // res.send(prepHTML(html, content)) - res.send(prepHTML(html, '')) + res.send(prepHTML(html, content)) - // store = null + store = null } diff --git a/server/setHead.js b/server/setHead.js index 1d9d35886..cdaf072d9 100644 --- a/server/setHead.js +++ b/server/setHead.js @@ -6,15 +6,15 @@ export const changeHead = async ({ key }, params) => { let res let data switch (key) { - case 'detail': - res = await getProjectDetailFunc(params.owner, params.projectsId); - data = res.data - if (data && data.status === 1) { - let keyWords=`${params.owner},${params.projectsId}${ data.topics.length > 0 && ','}${ data.topics.length > 0 && data.topics.map(item => item.name).join(',') }`; - let title= `${params.owner}/${params.projectsId}${data.description?':'+data.description:''}`; - setSeoMeta(keyWords,title,data.description || '',`/${params.owner}/${params.projectsId}`,params.owner,params.projectsId); - } - break; + // case 'detail': + // res = await getProjectDetailFunc(params.owner, params.projectsId); + // data = res.data + // if (data && data.status === 1) { + // let keyWords=`${params.owner},${params.projectsId}${ data.topics.length > 0 && ','}${ data.topics.length > 0 && data.topics.map(item => item.name).join(',') }`; + // let title= `${params.owner}/${params.projectsId}${data.description?':'+data.description:''}`; + // setSeoMeta(keyWords,title,data.description || '',`/${params.owner}/${params.projectsId}`,params.owner,params.projectsId); + // } + // break; case 'zoneNews': res = await getNewsDetail(params.id) data = res.data.data @@ -33,7 +33,7 @@ export const changeHead = async ({ key }, params) => { res = await getOwnerInfo(params.owner); data = res.data const name = data.nickname || data.username - if (data && data.status === 1) { + if (data && data.name) { setSeoMeta(`${name}`, name, data.description || '', `/${params.owner}`) } break; diff --git a/src/App.js b/src/App.js index d44aab6db..34a177917 100644 --- a/src/App.js +++ b/src/App.js @@ -23,6 +23,8 @@ import SiderBarHelp from './glcc/siderBarHelp'; import { SnackbarHOC, configShareForCustom } from 'educoder'; import { initAxiosInterceptors } from './AppConfig' import cookie from 'react-cookies'; +import InfosIndex from './forge/users/Index' +import OrganizeIndex from './forge/Team/Index' window.marked = marked; const theme = createMuiTheme({ @@ -74,15 +76,15 @@ const http500 = Loadable({ loader: () => import('./modules/500/http500'), loading: Loading, }) -const InfosIndex = Loadable({ - loader: () => import('./forge/users/Index'), - loading: Loading, -}) +// const InfosIndex = Loadable({ +// loader: () => import('./forge/users/Index'), +// loading: Loading, +// }) // 组织 -const OrganizeIndex = Loadable({ - loader: () => import('./forge/Team/Index'), - loading: Loading, -}) +// const OrganizeIndex = Loadable({ +// loader: () => import('./forge/Team/Index'), +// loading: Loading, +// }) const Search = Loadable({ loader: () => import('./modules/search/'), diff --git a/src/common/components/comment/CommentForm.js b/src/common/components/comment/CommentForm.js index 4f0692e71..93db885d3 100644 --- a/src/common/components/comment/CommentForm.js +++ b/src/common/components/comment/CommentForm.js @@ -9,7 +9,7 @@ import './index.scss'; import React, { useState } from 'react'; import { Form, Button, Input } from 'antd'; -import QuillForEditor from '../../quillForEditor'; +// import QuillForEditor from '../../quillForEditor'; const FormItem = Form.Item; function CommentForm(props) { @@ -116,7 +116,7 @@ function CommentForm(props) { ) } - + /> */} diff --git a/src/common/educoder.js b/src/common/educoder.js index 96896845a..6ee8787f5 100644 --- a/src/common/educoder.js +++ b/src/common/educoder.js @@ -68,7 +68,7 @@ export { default as ActionBtn } from './course/ActionBtn' export { default as MarkdownToHtml } from './components/markdown/MarkdownToHtml' -export { default as QuillForEditor } from './quillForEditor' +// export { default as QuillForEditor } from './quillForEditor' export { default as Clappr } from './components/media/Clappr' export { default as AliyunUploader } from './components/media/AliyunUploader' diff --git a/src/common/quillForEditor/index.js b/src/common/quillForEditor/index.js index a34a826ca..dda76c612 100644 --- a/src/common/quillForEditor/index.js +++ b/src/common/quillForEditor/index.js @@ -1,7 +1,7 @@ import './index.scss' -import 'quill/dist/quill.core.css' // 核心样式 -import 'quill/dist/quill.snow.css' // 有工具栏 -import 'quill/dist/quill.bubble.css' // 无工具栏 +// import 'quill/dist/quill.core.css' // 核心样式 +// import 'quill/dist/quill.snow.css' // 有工具栏 +// import 'quill/dist/quill.bubble.css' // 无工具栏 import './font.css' import React, { useState, useRef, useEffect } from 'react' import Quill from 'quill' diff --git a/src/forge/Main/CoderDepot.jsx b/src/forge/Main/CoderDepot.jsx index 8205d45d4..5e7cf22cb 100644 --- a/src/forge/Main/CoderDepot.jsx +++ b/src/forge/Main/CoderDepot.jsx @@ -13,7 +13,7 @@ import axios from 'axios'; import Path from './CoderDepotPath'; import Catalogue from './CoderDepotCatalogue'; import ReadMe from './CoderDepotReadme'; -import CoderRootFileDetail from './CoderRootFileDetail'; +// import CoderRootFileDetail from './CoderRootFileDetail'; import './Index.scss'; import Releases from '../Component/Releases'; import Contributors from '../Component/Contributors'; @@ -571,18 +571,18 @@ function CoderDepot(props){ }) } { - fileInfo && - + // fileInfo && + // } diff --git a/src/forge/Main/Detail.js b/src/forge/Main/Detail.js index d33817453..689f8d496 100644 --- a/src/forge/Main/Detail.js +++ b/src/forge/Main/Detail.js @@ -15,6 +15,9 @@ import types from '../../redux/actions/actionTypes' import { getProjectFunc, getProjectDetailFunc } from '../../services/project' import '../css/index.scss' import './list.scss'; +import styles from './list.scss' +import styles1 from '../css/index.scss' +import withStyles from 'isomorphic-style-loader/withStyles'; import Loadable from 'react-loadable'; @@ -980,7 +983,7 @@ Detail.preFetch = ({ store, match, query }) => { }); }; -export default withRouter(connect( +export default withRouter(withStyles(styles, styles1)(connect( mapStateToProps, mapDispatchToProps -)(Detail)); \ No newline at end of file +)(Detail))); \ No newline at end of file diff --git a/src/index.js b/src/index.js index 01ee36c19..24ef80190 100644 --- a/src/index.js +++ b/src/index.js @@ -9,13 +9,17 @@ import { configureUrlQuery } from 'react-url-query'; import history from './history'; import configureStore from './redux/stores/configureStore'; import { Provider } from 'react-redux'; +import StyleContext from 'isomorphic-style-loader/StyleContext' configureUrlQuery({ history }); const store = configureStore(); window.__useKindEditor = false; - +const insertCss = (...styles) => { + const removeCss = styles.map(style => style._insertCss && style._insertCss()); + return () => removeCss.forEach(dispose => dispose && dispose()) +} const render = (Component) => { ReactDOM.hydrate( @@ -24,7 +28,9 @@ const render = (Component) => { - + + +