You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently, we use Styled components for all CSS styling. This has a few problems at the scale of Madoc and is
not been possible to solve these issues with the library itself. It's not practical to migrate everything at once
but for new components they should use the Stitches library instead.
At the moment pages mostly work using serverRendererFor() helper or createUniversalComponent to load
server side information. This will slow change for new pages using vite for discovery of pages.
Current page example:
// pages/some-page.tsxfunctionSomePage(){const{ data }=useData(SomePage);// Uses selfreturn<div>This is my page: {data.someProperty}</div>}// This data will be pre-loaded when server-rendering.serverRendererFor(SomePage,{getKey: ()=>'some-page',getData: (key,vars,api)=>api.getSomethingFromApi(),});
New example:
pages/SomePage/SomePage.tsx
exportdefaultfunctionSomePage(){const{ data }=useClientData();// No self-refreturn<div>This is my page: {data.someProperty}</div>}
pages/SomePage/SomePage.loader.ts
exportfunctionloader({ api }: LoaderType){returnapi.getSomethingFromApi();}
This splitting allows for bundles to be more optimised, we can know what data is required without loading
the full component and dependencies. This also means we can load data and components in parallel using the
latest version of React Router (v6.4).
// All routing information exported.exportdefault{id: 'ping',method: 'GET',path: '/api/madoc/ping/:slug',middleware: [ping]}// JSON schema-lite definitionexportconstparams={slug: {type: 'string'}}functionping(context: RouteMiddlewareFn<typeofparams>){context.response.body={ping: 'pong',slug: context.params.slug};// type checking on params.}
This has a few benefits:
Single file routing, and vite auto-loading to make DX smoother
Strongly typed params, with option to add runtime-validation
Can generate documentation from definition more easily
Model can be extended (e.g. export const statusMap = {200: {ping: 'boolean'}, 400: {error: 'string'}})
Vite can be added to hot-reloading of individual endpoints
Moving all SQL to /repository folder
At the moment there are routes that have Postgres queries inline. This should be switched to use the repository
pattern that has cleaned up these routes considerably. This will also make it much easier to test servers with
repository-only mocks.
Consolidate environment variables
These should be configured in a single place, and imported or injected in config. This is mostly done but still
has some gaps.
Possibly reformat of "tasks"
At the moment a task contains ALL the code for a task including types. Splitting these down may reduce bundle sizes
and keep the backend and frontend split.
Auto-loading of extensions
These should use vite to autoload extensions and make development easier.
Splitting monolithic API class
Currently, the api.ts file is massive. This should be split down into distinct API clients, accessible and lazy-loaded
through the existing interface.
classApiClient{getSomethingClient(){if(!this._somethingClient){this._somethingClient=import('./apis/SomethingApiClient').then(mod=>newmod.SomethingApiClient());// Any set up.}returnthis._somethingClient;}asyncgetSomething(){deprecationWarning('Use SomethingApiClient instead');return(awaitthis.getSomethingClient()).getSomething();}}
This should make splitting large APIs much easier, and also reduce the size of APIs floating around. For context
the current API is 66KB on its own. We may also be able to generate some API clients automatically, further
reducing the size and maintenance of the API client.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Proposed structure changes
Source /src folder is the top level for all Typescript.
Top level folders
frontend
server
queue
utility
Frontend
admin
- All pages and components specific to the adminsite
- All pages and components specific to the siteshared
- All pages and components that are sharedserver-side-rendering
- Contains server code specific for rendering the frontend on the servercapture-models
- Specific area for all capture model specific codecore
- I hate this name, but there are some things that do not fit in the above - reduce noiseAdmin / Site / Shared common structure
Directories:
atoms
- Single component per file, atomic and reusable componentsblocks
- Will contain organised folders of components (e.g.blocks/viewers/XYZ/XYZ.tsx
) but must be page-blockscomponents
- Same as above, but not (yet) page blocksfeatures
- Features are all page-blocks and usually themselves compositionshooks
- Reusable React hookspages
- See belowFiles (admin/site only):
routes.tsx
- All routes for the frontendrender-client.tsx
- Client-only entrypointrender-server.tsx
- Server-only entrypointconfig-client.ts
- Client-only configconfig-server.ts
- Server-only configindex.tsx
- Common entrypoint (loaded by therender-(client|server).tsx
)New Component structure
At the moment components are a mix of styles. The following will be applied for new components:
1. Moving to prefer function components over const expressions
2. Component folders
Before:
components/Button.tsx
../stories/Button.stories.tsx
After:
components/Button/Button.tsx
components/Button/Button.styles.ts
components/Button/Button.stories.tsx
components/Button/Button.tests.ts
components/Button/Button.types.ts
components/Button/Button.[feature].ts
These component folder can grow with a component, and can be split where it makes sense.
3. Styled components -> Stitches
Currently, we use Styled components for all CSS styling. This has a few problems at the scale of Madoc and is
not been possible to solve these issues with the library itself. It's not practical to migrate everything at once
but for new components they should use the
Stitches
library instead.Before:
After:
New page structure
At the moment pages mostly work using
serverRendererFor()
helper orcreateUniversalComponent
to loadserver side information. This will slow change for new pages using vite for discovery of pages.
Current page example:
New example:
pages/SomePage/SomePage.tsx
pages/SomePage/SomePage.loader.ts
This splitting allows for bundles to be more optimised, we can know what data is required without loading
the full component and dependencies. This also means we can load data and components in parallel using the
latest version of React Router (v6.4).
Other features
Loader options:
Server-only loaders / actions:
These will available at special endpoints:
/api/madoc/loaders?page=SomePage
and are a tool to compose APIsError boundary:
Similar to the new component model we can expand this structure with more features we might need in the future.
Backend
Changes to the backend are fairly limited, some are simply technical debt to be addressed.
New route structure
For new routes, a structure similar to the frontend will be used, with the goal to migrate everything across
eventually.
Current system:
and in routes:
New system
This has a few benefits:
export const statusMap = {200: {ping: 'boolean'}, 400: {error: 'string'}}
)Moving all SQL to /repository folder
At the moment there are routes that have Postgres queries inline. This should be switched to use the repository
pattern that has cleaned up these routes considerably. This will also make it much easier to test servers with
repository-only mocks.
Consolidate environment variables
These should be configured in a single place, and imported or injected in config. This is mostly done but still
has some gaps.
Possibly reformat of "tasks"
At the moment a task contains ALL the code for a task including types. Splitting these down may reduce bundle sizes
and keep the backend and frontend split.
Auto-loading of extensions
These should use vite to autoload extensions and make development easier.
Splitting monolithic API class
Currently, the
api.ts
file is massive. This should be split down into distinct API clients, accessible and lazy-loadedthrough the existing interface.
Example before:
After:
This should make splitting large APIs much easier, and also reduce the size of APIs floating around. For context
the current API is 66KB on its own. We may also be able to generate some API clients automatically, further
reducing the size and maintenance of the API client.
Beta Was this translation helpful? Give feedback.
All reactions