Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Proposal] Lazy load views with suspense #749

Merged
merged 33 commits into from
Mar 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
23bcf55
Add lazy loading stuff to field-views-loader
emmatown Mar 1, 2019
7bedfd6
More stuff
emmatown Mar 1, 2019
00d606d
Use render prop for target in withModalHandlers
emmatown Mar 1, 2019
c59050a
Update types
emmatown Mar 1, 2019
6b60302
Fix linting error
emmatown Mar 1, 2019
7534c90
Fix a thing
emmatown Mar 1, 2019
0f364ea
Merge branch 'use-render-prop-in-with-modal-handlers-for-target' into…
emmatown Mar 1, 2019
b56225f
Fix thing
emmatown Mar 1, 2019
f14056e
Merge branch 'use-render-prop-in-with-modal-handlers-for-target' into…
emmatown Mar 1, 2019
ca5eeea
Works in some cases
emmatown Mar 1, 2019
4b51b3d
Fix a thing
emmatown Mar 1, 2019
ddf5997
Add a Suspense component around page content
emmatown Mar 1, 2019
235f4cc
Update CreateItemModal in Relationship field type
emmatown Mar 1, 2019
d5bb27d
Update UpdateManyItemsModal
emmatown Mar 1, 2019
06be86c
Everything is _mostly_ working now
emmatown Mar 1, 2019
f386e97
Fix a thing
emmatown Mar 1, 2019
d5e9a26
Fix some things
emmatown Mar 2, 2019
f85ace9
forwardRef Pill
emmatown Mar 3, 2019
eec9389
Merge branch 'forward-ref-pill' into lazy-load-views-with-suspense
emmatown Mar 3, 2019
6e47707
Fix things
emmatown Mar 3, 2019
ffe1efb
Fix a thing
emmatown Mar 3, 2019
7fd85c5
Add changeset
emmatown Mar 3, 2019
a76099c
Merge branch 'forward-ref-pill' into lazy-load-views-with-suspense
emmatown Mar 3, 2019
a19a7be
Add changeset
emmatown Mar 3, 2019
569d0d8
Add changeset for @arch-ui/layout changes
emmatown Mar 3, 2019
defaa0b
Merge branch 'master' into lazy-load-views-with-suspense
emmatown Mar 6, 2019
f2bfe98
Merge branch 'master' into lazy-load-views-with-suspense
timleslie Mar 10, 2019
f818f9a
Merge branch 'master' into lazy-load-views-with-suspense
emmatown Mar 24, 2019
39f93f5
Add `compression` and change webpack config stuff so it works how it …
emmatown Mar 24, 2019
9f175c1
Change webpack stuff back
emmatown Mar 25, 2019
669d7da
Try a thing to fix the access control tests
emmatown Mar 25, 2019
c6532e3
Merge branch 'master' into lazy-load-views-with-suspense
emmatown Mar 25, 2019
5e215fc
Only do gzipping in prod
emmatown Mar 25, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .changeset/1d357d19/changes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"releases": [
{ "name": "@voussoir/admin-ui", "type": "major" },
{ "name": "@voussoir/fields", "type": "major" },
{ "name": "@voussoir/field-views-loader", "type": "minor" }
],
"dependents": [
{
"name": "keystone_demo_blog",
"type": "patch",
"dependencies": ["@voussoir/core", "@voussoir/admin-ui", "@voussoir/fields"]
},
{
"name": "@voussoir/demo-project-todo",
"type": "patch",
"dependencies": ["@voussoir/core", "@voussoir/admin-ui", "@voussoir/fields"]
},
{
"name": "@voussoir/cypress-project-access-control",
"type": "patch",
"dependencies": ["@voussoir/core", "@voussoir/admin-ui", "@voussoir/fields"]
},
{
"name": "@voussoir/cypress-project-basic",
"type": "patch",
"dependencies": ["@voussoir/core", "@voussoir/admin-ui", "@voussoir/fields"]
},
{
"name": "@voussoir/cypress-project-login",
"type": "patch",
"dependencies": ["@voussoir/core", "@voussoir/admin-ui", "@voussoir/fields"]
},
{
"name": "@voussoir/cypress-project-twitter-login",
"type": "patch",
"dependencies": ["@voussoir/core", "@voussoir/admin-ui", "@voussoir/fields"]
},
{ "name": "@voussoir/core", "type": "patch", "dependencies": ["@voussoir/fields"] }
]
}
1 change: 1 addition & 0 deletions .changeset/1d357d19/changes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Lazy load field type views with suspense
16 changes: 16 additions & 0 deletions .changeset/2ae667cf/changes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"releases": [{ "name": "@arch-ui/layout", "type": "minor" }],
"dependents": [
{
"name": "@voussoir/admin-ui",
"type": "patch",
"dependencies": ["@voussoir/fields", "@arch-ui/filters", "@arch-ui/layout"]
},
{
"name": "@voussoir/fields",
"type": "patch",
"dependencies": ["@arch-ui/filters", "@arch-ui/layout"]
},
{ "name": "@arch-ui/filters", "type": "patch", "dependencies": ["@arch-ui/layout"] }
]
}
1 change: 1 addition & 0 deletions .changeset/2ae667cf/changes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Forward refs passed to FlexGroup to the container element
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"body-parser": "^1.18.2",
"chrono-node": "^1.3.5",
"cloudinary": "^1.13.2",
"compression": "^1.7.4",
"cookie": "^0.3.1",
"cookie-signature": "^1.1.0",
"cors": "^2.8.4",
Expand Down
9 changes: 2 additions & 7 deletions packages/admin-ui/client/apolloClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ import { onError } from 'apollo-link-error';
import { InMemoryCache } from 'apollo-cache-inmemory';
import ApolloClient from 'apollo-client';

import { adminMeta } from './providers/AdminMeta';
const { apiPath } = adminMeta;

const fetch = require('cross-fetch');

// Ejected from apollo-boost v0.1.4:
Expand All @@ -17,7 +14,7 @@ const fetch = require('cross-fetch');
// Then modified to replace apollo-link-http with apollo-upload-client:
// https://github.com/jaydenseric/apollo-upload-client

class BoostClientWithUplaod extends ApolloClient {
class BoostClientWithUpload extends ApolloClient {
constructor(config) {
const cache =
config && config.cacheRedirects
Expand Down Expand Up @@ -83,6 +80,4 @@ class BoostClientWithUplaod extends ApolloClient {
}
}

export default new BoostClientWithUplaod({
uri: apiPath,
});
export default BoostClientWithUpload;
3 changes: 2 additions & 1 deletion packages/admin-ui/client/classes/List.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ export const gqlCountQueries = lists => gql`{
export default class List {
constructor(config, adminMeta, views) {
this.config = config;
this.adminMeta = adminMeta;

// TODO: undo this
Object.assign(this, config);

this.fields = config.fields.map(fieldConfig => {
const { Controller } = views[fieldConfig.path];
const [Controller] = adminMeta.readViews([views[fieldConfig.path].Controller]);
return new Controller(fieldConfig, this, adminMeta, views[fieldConfig.path]);
});

Expand Down
30 changes: 12 additions & 18 deletions packages/admin-ui/client/components/AnimateHeight.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@

/** @jsx jsx */
import { jsx } from '@emotion/core';
import { Component, type Element, type Ref, type Node, useMemo } from 'react';
import { Component, type Ref, type Node, useMemo } from 'react';
import ResizeObserver from 'resize-observer-polyfill';
import NodeResolver from 'react-node-resolver';

type Height = number | string;
type Props = {
autoScroll: boolean | HTMLElement,
children?: Element<*>,
initialHeight: Height,
onChange?: Height => any,
render?: ({ ref: Ref<*> }) => Node,
render: ({ ref: Ref<*> }) => Node,
};
type State = { height: Height, isTransitioning: boolean };

Expand Down Expand Up @@ -88,7 +86,7 @@ export default class AnimateHeight extends Component<Props, State> {
this.calculateHeight();
};
render() {
const { autoScroll, children, initialHeight, render, ...props } = this.props;
const { autoScroll, initialHeight, render, ...props } = this.props;
const { height, isTransitioning } = this.state;
const overflow = isTransitioning ? 'hidden' : null;

Expand All @@ -109,19 +107,15 @@ export default class AnimateHeight extends Component<Props, State> {
}}
{...props}
>
{render ? (
<Memoize
// this.getNode will never change so i'm not including it in the deps
// render will probably change a bunch but that's fine, the reason for
// memoizing this is so that state updates inside of AnimateHeight don't
// cause a bunch of rerenders of children
deps={[render]}
>
{() => render({ ref: this.getNode })}
</Memoize>
) : (
<NodeResolver innerRef={this.getNode}>{children}</NodeResolver>
)}
<Memoize
// this.getNode will never change so i'm not including it in the deps
// render will probably change a bunch but that's fine, the reason for
// memoizing this is so that state updates inside of AnimateHeight don't
// cause a bunch of rerenders of children
deps={[render]}
>
{() => render({ ref: this.getNode })}
</Memoize>
</div>
);
}
Expand Down
26 changes: 19 additions & 7 deletions packages/admin-ui/client/components/CreateItemModal.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** @jsx jsx */
import { jsx } from '@emotion/core';
import { Component, Fragment, useCallback, useMemo } from 'react';
import { Component, Fragment, useCallback, useMemo, Suspense } from 'react';
import { Mutation } from 'react-apollo';

import { Button } from '@arch-ui/button';
Expand Down Expand Up @@ -61,6 +61,16 @@ class CreateItemModal extends Component {
render() {
const { isLoading, isOpen, list } = this.props;
const { item } = this.state;
// we want to read all of the fields before reading the views individually
// note we want to _read_ before not just preload because the important thing
// isn't doing all the requests in parallel, that already happens
// what we're doing here is making sure there aren't a bunch of rerenders as
// each of the promises resolve
// this probably won't be necessary with concurrent mode/maybe just other react changes
// also, note that this is just an optimisation, it's not strictly necessary and it should
// probably be removed in the future because i'm guessing this will make performance _worse_ in concurrent mode
list.adminMeta.readViews(list.fields.map(({ views }) => views.Field));

return (
<Drawer
closeOnBlanketClick
Expand Down Expand Up @@ -89,10 +99,10 @@ class CreateItemModal extends Component {
>
<AutocompleteCaptor />
{list.fields.map((field, i) => {
const { Field } = field.views;
return (
<Render key={field.path}>
{() => {
let [Field] = field.adminMeta.readViews([field.views.Field]);
let onChange = useCallback(value => {
this.setState(({ item }) => ({
item: {
Expand Down Expand Up @@ -129,11 +139,13 @@ export default class CreateItemModalWithMutation extends Component {
render() {
const { list } = this.props;
return (
<Mutation mutation={list.createMutation}>
{(createItem, { loading }) => (
<CreateItemModal createItem={createItem} isLoading={loading} {...this.props} />
)}
</Mutation>
<Suspense fallback={null}>
<Mutation mutation={list.createMutation}>
{(createItem, { loading }) => (
<CreateItemModal createItem={createItem} isLoading={loading} {...this.props} />
)}
</Mutation>
</Suspense>
);
}
}
4 changes: 2 additions & 2 deletions packages/admin-ui/client/components/ListTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,9 @@ class ListRow extends Component {

let content;

const { Cell } = field.views;
if (field.views.Cell) {
const [Cell] = field.adminMeta.readViews([field.views.Cell]);

if (Cell) {
// TODO
// fix this later, creating a react component on every render is really bad
// react will rerender into the DOM on every react render
Expand Down
16 changes: 9 additions & 7 deletions packages/admin-ui/client/components/UpdateManyItemsModal.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { Component, Fragment, useMemo, useCallback } from 'react';
import React, { Component, Fragment, useMemo, useCallback, Suspense } from 'react';
import { Mutation } from 'react-apollo';
import { Button } from '@arch-ui/button';
import Drawer from '@arch-ui/drawer';
Expand Down Expand Up @@ -99,10 +99,10 @@ class UpdateManyModal extends Component {
</FieldInput>
</FieldContainer>
{selectedFields.map((field, i) => {
const { Field } = field.views;
return (
<Render key={field.path}>
{() => {
let [Field] = field.adminMeta.readViews([field.views.Field]);
let onChange = useCallback(value => {
this.setState(({ item }) => ({
item: {
Expand Down Expand Up @@ -140,11 +140,13 @@ export default class UpdateManyModalWithMutation extends Component {
// to update many things all at once. This doesn't appear to be common pattern
// across the board.
return (
<Mutation mutation={list.updateMutation}>
{(updateItem, { loading }) => (
<UpdateManyModal updateItem={updateItem} isLoading={loading} {...this.props} />
)}
</Mutation>
<Suspense fallback={null}>
<Mutation mutation={list.updateMutation}>
{(updateItem, { loading }) => (
<UpdateManyModal updateItem={updateItem} isLoading={loading} {...this.props} />
)}
</Mutation>
</Suspense>
);
}
}
Loading