mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-07 17:44:35 +08:00
site: SSR for official website (#3903)
* site: ssr for Layout * site: SSR for site * fix: ssr for Anchor * chore: add ssr test * chore: update deploy script * site: udpate detail * site: revert animation for site * site: fix loading animation
This commit is contained in:
parent
34f353deb0
commit
4ee2b9d930
@ -87,6 +87,10 @@ class AnchorHelper {
|
|||||||
|
|
||||||
getCurrentAnchor(bounds = 5) {
|
getCurrentAnchor(bounds = 5) {
|
||||||
let activeAnchor = '';
|
let activeAnchor = '';
|
||||||
|
if (typeof document === 'undefined') {
|
||||||
|
return activeAnchor;
|
||||||
|
}
|
||||||
|
|
||||||
this.links.forEach(section => {
|
this.links.forEach(section => {
|
||||||
const target = document.getElementById(section.substring(1));
|
const target = document.getElementById(section.substring(1));
|
||||||
if (target) {
|
if (target) {
|
||||||
|
19
package.json
19
package.json
@ -79,6 +79,10 @@
|
|||||||
"@types/react": "~0.14.41",
|
"@types/react": "~0.14.41",
|
||||||
"@types/react-dom": "~0.14.18",
|
"@types/react-dom": "~0.14.18",
|
||||||
"antd-tools": "0.14.2",
|
"antd-tools": "0.14.2",
|
||||||
|
"babel-cli": "^6.18.0",
|
||||||
|
"babel-preset-es2015": "^6.18.0",
|
||||||
|
"babel-preset-react": "^6.16.0",
|
||||||
|
"babel-preset-stage-0": "^6.16.0",
|
||||||
"babel-eslint": "^7.1.0",
|
"babel-eslint": "^7.1.0",
|
||||||
"babel-jest": "^17.0.0",
|
"babel-jest": "^17.0.0",
|
||||||
"babel-plugin-import": "^1.0.0",
|
"babel-plugin-import": "^1.0.0",
|
||||||
@ -131,8 +135,15 @@
|
|||||||
"typescript-babel-jest": "^0.1.5",
|
"typescript-babel-jest": "^0.1.5",
|
||||||
"values.js": "^1.0.3"
|
"values.js": "^1.0.3"
|
||||||
},
|
},
|
||||||
|
"babel": {
|
||||||
|
"presets": [
|
||||||
|
"es2015",
|
||||||
|
"react",
|
||||||
|
"stage-0"
|
||||||
|
]
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "npm run lint && npm run dist && npm run jest",
|
"test": "npm run lint && npm run dist && npm run jest && npm run site",
|
||||||
"lint": "npm run tslint && npm run eslint && npm run demolint && npm run lesshint",
|
"lint": "npm run tslint && npm run eslint && npm run demolint && npm run lesshint",
|
||||||
"tslint": "antd-tools run ts-lint && npm run compile && rm -rf lib",
|
"tslint": "antd-tools run ts-lint && npm run compile && rm -rf lib",
|
||||||
"eslint": "eslint test site scripts ./.eslintrc.js ./webpack.config.js --ext '.js,.jsx,.tsx' --ignore-pattern '!.eslintrc.js'",
|
"eslint": "eslint test site scripts ./.eslintrc.js ./webpack.config.js --ext '.js,.jsx,.tsx' --ignore-pattern '!.eslintrc.js'",
|
||||||
@ -147,8 +158,10 @@
|
|||||||
"compile": "antd-tools run compile && node ./tests/dekko/lib.test.js",
|
"compile": "antd-tools run compile && node ./tests/dekko/lib.test.js",
|
||||||
|
|
||||||
"start": "bisheng start -c ./site/bisheng.config.js --no-livereload",
|
"start": "bisheng start -c ./site/bisheng.config.js --no-livereload",
|
||||||
"site": "bisheng build -c ./site/bisheng.config.js",
|
"babel-site": "babel ./site/theme/template --out-dir ./site/theme/template",
|
||||||
"deploy": "npm run clean && bisheng gh-pages -c ./site/bisheng.config.js",
|
"clean-site": "rm site/theme/template/**/*.js site/theme/template/*.js",
|
||||||
|
"site": "npm run babel-site && bisheng build --ssr -c ./site/bisheng.config.js && npm run clean-site",
|
||||||
|
"deploy": "npm run clean && npm run site && bisheng gh-pages --push-only",
|
||||||
|
|
||||||
"pub": "antd-tools run update-self && antd-tools run pub",
|
"pub": "antd-tools run update-self && antd-tools run pub",
|
||||||
"prepublish": "antd-tools run guard",
|
"prepublish": "antd-tools run guard",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import appLocaleData from 'react-intl/locale-data/en';
|
const appLocaleData = require('react-intl/locale-data/en');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
locale: 'en-US',
|
locale: 'en-US',
|
||||||
|
@ -101,9 +101,12 @@ div.main-container {
|
|||||||
animation: loadTween 2s cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
|
animation: loadTween 2s cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#react-content:empty + .ant-site-loading {
|
#react-content[hidden] {
|
||||||
|
display: none;
|
||||||
|
+ .ant-site-loading {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#loading-text {
|
#loading-text {
|
||||||
font-family: lato,Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,Arial,sans-serif;
|
font-family: lato,Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,Arial,sans-serif;
|
||||||
|
@ -1 +1,2 @@
|
|||||||
|
import 'react-github-button/assets/style.css';
|
||||||
import './index.less';
|
import './index.less';
|
||||||
|
@ -24,7 +24,9 @@
|
|||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="react-content"></div>
|
<div id="react-content" hidden>
|
||||||
|
{{ content | safe }}
|
||||||
|
</div>
|
||||||
<div class="ant-site-loading" id="ant-site-loading">
|
<div class="ant-site-loading" id="ant-site-loading">
|
||||||
<img src='https://t.alipayobjects.com/images/rmsweb/T1B9hfXcdvXXXXXXXX.svg'/>
|
<img src='https://t.alipayobjects.com/images/rmsweb/T1B9hfXcdvXXXXXXXX.svg'/>
|
||||||
<div id="loading-text">One Design Language</div>
|
<div id="loading-text">One Design Language</div>
|
||||||
@ -32,6 +34,7 @@
|
|||||||
<script>
|
<script>
|
||||||
(function () {
|
(function () {
|
||||||
var content = document.getElementById('loading-text');
|
var content = document.getElementById('loading-text');
|
||||||
|
if (content) {
|
||||||
content.innerHTML = content.innerHTML.split('').map(function (letter, i) {
|
content.innerHTML = content.innerHTML.split('').map(function (letter, i) {
|
||||||
var className;
|
var className;
|
||||||
if (i > 0 && i < content.innerText.length - 1) {
|
if (i > 0 && i < content.innerText.length - 1) {
|
||||||
@ -42,6 +45,7 @@
|
|||||||
}
|
}
|
||||||
return '<span class="' + className + '">' + letter + '</span>';
|
return '<span class="' + className + '">' + letter + '</span>';
|
||||||
}).join('');
|
}).join('');
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// Enable Google Analytics
|
// Enable Google Analytics
|
||||||
|
@ -9,7 +9,7 @@ import config from '../../';
|
|||||||
const SubMenu = Menu.SubMenu;
|
const SubMenu = Menu.SubMenu;
|
||||||
|
|
||||||
function getActiveMenuItem(props) {
|
function getActiveMenuItem(props) {
|
||||||
return props.params.children || props.location.pathname;
|
return props.params.children || props.location.pathname.replace(/^\//, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
function fileNameToPath(filename) {
|
function fileNameToPath(filename) {
|
||||||
@ -120,8 +120,8 @@ export default class MainContent extends React.Component {
|
|||||||
|
|
||||||
getModuleData(props) {
|
getModuleData(props) {
|
||||||
const pathname = props.location.pathname;
|
const pathname = props.location.pathname;
|
||||||
const moduleName = /^components/.test(pathname) ?
|
const moduleName = /^\/?components/.test(pathname) ?
|
||||||
'components' : pathname.split('/').slice(0, 2).join('/');
|
'components' : pathname.split('/').filter(item => item).slice(0, 2).join('/');
|
||||||
const moduleData = moduleName === 'components' || moduleName === 'changelog' || moduleName === 'docs/react' ?
|
const moduleData = moduleName === 'components' || moduleName === 'changelog' || moduleName === 'docs/react' ?
|
||||||
[...props.picked.components, ...props.picked['docs/react'], ...props.picked.changelog] :
|
[...props.picked.components, ...props.picked['docs/react'], ...props.picked.changelog] :
|
||||||
props.picked[moduleName];
|
props.picked[moduleName];
|
||||||
|
@ -5,7 +5,7 @@ import * as utils from '../utils';
|
|||||||
|
|
||||||
const locale = utils.isZhCN() ? 'zh-CN' : 'en-US';
|
const locale = utils.isZhCN() ? 'zh-CN' : 'en-US';
|
||||||
export function collect(nextProps, callback) {
|
export function collect(nextProps, callback) {
|
||||||
const pageData = nextProps.location.pathname === 'changelog' ?
|
const pageData = nextProps.location.pathname.endsWith('changelog') ?
|
||||||
nextProps.data.CHANGELOG : nextProps.pageData;
|
nextProps.data.CHANGELOG : nextProps.pageData;
|
||||||
if (!pageData) {
|
if (!pageData) {
|
||||||
callback(404, nextProps);
|
callback(404, nextProps);
|
||||||
|
@ -3,7 +3,6 @@ import { Link } from 'react-router';
|
|||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import ScrollElement from 'rc-scroll-anim/lib/ScrollElement';
|
import ScrollElement from 'rc-scroll-anim/lib/ScrollElement';
|
||||||
import GitHubButton from 'react-github-button';
|
import GitHubButton from 'react-github-button';
|
||||||
import 'react-github-button/assets/style.css';
|
|
||||||
import { Icon } from 'antd';
|
import { Icon } from 'antd';
|
||||||
import QueueAnim from 'rc-queue-anim';
|
import QueueAnim from 'rc-queue-anim';
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@ import ScrollOverPack from 'rc-scroll-anim/lib/ScrollOverPack';
|
|||||||
import { Icon, Button } from 'antd';
|
import { Icon, Button } from 'antd';
|
||||||
import QueueAnim from 'rc-queue-anim';
|
import QueueAnim from 'rc-queue-anim';
|
||||||
|
|
||||||
const clientHeight = document.documentElement.clientHeight;
|
|
||||||
function onScrollEvent(e) {
|
function onScrollEvent(e) {
|
||||||
|
const clientHeight = document.documentElement.clientHeight;
|
||||||
const header = document.getElementById('header');
|
const header = document.getElementById('header');
|
||||||
if (e.pageY >= clientHeight) {
|
if (e.pageY >= clientHeight) {
|
||||||
if (header.className.indexOf('home-nav-bottom') < 0) {
|
if (header.className.indexOf('home-nav-bottom') < 0) {
|
||||||
|
@ -30,8 +30,10 @@ class Footer extends React.Component {
|
|||||||
// 大版本发布后全局弹窗提示
|
// 大版本发布后全局弹窗提示
|
||||||
// 1. 点击『知道了』之后不再提示
|
// 1. 点击『知道了』之后不再提示
|
||||||
// 2. 超过截止日期后不再提示
|
// 2. 超过截止日期后不再提示
|
||||||
if (localStorage.getItem('antd@2.0.0-notification-sent') !== 'true' &&
|
if (
|
||||||
Date.now() < new Date('2016/10/14').getTime()) {
|
localStorage.getItem('antd@2.0.0-notification-sent') !== 'true' &&
|
||||||
|
Date.now() < new Date('2016/10/14').getTime()
|
||||||
|
) {
|
||||||
this.infoNewVersion();
|
this.infoNewVersion();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,9 +67,8 @@ class Footer extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const options = Object.keys(docVersions).map(version => (
|
const options = Object.keys(docVersions)
|
||||||
<Option value={docVersions[version]} key={version}>{version}</Option>
|
.map(version => <Option value={docVersions[version]} key={version}>{version}</Option>);
|
||||||
));
|
|
||||||
return (
|
return (
|
||||||
<footer id="footer">
|
<footer id="footer">
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React from 'react';
|
import React, { PropTypes } from 'react';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import enquire from 'enquire.js';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Select, Menu, Row, Col, Icon, Button, Popover } from 'antd';
|
import { Select, Menu, Row, Col, Icon, Button, Popover } from 'antd';
|
||||||
|
|
||||||
@ -9,20 +8,18 @@ const Option = Select.Option;
|
|||||||
|
|
||||||
export default class Header extends React.Component {
|
export default class Header extends React.Component {
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: React.PropTypes.object.isRequired,
|
router: PropTypes.object.isRequired,
|
||||||
intl: React.PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
state = {
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
menuMode: 'horizontal',
|
menuMode: 'horizontal',
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
enquire.register('only screen and (min-width: 320px) and (max-width: 940px)', {
|
/* eslint-disable global-require */
|
||||||
|
require('enquire.js')
|
||||||
|
.register('only screen and (min-width: 320px) and (max-width: 940px)', {
|
||||||
match: () => {
|
match: () => {
|
||||||
this.setState({ menuMode: 'inline' });
|
this.setState({ menuMode: 'inline' });
|
||||||
},
|
},
|
||||||
@ -30,6 +27,7 @@ export default class Header extends React.Component {
|
|||||||
this.setState({ menuMode: 'horizontal' });
|
this.setState({ menuMode: 'horizontal' });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
/* eslint-enable global-require */
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSearch = (value) => {
|
handleSearch = (value) => {
|
||||||
@ -51,7 +49,7 @@ export default class Header extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
const { location, picked, isFirstScreen } = this.props;
|
const { location, picked, isFirstScreen } = this.props;
|
||||||
const components = picked.components;
|
const components = picked.components;
|
||||||
const module = location.pathname.replace(/\/$/, '').split('/').slice(0, -1).join('/');
|
const module = location.pathname.replace(/(^\/|\/$)/g, '').split('/').slice(0, -1).join('/');
|
||||||
let activeMenuItem = module || 'home';
|
let activeMenuItem = module || 'home';
|
||||||
if (activeMenuItem === 'components' || location.pathname === 'changelog') {
|
if (activeMenuItem === 'components' || location.pathname === 'changelog') {
|
||||||
activeMenuItem = 'docs/react';
|
activeMenuItem = 'docs/react';
|
||||||
|
@ -8,12 +8,17 @@ import Footer from './Footer';
|
|||||||
import enLocale from '../../en-US';
|
import enLocale from '../../en-US';
|
||||||
import cnLocale from '../../zh-CN';
|
import cnLocale from '../../zh-CN';
|
||||||
import * as utils from '../utils';
|
import * as utils from '../utils';
|
||||||
import '../../static/style';
|
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
/* eslint-disable global-require */
|
||||||
|
require('../../static/style');
|
||||||
|
|
||||||
// Expose to iframe
|
// Expose to iframe
|
||||||
window.react = React;
|
window.react = React;
|
||||||
window['react-dom'] = ReactDOM;
|
window['react-dom'] = ReactDOM;
|
||||||
window.antd = require('antd');
|
window.antd = require('antd');
|
||||||
|
/* eslint-enable global-require */
|
||||||
|
}
|
||||||
|
|
||||||
const appLocale = utils.isZhCN() ? cnLocale : enLocale;
|
const appLocale = utils.isZhCN() ? cnLocale : enLocale;
|
||||||
addLocaleData(appLocale.data);
|
addLocaleData(appLocale.data);
|
||||||
@ -23,12 +28,9 @@ export default class Layout extends React.Component {
|
|||||||
router: React.PropTypes.object.isRequired,
|
router: React.PropTypes.object.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
state = {
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
isFirstScreen: true,
|
isFirstScreen: true,
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if (typeof ga !== 'undefined') {
|
if (typeof ga !== 'undefined') {
|
||||||
@ -43,6 +45,7 @@ export default class Layout extends React.Component {
|
|||||||
loadingNode.parentNode.removeChild(loadingNode);
|
loadingNode.parentNode.removeChild(loadingNode);
|
||||||
}, 450);
|
}, 450);
|
||||||
}
|
}
|
||||||
|
document.getElementById('react-content').removeAttribute('hidden');
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
@ -20,6 +20,10 @@ export function getMenuItems(moduleData, locale) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function isZhCN() {
|
export function isZhCN() {
|
||||||
|
if (typeof location === 'undefined') {
|
||||||
|
// Use English in SSR.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (location.search.indexOf('locale=zh-CN') > -1) {
|
if (location.search.indexOf('locale=zh-CN') > -1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import appLocaleData from 'react-intl/locale-data/zh';
|
const appLocaleData = require('react-intl/locale-data/zh');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
locale: 'zh-CN',
|
locale: 'zh-CN',
|
||||||
|
Loading…
Reference in New Issue
Block a user