Skip to content

Commit

Permalink
file-size optimisation
Browse files Browse the repository at this point in the history
  • Loading branch information
gwyneplaine committed May 7, 2021
1 parent a52f1c4 commit faf93ba
Show file tree
Hide file tree
Showing 17 changed files with 502 additions and 101 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,5 @@ package-lock.json

# Notes
.NOTES.md

magical-types
11 changes: 1 addition & 10 deletions docs/PropTypes/Async.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1 @@
import { Component } from 'react';

import { AsyncProps } from 'react-select/src/Async';
import { GroupBase, OptionBase } from 'react-select';

export default class Select<
Option extends OptionBase,
IsMulti extends boolean,
Group extends GroupBase<Option>
> extends Component<AsyncProps<Option, IsMulti, Group>> {}
export { AsyncAdditionalProps } from 'react-select/src/useAsync';
11 changes: 1 addition & 10 deletions docs/PropTypes/Creatable.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1 @@
import { Component } from 'react';

import { CreatableProps } from 'react-select/src/Creatable';
import { GroupBase, OptionBase } from 'react-select';

export default class Select<
Option extends OptionBase,
IsMulti extends boolean,
Group extends GroupBase<Option>
> extends Component<CreatableProps<Option, IsMulti, Group>> {}
export { CreatableAdditionalProps } from 'react-select/src/useCreatable';
43 changes: 43 additions & 0 deletions docs/components/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useEffect, useState } from 'react';
import { MagicalNode, MagicalNodeIndex } from '@magical-types/types';
import { deserialize } from '@magical-types/serialization/deserialize';

export type MagicalNodeMetadata = Record<
string,
Record<string, { type: 'component' | 'other'; index: MagicalNodeIndex }>
>;

export type MagicalNodesForPackage = Record<
string,
{ type: 'component' | 'other'; node: MagicalNode }
>;

export type MagicalNodes = Record<string, MagicalNodesForPackage>;

// @ts-ignore
import manifest from '../magical-types/magical-types-manifest.json';

let getNode: ((index: MagicalNodeIndex) => MagicalNode) | undefined;

export const metadata: MagicalNodeMetadata = (manifest as any).types;

export function useMagicalNodes() {
let [, forceUpdate] = useState(0);

useEffect(() => {
if (!getNode) {
fetch(manifest.paths[0])
.then((x) => x.json())
.then((firstNodeGroup) => {
getNode = deserialize([
firstNodeGroup,
...(manifest.paths as string[])
.slice(1)
.map((path) => () => fetch(path).then((x) => x.json())),
]);
forceUpdate(1);
});
}
}, []);
return getNode;
}
6 changes: 6 additions & 0 deletions docs/generate-magical-types/generate/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"main": "dist/generate-magical-types.cjs.js",
"preconstruct": {
"source": "../src/generate"
}
}
20 changes: 20 additions & 0 deletions docs/generate-magical-types/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "@react-select/generate-magical-types",
"main": "dist/generate-magical-types.cjs.js",
"//": "these deps aren't real, they're just to appease preconstruct",
"dependencies": {
"@babel/runtime": "*",
"@magical-types/convert-type": "*",
"@magical-types/serialization": "*",
"ts-morph": "*",
"fs-extra": "*",
"flatted": "*"
},
"preconstruct": {
"entrypoints": [
"generate",
"serialize",
"types"
]
}
}
6 changes: 6 additions & 0 deletions docs/generate-magical-types/serialize/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"main": "dist/generate-magical-types.cjs.js",
"preconstruct": {
"source": "../src/serialize"
}
}
113 changes: 113 additions & 0 deletions docs/generate-magical-types/src/generate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import path from 'path';

// @ts-ignore
import fs from 'fs-extra';
import * as flatted from 'flatted';
import { Project } from 'ts-morph';
import { MagicalNode } from '@magical-types/types';
import { convertType, getPropTypesType } from '@magical-types/convert-type';
// import { AsyncProps } from '../../PropTypes/Async';
// import { CreatableProps } from '../../PropTypes/Creatable';

type MagicalNodesForPackage = Record<
string,
{ type: 'component' | 'other'; node: MagicalNode }
>;

export type MagicalNodes = Record<string, MagicalNodesForPackage>;

const OTHERFILES: string[] = ['Async', 'Creatable'];
const getOtherProps = (obj: MagicalNodes) => {
OTHERFILES.forEach((name: string) => {
let pkgExports: MagicalNodesForPackage = {};
obj[`${name}`] = pkgExports;
let sourceFile = project.getSourceFile(
path.join(__dirname, '../../Proptypes', `${name}.ts`)
);
if (!sourceFile) {
sourceFile = project.getSourceFile(
path.join(__dirname, '../../Proptypes', `${name}.tsx`)
);
}
if (!sourceFile) {
throw new Error(`source file not found for ${name}`);
}
resolveTypes({ sourceFile, item: name, pkgExports });
});
};

const resolveTypes = ({
sourceFile,
item,
pkgExports,
}: {
sourceFile: any;
item: string;
pkgExports: MagicalNodesForPackage;
}) => {
let exportedDeclarations = sourceFile.getExportedDeclarations();
for (const [exportName, declaration] of exportedDeclarations) {
if (item === 'icon' && exportName !== 'IconProps') continue;
if (declaration.length) {
let type = declaration[0].getType().compilerType;
let typeKind: 'component' | 'other' = 'other';
console.log(`about to convert ${exportName} from ${item}`);
if (exportName[0].toUpperCase() === exportName[0]) {
try {
type = getPropTypesType(type);
typeKind = 'component';
} catch (err) {}
}
pkgExports[exportName] = {
node: convertType(type, []),
type: typeKind,
};
console.log(`converted`);
}
}
};

let project = new Project({
addFilesFromTsConfig: true,
tsConfigFilePath: path.resolve(__dirname, '../../../tsconfig.json'),
});
console.log('done');
let pkgDir = path.resolve(__dirname, '../../../packages');
let pkgs = fs
.readdirSync(pkgDir, {
withFileTypes: true,
})
.filter(
// @ts-ignore
(x) =>
x.isDirectory() &&
fs.existsSync(path.join(pkgDir, path.join(x.name), 'package.json'))
)
// @ts-ignore
.map((x) => x.name);

let obj: MagicalNodes = {};

for (const item of pkgs) {
let pkgExports: MagicalNodesForPackage = {};
obj[`${item}`] = pkgExports;
let sourceFile = project.getSourceFile(
path.join(pkgDir, item, 'src', 'index.tsx')
);
if (!sourceFile) {
sourceFile = project.getSourceFile(
path.join(pkgDir, item, 'src', 'index.ts')
);
}
if (!sourceFile) {
throw new Error(`source file not found for ${item}`);
}
resolveTypes({ sourceFile, item, pkgExports });
}

getOtherProps(obj);

fs.outputFileSync(
path.join(__dirname, '..', 'dist', 'magical-types.json'),
flatted.stringify(obj)
);
107 changes: 107 additions & 0 deletions docs/generate-magical-types/src/serialize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import path from 'path';

// @ts-ignore
import fs from 'fs-extra';
import * as flatted from 'flatted';
import {
chunkNodes,
serializeNodes,
} from '@magical-types/serialization/serialize';

// import { MagicalNodeMetadata, MagicalNodes } from './types';

import { MagicalNode, MagicalNodeIndex } from '@magical-types/types';

export type MagicalNodeMetadata = Record<
string,
Record<string, { type: 'component' | 'other'; index: MagicalNodeIndex }>
>;

export type MagicalNodesForPackage = Record<
string,
{ type: 'component' | 'other'; node: MagicalNode }
>;

export type MagicalNodes = Record<string, MagicalNodesForPackage>;

const allTypes: MagicalNodes = flatted.parse(
fs.readFileSync(
path.join(__dirname, '..', 'dist', 'magical-types.json'),
'utf8'
)
);

const staticDir = path.resolve(__dirname, '..', '..', 'magical-types');

// this is where gatsby copies the static directory to
// it doesn't clear it though, so this prevents it from growing forever
// fs.removeSync(path.resolve(__dirname, '..', '..', 'public', 'magical-types'));

fs.removeSync(staticDir);

fs.ensureDirSync(staticDir);

let rootNodes: MagicalNode[] = [];

for (const pkgName in allTypes) {
for (const exportName in allTypes[pkgName]) {
rootNodes.push(allTypes[pkgName][exportName].node);
}
}

console.log('serializing nodes');
const serializationResult = serializeNodes(rootNodes);
console.log('done');

console.log('chunking nodes');
const chunkedNodes = chunkNodes(serializationResult);
console.log('done');

let outputPaths = chunkedNodes.map((x, index) =>
path.join(
staticDir,
`magical-types-${index}-${Math.random().toString(36)}.json`
)
);

let outputUrlSegments = outputPaths.map(
(filepath) => `/magical-types/${path.basename(filepath)}`
);
let manifestOutputPath = path.resolve(staticDir, `magical-types-manifest.json`);

const metadataWithIndexes: MagicalNodeMetadata = {};

for (const pkgName in allTypes) {
metadataWithIndexes[pkgName] = {};
for (const exportName in allTypes[pkgName]) {
if (serializationResult.nodesMeta.has(allTypes[pkgName][exportName].node)) {
metadataWithIndexes[pkgName][exportName] = {
type: allTypes[pkgName][exportName].type,
index: serializationResult.nodesMeta.get(
allTypes[pkgName][exportName].node
)!.index,
};
}
}
}

(async () => {
console.log(`writing output`);
await Promise.all([
fs.writeFile(
manifestOutputPath,
JSON.stringify({
paths: outputUrlSegments,
types: metadataWithIndexes,
})
),
...outputPaths.map((filepath, index) =>
fs.writeFile(filepath, JSON.stringify(chunkedNodes[index]))
),
]);

console.log('done');
})().catch((err) => {
console.error(err);
process.exit(1);
});
13 changes: 13 additions & 0 deletions docs/generate-magical-types/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { MagicalNode, MagicalNodeIndex } from '@magical-types/types';

export type MagicalNodeMetadata = Record<
string,
Record<string, { type: 'component' | 'other'; index: MagicalNodeIndex }>
>;

export type MagicalNodesForPackage = Record<
string,
{ type: 'component' | 'other'; node: MagicalNode }
>;

export type MagicalNodes = Record<string, MagicalNodesForPackage>;
6 changes: 6 additions & 0 deletions docs/generate-magical-types/types/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"main": "dist/generate-magical-types.cjs.js",
"preconstruct": {
"source": "../src/types"
}
}
1 change: 1 addition & 0 deletions docs/markdown/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class HeadingStore {
headings: { [key: string]: Data[] } = {};

add(key: string, data: Data) {
console.log('add being called with', data.label);
if (!this.headings[location.pathname]) {
this.headings[location.pathname] = [];
}
Expand Down
10 changes: 8 additions & 2 deletions docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "@react-select/docs",
"private": true,
"version": "3.1.0",
"main": "dist/docs.cjs.js",
"author": "Jed Watson",
"license": "MIT",
"dependencies": {
Expand All @@ -19,7 +20,11 @@
"@babel/runtime": "^7.12.0",
"@emotion/babel-plugin": "^11.0.0",
"@emotion/react": "^11.1.1",
"@magical-types/convert-type": "^0.1.4",
"@magical-types/macro": "^0.6.3",
"@magical-types/pretty": "^0.3.5",
"@magical-types/serialization": "^0.2.1",
"@magical-types/types": "^0.1.2",
"@types/chroma-js": "^1.4.3",
"@types/copy-webpack-plugin": "^5.0.2",
"@types/html-webpack-plugin": "^3.2.4",
Expand Down Expand Up @@ -71,7 +76,8 @@
"webpack-dev-server": "^3.3.1"
},
"scripts": {
"start": "cross-env FORCE_EXTRACT_REACT_TYPES=true webpack-dev-server --progress",
"build:docs": "rimraf docs/dist && cross-env FORCE_EXTRACT_REACT_TYPES=true webpack --progress -p"
"site-prebuild": "node ./generate-magical-types/generate && node ./generate-magical-types/serialize",
"start": "yarn site-prebuild && webpack-dev-server --progress",
"build:docs": "rimraf docs/dist && yarn site-prebuild && webpack --progress -p"
}
}
Loading

0 comments on commit faf93ba

Please sign in to comment.