expressots-cli icon indicating copy to clipboard operation
expressots-cli copied to clipboard

Create `start` and `dev` Commands with Improved Implementation & Move to `tsx`

Open Daniel-Boll opened this issue 2 years ago • 15 comments

Introduction

The existing CLI commands for starting the application and running in development mode could be simplified and optimized. Currently, the following commands are used:

  • Start: node -r dotenv/config -r ./dist/register-path.js ./dist/src/main.js
  • Development: tsnd -r dotenv/config -r tsconfig-paths/register ./src/main.ts

The proposal is to replace these with two simple commands, start and dev, and change the underlying package from ts-node-dev to tsx.

Proposed Changes

  1. Replace Start Command: Introduce a start command to replace the current complex command.
  2. Replace Development Command: Introduce a dev command for development, replacing the existing command.
  3. Move from ts-node-dev to tsx: As ts-node-dev has not been actively maintained and tsx (https://github.com/esbuild-kit/tsx) has been more broadly used, it is suggested to migrate to tsx, which may provide better performance and compatibility.

Implementation Details

start Command:

The start command can replace the current command for running the application.

expressots start
dev Command:

The dev command can replace the current command for running the development server.

expressots dev
Use tsx:

Move from ts-node-dev to tsx

Overview

I'm proposing to migrate from ts-node-dev to tsx (https://github.com/esbuild-kit/tsx) for running TypeScript files. This change is driven by the following critical factors:

Active Maintenance
  • ts-node-dev: The ts-node-dev package has not been actively maintained, with the latest updates showing a lack of consistent development. This poses a risk of running into unsupported issues or bugs that might not be addressed promptly.
  • tsx: In contrast, tsx is an actively maintained package with regular updates, ensuring that it keeps up with the latest TypeScript features and best practices. This active maintenance promotes stability and support for future enhancements.
Performance
  • Faster Compilation: tsx uses esbuild, known for its remarkable compilation speed. This speed can make the development process more efficient, particularly in large codebases.
  • Reduced Startup Time: tsx optimizes the startup time, enabling quicker iterations during development. This can save valuable time for developers and streamline the workflow.
Compatibility
  • Latest TypeScript Features: tsx supports the latest TypeScript features, ensuring compatibility with modern development practices and tools.
  • Flexibility with Configuration: tsx provides a flexible configuration system, allowing customization and fine-tuning to fit the specific needs of the project.
Community Adoption
  • Wider Usage: tsx has seen more extensive adoption within the community, reflecting a positive reception and trust in the package.
  • Contributions: Being a more popular package, tsx benefits from community contributions, resulting in a more refined and robust solution.
Conclusion

The migration from ts-node-dev to tsx offers substantial benefits, including enhanced performance, active maintenance, and compatibility with modern development practices. Aligning with a package that enjoys broader community support will contribute to the project's long-term success and maintainability. Therefore, transitioning to tsx is a strategic move that we believe will positively impact the development experience in ExpressoTS.

Benefits

  • Simplicity: Simplifies the commands to start and develop the project.
  • Maintainability: Utilizes a well-maintained and widely-used package (tsx) over ts-node-dev.
  • Performance: Potentially provides improved speed with tsx.

Conclusion

These changes aim to enhance the CLI experience by providing more straightforward commands and migrating to a more efficient and actively maintained package. Feedback are welcome for this proposed update.

Daniel-Boll avatar Aug 11 '23 12:08 Daniel-Boll

If you are referring to the commands in the templates, the correct commands are these ones:

"build": "tsc -p tsconfig.build.json && cp -R ./register-path.js tsconfig.build.json package.json ./dist",
"dev": "tsnd -r dotenv/config -r tsconfig-paths/register ./src/main.ts",
"prod": "node -r dotenv/config -r ./dist/register-path.js ./dist/src/main.js",

These commands above are project bind commands, they are not available globally from the expressots/cli

Are you suggesting to add these commands to the CLI and then change the signature of the project command of the templates to possibly:

expressots build
expressots dev
expressots prod

Is this the correct understanding?

If this is what you are trying to achieve, I think is a good idea however you need to have in mind that we gonna be generating a dependency from the template to the CLI. And any change in the template that involves commands will have to change CLI as well.

Please, create a POC to demonstrate this proposal to understand the impact, the dependencies that will be included, dependency sizes, as well as a comparison between tsnd versus tsx performance during development. Attach your code and send a link to your POC to be appreciated.

rsaz avatar Aug 12 '23 07:08 rsaz

@rsaz I've been attempting to integrate tsx into the project without success. It appears the issue may be related to the Env validator. Should we simplify our approach by focusing on the start and dev commands, moving the tsnd dependency to the CLI?

Daniel-Boll avatar Aug 15 '23 00:08 Daniel-Boll

@Daniel-Boll can you respond please to the questions above mentioned in the previous message? This will help us to understand how do you intend to implement and resolve those issues mentioned above.

rsaz avatar Aug 15 '23 00:08 rsaz

Yes, that's the plan. Instead of using tsnd -r dotenv/config -r tsconfig-paths/register ./src/main.ts, we'll simplify it to just expressots dev for instance.

Daniel-Boll avatar Aug 15 '23 01:08 Daniel-Boll

For now, I'd say we stick with tsnd, and initially only port the start and dev commands. Essentially, I believe we're just moving the dependency from the core to the CLI this way.

Daniel-Boll avatar Aug 15 '23 01:08 Daniel-Boll

Ok, in doing that, a simple command will depend on cli change. Ok, lets do a POC, please proceed with a POC. I will move this idea to stage 2

image

rsaz avatar Aug 15 '23 02:08 rsaz

@joaoneto as mentioned we are in the stage 2. Let us know, or discuss with @Daniel-Boll so that you guys can POC these two scenarios:

1 - Change the commands from

"build": "tsc -p tsconfig.build.json && cp -R ./register-path.js tsconfig.build.json package.json ./dist",
"dev": "tsnd -r dotenv/config -r tsconfig-paths/register ./src/main.ts",
"prod": "node -r dotenv/config -r ./dist/register-path.js ./dist/src/main.js",

To

expressots build
expressots dev
expressots prod

2 - Your proposal #16

The changes that I propose are the following:

Add a command option, for example: --experimental, --use-swc, so that the template uses the build with SWC Change or create a template so that the npm scripts of the package.json use the experimental build

Waiting feedback!

rsaz avatar Aug 21 '23 07:08 rsaz

Nice!

A suggestion to proceed with the two changes, would be to create in the cli the bin scripts of the package.json, that will trigger:

expressots build
expressots dev
expressots prod 

once we opt to use the swc transpiler, we would pass a flag:

expressots build --experimental
expressots dev --experimental
expressots prod --experimental

I created a basic funcional project that uses expressots with the build/test/etc.. tools in the swc's performant environment called expressots-opinionated-experimental so that we can have some insights too, what do you think?

joaoneto avatar Aug 21 '23 14:08 joaoneto

@joaoneto, the progress appears promising, and your approach seems solid. The next logical step might be to conduct a benchmark, comparing the performance with and without the integration of SWC in the build process.

It would be beneficial to document these findings in the README file itself, providing clear insight for anyone exploring the repository.

Rest assured, I'll be monitoring the changes in the repo by subscribing to the changes look forward to seeing the results.

Best Regards, Daniel Boll. :flower_playing_cards:

Daniel-Boll avatar Aug 21 '23 15:08 Daniel-Boll

@joaoneto to your points:

Should we separate bin expressots scripts?

  • I would advise to not at least now, the reason is that more packages to maintain, add ci/cd, format, document and so on
  • I think we can have the same script just with an additional flag experimental as you suggested

Should we create templates for experimental?

  • yes absolutely. We could organize like this:
  • tsconfig
    • opinionated
    • non opinionated
  • swc
    • opinionated
    • non opinionated

Few things to consider:

  • If the user decide to use swc we need to test all current functionalities available in tsconfig, they should work on swc as well
  • We need to test on win and wsl
  • Type Checking: SWC itself does not perform TypeScript type checking. It just cares about transforming code as quickly as possible. We rely on TypeScript's type-checking capabilities so we will still need to run the TypeScript compiler (tsc --noEmit) to validate your types.

Configuration: SWC has its own configuration file (.swcrc), which is separate from TypeScript's tsconfig.json. You will have to configure SWC separately to ensure that it understands your project's needs. Now we gonna have 2 configuration files, we need to clearly define where the user should use one rather than the other, or for swc just use .swcrc file

Compatibility: SWC aims to support most TypeScript syntax and features, but there might be subtle differences or unsupported edge cases. It's a good idea to thoroughly test the templates/application

Yeah, lets proceed and observe these points. Once you get a branch send me out to test as well.

Keep up the good work!

rsaz avatar Aug 21 '23 19:08 rsaz

@joaoneto added your comments from #16 to here image

Let me know about the points above. Also, I will be testing end of the day to provide a proper technical feedback.

rsaz avatar Aug 21 '23 19:08 rsaz

@joaoneto to your points:

Should we separate bin expressots scripts?

  • I would advise to not at least now, the reason is that more packages to maintain, add ci/cd, format, document and so on
  • I think we can have the same script just with an additional flag experimental as you suggested

Should we create templates for experimental?

  • yes absolutely. We could organize like this:

  • tsconfig

    • opinionated
    • non opinionated
  • swc

    • opinionated
    • non opinionated

Few things to consider:

  • If the user decide to use swc we need to test all current functionalities available in tsconfig, they should work on swc as well
  • We need to test on win and wsl
  • Type Checking: SWC itself does not perform TypeScript type checking. It just cares about transforming code as quickly as possible. We rely on TypeScript's type-checking capabilities so we will still need to run the TypeScript compiler (tsc --noEmit) to validate your types.

Configuration: SWC has its own configuration file (.swcrc), which is separate from TypeScript's tsconfig.json. You will have to configure SWC separately to ensure that it understands your project's needs. Now we gonna have 2 configuration files, we need to clearly define where the user should use one rather than the other, or for swc just use .swcrc file

Compatibility: SWC aims to support most TypeScript syntax and features, but there might be subtle differences or unsupported edge cases. It's a good idea to thoroughly test the templates/application

Yeah, lets proceed and observe these points. Once you get a branch send me out to test as well.

Keep up the good work!

@rsaz Very well observed!

Let me see if I understand. I imagine that for the script bin build and dev, two concurrent tasks, tsc --noEmit (–watch for dev) and the swc task that only transpiles, we can add the lib concurrently to run on any platform, or create our own solution that uses spawn to start both tasks in parallel.

Unfortunately, swc currently does not support tsconfig.json, so .swcrc would have to be kept only for transpiling. It doesn’t need to change, and tsconfig.json would be the source of truth, that validate types with (tsc --noEmit).

Those who opt to use the experimental template should accept the risks of possibly not being compatible with some extreme case without swc support. We should have a very clear warning that this is a tradeoff between optimizing build time and the features you intend to use.

joaoneto avatar Aug 21 '23 20:08 joaoneto

Solution moved to approved. I think now we have covered the major scenarios Now you can use #16 to implement it. Make sure on #16 you refer the discussion on #15

Looking forward to review your submission

rsaz avatar Aug 21 '23 21:08 rsaz

Currently the CLI already supports the commands inferred:

"build": "expressots run build",
"dev": "expressots run dev",
"prod": "expressots run prod",

I will create a ticket to compress even more to:

"build": "expressots build",
"dev": "expressots dev",
"prod": "expressots prod",

Also allow parameters to be passed as well as to change the ts-node-dev dependency out of the picture,

Alternatives to be compared:

  • nodemon --watch + ts-node
  • node-dev + ts-node
  • ts-node-dev -tsx (https://www.npmjs.com/package/tsx)
  • nodemon + node-dev + ts-node + swc
  • swc

rsaz avatar Mar 31 '24 20:03 rsaz

At the time I tried tsx, but couldn't make it work for some reason, tried for a while but unsuccessful, I then quit trying. Albeit being one hell of a package.

Daniel-Boll avatar Mar 31 '24 21:03 Daniel-Boll

Done in the v3.0.0

rsaz avatar Nov 20 '24 00:11 rsaz