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
TypeScript enthusiasts like me want as much of our code to be written in TypeScript as possible. As a user of @gasket/preset-nextjs, I enjoy the fact that the next.js integration gives me the ability to author some of my code in TypeScript (React components for example), but it's frustrating that any code compatible with SSR (/store.js) or pure gasket artifacts /lifecycles cannot be authored in TypeScript without some hackery or degradation in developer experience (DX).
Technical Challenges
There are many technical challenges to supporting TypeScript source code in gasket applications:
Gasket, being a framework engine, needs to remain as tiny as possible and mandate as few technology choices as possible. This includes TypeScript. We therefore would prefer not to have Gasket automatically support TypeScript out of the box.
Developers find the presence of compilation artifacts residing alongside their source code to be a nuisance and a potential source of bugs if these artifacts are not up-to-date. Though they may be receptive to having to compile prior to a deployment, they do not wish to have to dodge extraneous file artifacts in their workspace or rely on starting a watching builder to keep things current.
However, node-loadable source files are a must for packages like @gasket/plugin-lifecycles, which lists the files in a /lifecycles directory and dynamically loads that code, and @gasket/plugin-redux which needs to discover a redux store factory.
Another tangential thing that developers may desire is the ability to automatically restart gasket servers when code changes. This avoids those confusing moments where you're tearing your hair out wondering why the code is not behaving as written because you forgot to restart.
Current Workarounds
Although TypeScript outside of next.js-built components is not officially supported, some approaches have been employed to support it within some projects, falling into two broad categories. Here are the challenges with these workarounds:
Building TypeScript files before running gasket
Running tsc before invoking the gasket CLI causes generated .js files to be placed alongside .ts files so that they're discoverable by Gasket. This works, but:
It is annoying to developers who now have to navigate both .js and .ts files in their source files.
For next.js apps, care has to be taken to make sure the TypeScript compilation doesn't conflict with the built-in TS support used when generating webpack artifacts. The ideal compiled output for a browser versus node differs, so you end up wanting different configurations for those two targets.
If you'd like your Gasket server to be restarted on source files changes, you have to take care that only code for the server side does this since next.js already has hot module reloading for client-side artifacts, and you wouldn't want changes to React component .tsx files to provoke server restarts.
Registering a module loader for TypeScript files
Another workaround involves registering a module loader for .ts files, using techniques like @babel/register or ts-node/register early in the source code of a gasket app, such as in gasket.config.js. This has some challenges:
It requires heavy toolchains like babel or typescript to be deployed alongside an app's dependencies since they are now used at runtime instead of just build time.
Although it addresses issues with importing source code, every package, that dynamically loads source code, such as @gasket/plugin-lifecycle, needs to know to look for other file extensions like .ts.
Source changes to server code not provoking restarts is also not addressed.
Proposed Solution
Add a gasket config property like extensions that is an array of which file extensions gasket plugins should look for when dynamically loading source files (or can we read this from Module?). This should have a reasonable default for typical node development.
Update plugins that do code discovery, like @gasket/plugin-lifecycle, to use this extensions config value.
In @gasket/plugin-start or a new @gasket/plugin-clean plugin:
Introduce a new clean command to gasket
Inject a clean package.json script that invokes gasket clean
Add clean hooks for any plugin that generates build artifacts, like @godaddy/gasket-plugin-intl
Create a @gasket/plugin-nodemon package which:
Hooks the create lifecycle and generates:
A devDependency on nodemon
A nodemon.json with useful defaults
A modified local package.json script which invokes gasket local via nodemon
Emits a nodemonConfig lifecycle event during create to enable plugins to modify the generated config
Create a @gasket/plugin-typescript package, which:
Hooks the configure lifecycle, injecting .ts (and maybe .tsx?) as an extension.
Hooks the create lifecycle after@gasket/plugin-nodemon and generates:
Appropriate devDependencies, like:
typescript
ts-node
@types/foo dependencies for any packages with known external type definitions. These will be read by invoking a new tsTypeDefinitionPackages lifecycle, enabling any plugin to register their own type definitions.
Two TypeScript config files, one for client code (tsconfig.json so it's picked up by the next.js babel compiler), one for server code
Appropriate .gitignore modifications
A modified local package.json script where ts-node is used to execute gasket or nodemon --exec ts-node if it's already wrapped by nodemon.
Hooks the nodemonConfig lifecycle and adds watching of .ts files, except those that are likely to be client-only
Hooks the build lifecycle, invoking tsc with the server config file if the gasket command isn't local
Hooks the clean lifecycle, deleting generated .js files
The text was updated successfully, but these errors were encountered:
Can we add a "before everything" init method where we can compile all *.ts files into js before Gasket reads the config file? This would let us to write everything in TypeScript including the Gasket config.
Problem Statement
TypeScript enthusiasts like me want as much of our code to be written in TypeScript as possible. As a user of
@gasket/preset-nextjs
, I enjoy the fact that the next.js integration gives me the ability to author some of my code in TypeScript (React components for example), but it's frustrating that any code compatible with SSR (/store.js
) or pure gasket artifacts/lifecycles
cannot be authored in TypeScript without some hackery or degradation in developer experience (DX).Technical Challenges
There are many technical challenges to supporting TypeScript source code in gasket applications:
@gasket/plugin-lifecycles
, which lists the files in a/lifecycles
directory and dynamically loads that code, and@gasket/plugin-redux
which needs to discover a redux store factory.Another tangential thing that developers may desire is the ability to automatically restart gasket servers when code changes. This avoids those confusing moments where you're tearing your hair out wondering why the code is not behaving as written because you forgot to restart.
Current Workarounds
Although TypeScript outside of next.js-built components is not officially supported, some approaches have been employed to support it within some projects, falling into two broad categories. Here are the challenges with these workarounds:
Building TypeScript files before running gasket
Running
tsc
before invoking the gasket CLI causes generated.js
files to be placed alongside.ts
files so that they're discoverable by Gasket. This works, but:.js
and.ts
files in their source files..tsx
files to provoke server restarts.Registering a module loader for TypeScript files
Another workaround involves registering a module loader for
.ts
files, using techniques like@babel/register
orts-node/register
early in the source code of a gasket app, such as ingasket.config.js
. This has some challenges:babel
ortypescript
to be deployed alongside an app's dependencies since they are now used at runtime instead of just build time.@gasket/plugin-lifecycle
, needs to know to look for other file extensions like.ts
.Proposed Solution
extensions
that is an array of which file extensions gasket plugins should look for when dynamically loading source files (or can we read this fromModule
?). This should have a reasonable default for typical node development.@gasket/plugin-lifecycle
, to use thisextensions
config value.@gasket/plugin-start
or a new@gasket/plugin-clean
plugin:clean
command to gasketclean
package.json script that invokesgasket clean
@godaddy/gasket-plugin-intl
@gasket/plugin-nodemon
package which:create
lifecycle and generates:nodemon
nodemon.json
with useful defaultslocal
package.json script which invokesgasket local
vianodemon
nodemonConfig
lifecycle event duringcreate
to enable plugins to modify the generated config@gasket/plugin-typescript
package, which:configure
lifecycle, injecting.ts
(and maybe .tsx?) as an extension.create
lifecycle after@gasket/plugin-nodemon
and generates:typescript
ts-node
@types/foo
dependencies for any packages with known external type definitions. These will be read by invoking a newtsTypeDefinitionPackages
lifecycle, enabling any plugin to register their own type definitions.tsconfig.json
so it's picked up by the next.js babel compiler), one for server code.gitignore
modificationslocal
package.json script wherets-node
is used to executegasket
ornodemon --exec ts-node
if it's already wrapped bynodemon
.nodemonConfig
lifecycle and adds watching of.ts
files, except those that are likely to be client-onlybuild
lifecycle, invokingtsc
with the server config file if the gasket command isn'tlocal
clean
lifecycle, deleting generated.js
filesThe text was updated successfully, but these errors were encountered: