Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Initial babel plugin * Cache + analyzer * Member analysis * Filter preloader output based on arguments * Handle more edge cases * Import analysis * Add more tests * Track function calls * Add more tests * fix * Support var destructuring with pathCtx * Pattern scanning * Add more tests * Track array iterations * Add tests * Initial devtools commit * fix: build * fix: typescript types
- Loading branch information
Showing
138 changed files
with
13,648 additions
and
1,292 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,3 +15,4 @@ build | |
.env | ||
.envrc | ||
.changelog | ||
.history |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
# gqless compiler | ||
|
||
## What is does | ||
|
||
It takes your sourcecode, and generates a Graph from it.# | ||
|
||
## Options | ||
|
||
Due to the single-file nature of babel, cross-file data references will be tricky to implement. | ||
|
||
### Static analysis IR | ||
|
||
Outputs `[file].data.json` files from your sourcecode. These files will be read by the babel-plugin, to transform the code. | ||
|
||
Limitations: | ||
|
||
- Requires a separate "extraction" step & files. | ||
|
||
See [data/index.data.json](./data/index.data.json) | ||
|
||
### Single-file static analysis | ||
|
||
Works as a babel-plugin. | ||
|
||
Has a static graph of your app. | ||
|
||
Limitations: | ||
|
||
- All graphql-data references should be local to the file, as imports can't be resolved. | ||
|
||
```ts | ||
const useFullName = user => user.firstName + user.lastName | ||
|
||
const User = graphql(({ user }) => { | ||
const fullName = useFullName(user) | ||
return <div>{fullName}</div> | ||
}) | ||
|
||
// => | ||
const App = graphql(({ user }) => { | ||
const fullName = useFullName(user) | ||
return <div>{fullName}</div> | ||
}) | ||
|
||
App[Symbol.preload] = props => { | ||
props.user.firstName | ||
props.user.lastName | ||
} | ||
``` | ||
|
||
### "Dynamic" analysis | ||
|
||
Works as a babel-plugin. | ||
Doesn't actually have a static graph of your app. Relies upon the runtime to generate it. | ||
|
||
Require all functions to have a `Symbol.preload` method on them: | ||
|
||
Limitations: | ||
|
||
- Dead-code removal would be infeasible | ||
|
||
```tsx | ||
const useFullName = user => user.firstName + user.lastName | ||
|
||
const User = graphql(({ user }) => { | ||
const fullName = useFullName(user) | ||
return <div>{fullName}</div> | ||
}) | ||
|
||
// => | ||
|
||
const useFullName = user => { | ||
user.firstName | ||
user.lastName | ||
} | ||
useFullName[Symbol.preload] = user => { | ||
user.firstName | ||
user.lastName | ||
} | ||
|
||
const App = graphql(({ user }) => { | ||
const fullName = useFullName(user)> | ||
return <div>{fullName}</div> | ||
}) | ||
|
||
App[Symbol.preload] = props => { | ||
useFullName[Symbol.preload]?.(props.user) | ||
} | ||
``` | ||
|
||
## Method | ||
|
||
Find all import references to `query` from `./graphql`. | ||
|
||
Iterate over references | ||
|
||
- If referenced inside a function | ||
|
||
## Preloaders | ||
|
||
In order for dead code elimination and lazy-loading to work, a file named `preloaders.js` will be created in the client directory. | ||
|
||
It will take `preload(Component, {})` and convert it into `preloadComponent` (inserting an import from preloaders.js). | ||
|
||
**preloaders.js:** | ||
|
||
```js | ||
export function preloadUserComponent() {} | ||
export function preloadAppComponent() { | ||
preloadUserComponent({}) | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
```ts | ||
preload( | ||
_0 => { | ||
_0.a.name | ||
_0.b.name | ||
}, | ||
// Value of the call arguments, is used to 'refine' output | ||
{ a: data } | ||
) | ||
|
||
// => | ||
const preloadFunc = _0 => { | ||
_0.a?.name | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Method | ||
|
||
Find all references to `preload(Function, {})`, and traverse from there. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# Tracking | ||
|
||
`preload(myFunc, GRAPHQL_DATA)` | ||
|
||
In order to `preload` a function, call information is required. | ||
|
||
```ts | ||
preload( | ||
_0 => { | ||
_0.a.name | ||
_0.b.name | ||
}, | ||
// Value of the call arguments, is used to 'refine' output | ||
{ a: data } | ||
) | ||
|
||
// => | ||
const preloadFunc = _0 => { | ||
const _0a = _0.a | ||
if (_0a) { | ||
_0a.name | ||
} | ||
} | ||
``` | ||
|
||
```ts | ||
preload(_0 => { | ||
_0.a.name | ||
_0.b.name | ||
}, {}) | ||
|
||
// => | ||
const preloadFunc = _0 => {} | ||
``` | ||
|
||
## Preload arguments | ||
|
||
Arguments can be either inline objects, or references: | ||
|
||
```js | ||
{ user }, | ||
{ user: { followers: [user] }} | ||
``` | ||
|
||
When inline objects/arrays are used, output will be refined. | ||
|
||
When references are used, the entire function's output will be produced. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"AppComponent": { | ||
"variables": { | ||
"limit": "10" | ||
}, | ||
"data": [ | ||
{ | ||
"file": "UserComponent.json", | ||
"export": "UserComponent", | ||
"args": [ | ||
{ | ||
"user": "query.users({ limit: var.limit }).0" | ||
} | ||
] | ||
} | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"DescriptionComponent": { | ||
"data": ["0.user.description"] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"UserComponent": { | ||
"data": [ | ||
"query.me.name", | ||
{ | ||
"file": "useFullName.json", | ||
"export": "useFullName", | ||
"args": ["0.user"] | ||
}, | ||
{ | ||
"file": "DescriptionComponent.json", | ||
"export": "DescriptionComponent", | ||
"args": [{ "user": "0.user" }] | ||
} | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
["AppComponent.json", "./UserComponent.json"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"useFullName": { | ||
"data": ["0.firstName", "0.lastName"] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { query } from './client' | ||
import { UserComponent } from './UserComponent' | ||
import { useVariable } from '@gqless/react' | ||
|
||
export function AppComponent() { | ||
const limit = useVariable(window.asd ? 0 : 10) | ||
|
||
return ( | ||
<div> | ||
{query.users({ limit }).map(user => ( | ||
<UserComponent user={user} /> | ||
))} | ||
</div> | ||
) | ||
} | ||
|
||
export function preloadAppComponent() { | ||
const limit = window.asd ? 0 : 10 | ||
|
||
const user = query.users({ limit })[0] | ||
preloadUserComponent({ user }) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
type Import = { | ||
file: string | ||
import: string | ||
args?: any[] | ||
} | ||
|
||
type Data = (Import | string)[] | ||
|
||
export type DataJSON = Record< | ||
string, | ||
{ | ||
data: Data | ||
variables?: Record<string, string | number | boolean> | ||
} | ||
> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
const getDescription = user => user.description | ||
|
||
export function DescriptionComponent({ user }) { | ||
// Same-file functions are flattened into an export | ||
return getDescription(user) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { query } from './client' | ||
import { DescriptionComponent } from './DescriptionComponent' | ||
import { useFullName } from './useFullName' | ||
|
||
export function UserComponent({ user }) { | ||
const fullName = useFullName(user) | ||
|
||
return ( | ||
<div> | ||
{query.me.name} | ||
{fullName} | ||
<DescriptionComponent user={user} /> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from './AppComponent' | ||
export * from './UserComponent' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export const useFullName = user => { | ||
user.firstName + user.lastName | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import * as React from 'react' | ||
import { query } from './gqless' | ||
|
||
const UserComponent = graphql(({ user }) => { | ||
return <div>{user.name}</div> | ||
}) | ||
UserComponent.preload = ({ user }) => { | ||
user.name | ||
} | ||
|
||
const App = graphql(() => { | ||
return ( | ||
<div> | ||
<UserComponent user={query.me} /> | ||
</div> | ||
) | ||
}) | ||
|
||
App.preload() | ||
UserComponent.preload({ user: query.me }) |
Oops, something went wrong.