Skip to content
This repository has been archived by the owner on Nov 28, 2022. It is now read-only.

Commit

Permalink
Merge pull request #224 from readmeio/update/lazy-load
Browse files Browse the repository at this point in the history
♻️ be more selective about which docs to lazy render
  • Loading branch information
erunion authored Jun 26, 2019
2 parents bdb3a1e + b138213 commit 5e58131
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 31 deletions.
54 changes: 54 additions & 0 deletions packages/api-explorer/__tests__/index.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,60 @@ describe('auth', () => {
expect(explorer.state('auth')).toEqual({ api_key: '123456', petstore_auth: '' });
});

it('should return nothing for lazy + `splitReferenceDocs`', () => {
const explorer = shallow(<ApiExplorer {...props} appearance={{ splitReferenceDocs: true }} />);

const { lazyHash } = explorer.instance();
expect(lazyHash).toEqual({});
});

it('should disable lazy render first 5 projects', () => {
const explorer = shallow(<ApiExplorer {...props} />);

const { lazyHash } = explorer.instance();
expect(lazyHash[0]).toEqual(false);
expect(lazyHash[1]).toEqual(false);
expect(lazyHash[2]).toEqual(false);
expect(lazyHash[3]).toEqual(false);
expect(lazyHash[4]).toEqual(false);
expect(lazyHash[5]).toEqual(true);
});

it('should disable lazy render middle 5 projects', () => {
// somewhere in the middle of props.docs
window.history.pushState({}, '', '/#user-createWithArray');
const explorer = shallow(<ApiExplorer {...props} />);

const instance = explorer.instance();
const slugs = instance.props.docs.map(x => x.slug);
const centerIdx = slugs.indexOf('user-createWithArray');

expect(instance.lazyHash[centerIdx - 3]).toEqual(true);
expect(instance.lazyHash[centerIdx - 2]).toEqual(false);
expect(instance.lazyHash[centerIdx - 1]).toEqual(false);
expect(instance.lazyHash[centerIdx]).toEqual(false);
expect(instance.lazyHash[centerIdx + 1]).toEqual(false);
expect(instance.lazyHash[centerIdx + 2]).toEqual(false);
expect(instance.lazyHash[centerIdx + 3]).toEqual(true);
});

it('should disable lazy render for last 5 projects', () => {
// last doc in props.docs
window.history.pushState({}, '', '/#user-username');
const explorer = shallow(<ApiExplorer {...props} />);

const instance = explorer.instance();
const slugs = instance.props.docs.map(x => x.slug);
const centerIdx = slugs.indexOf('user-username');

expect(instance.lazyHash[centerIdx - 3]).toEqual(true);
expect(instance.lazyHash[centerIdx - 2]).toEqual(false);
expect(instance.lazyHash[centerIdx - 1]).toEqual(false);
expect(instance.lazyHash[centerIdx]).toEqual(false);
expect(instance.lazyHash[centerIdx + 1]).toEqual(false);
expect(instance.lazyHash[centerIdx + 2]).toEqual(false);
});

it('should default to empty string', () => {
const explorer = shallow(<ApiExplorer {...props} />);

Expand Down
5 changes: 4 additions & 1 deletion packages/api-explorer/lib/create-docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ module.exports = (oas, apiSetting) => {
docs.push({
_id: Math.random().toString(16),
title: operation.summary || path || tag,
slug: tag,
slug: path
.replace(/^\W|\W$/, '')
.replace(/\W+/g, '-')
.replace(/^\W|\W$/, ''),
type: 'endpoint',
category: { apiSetting },
api: {
Expand Down
31 changes: 9 additions & 22 deletions packages/api-explorer/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 11 additions & 7 deletions packages/api-explorer/src/Doc.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -289,17 +289,19 @@ class Doc extends React.Component {
}

render() {
const { doc } = this.props;
const { doc, lazy } = this.props;
const oas = this.oas;

const renderEndpoint = () => {
if (this.props.appearance.splitReferenceDocs) return this.renderEndpoint();

return (
<Waypoint onEnter={this.waypointEntered} fireOnRapidScroll={false} bottomOffset="-1%">
{this.state.showEndpoint && this.renderEndpoint()}
</Waypoint>
);
if (lazy) {
return (
<Waypoint onEnter={this.waypointEntered} fireOnRapidScroll={false} bottomOffset="-1%">
{this.state.showEndpoint && this.renderEndpoint()}
</Waypoint>
);
}
return this.renderEndpoint();
};

return (
Expand Down Expand Up @@ -391,13 +393,15 @@ Doc.propTypes = {
suggestedEdits: PropTypes.bool.isRequired,
tryItMetrics: PropTypes.func.isRequired,
onAuthChange: PropTypes.func.isRequired,
lazy: PropTypes.bool.isRequired,
};

Doc.defaultProps = {
oas: {},
flags: {
correctnewlines: false,
},
lazy: true,
appearance: {
referenceLayout: 'row',
splitReferenceDocs: false,
Expand Down
44 changes: 43 additions & 1 deletion packages/api-explorer/src/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class ApiExplorer extends React.Component {
},
auth: getAuth(this.props.variables.user, this.props.oasFiles),
};

this.lazyHash = this.buildLazyHash();
}

onAuthChange(auth) {
Expand All @@ -53,6 +55,7 @@ class ApiExplorer extends React.Component {
return 'curl';
}
}

getOas(doc) {
// Get the apiSetting id from the following places:
// - category.apiSetting if set and populated
Expand All @@ -67,6 +70,43 @@ class ApiExplorer extends React.Component {
return this.props.oasFiles[apiSetting];
}

/**
* Be a bit more selective of that to lazy render
* @return {Object} Builds a hash of which indexes of this.props.docs should
* be lazy rendered.
*/
buildLazyHash() {
const { splitReferenceDocs } = this.props.appearance;
if (splitReferenceDocs) return {};

const { docs } = this.props;
const range = num => [...Array(num).keys()];

const hash = range(docs.length).reduce((total, idx) => {
total[idx] = true;
return total;
}, {});

// there is no hash, disable lazy rendering for the first 5 docs
if (!window.location.hash) {
range(5).forEach(index => {
hash[index] = false;
});
return hash;
}

// if there is a hash in the URL, disable lazy rendering for the potential slug
// and its neighbors
const slug = window.location.hash.substr(1);
const slugs = this.props.docs.map(x => x.slug);
const indexOfSlug = slugs.indexOf(slug);
const startIndex = indexOfSlug <= 2 ? 0 : indexOfSlug - 2;
range(5).forEach(num => {
hash[startIndex + num] = false;
});
return hash;
}

changeSelected(selected) {
this.setState({ selectedApp: { selected, changeSelected: this.changeSelected } });
}
Expand All @@ -79,7 +119,7 @@ class ApiExplorer extends React.Component {
className={`content-body hub-reference-sticky hub-reference-theme-${this.props.appearance
.referenceLayout}`}
>
{this.props.docs.map(doc => (
{this.props.docs.map((doc, index) => (
<VariablesContext.Provider value={this.props.variables}>
<OauthContext.Provider value={this.props.oauth}>
<GlossaryTermsContext.Provider value={this.props.glossaryTerms}>
Expand All @@ -88,6 +128,7 @@ class ApiExplorer extends React.Component {
<Doc
key={doc._id}
doc={doc}
lazy={this.lazyHash[index]}
oas={this.getOas(doc)}
setLanguage={this.setLanguage}
flags={this.props.flags}
Expand Down Expand Up @@ -119,6 +160,7 @@ ApiExplorer.propTypes = {
oasFiles: PropTypes.shape({}).isRequired,
appearance: PropTypes.shape({
referenceLayout: PropTypes.string,
splitReferenceDocs: PropTypes.bool,
}).isRequired,
flags: PropTypes.shape({
correctnewlines: PropTypes.bool,
Expand Down

0 comments on commit 5e58131

Please sign in to comment.