Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Shareable Plugins (for TSDX Build/Config, i.e. tsdx.config.js or Rollup in general) #635

Open
agilgur5 opened this issue Mar 23, 2020 · 0 comments
Labels
kind: discussion Discussion on changes to make scope: integration Related to an integration, not necessarily to core (but could influence core)

Comments

@agilgur5
Copy link
Collaborator

agilgur5 commented Mar 23, 2020

Current Behavior

Currently, tsdx.config.js allows many internals to be changed however a user so chooses. As the warning I added to the README states, this can be very fragile/brittle against updates and can break easily, since this exposes a large part of TSDX as an API that's normally only used internally.

That warning not withstanding, there are still many users of tsdx.config.js, and both official and unofficial documentation (e.g. #379 ) of ways of extending it.

Features like #367 , at least one optimization mentioned there, and likely many more would be entirely non-breaking, but because they change the Rollup config, they are breaking for certain users of tsdx.config.js (which is one of the primary reasons I added the warning -- it's very easy to break this API as the internal Rollup config is a core portion of tsdx build which is the core of TSDX).

Desired Behavior

Document some sort of API that allows users to share tsdx.config.js plugins together for interoperability and better maintenance -- especially through version-locked peerDependencies on TSDX itself (that current copy/paste solutions don't have).

It also allows for users and orgs to re-use their configs between projects more easily.

Plugins could also be written in TypeScript for better safety, adhering to an interface set by TSDX, using whatever other library types are available, and transpiled down to JS for use by tsdx.config.js (which can only be written in CJS right now, as it's require'd).

Suggested Solution

The kicker is that I'm 100% sure what this should look like yet, there are pros/cons to each option. The main proposal is:

  1. The plugin just accepts a Rollup config and returns a new config. That would look like:

    const tsdxRollupPluginPostCSS = require('tsdx-rollup-plugin-postcss');
    
    // tsdx.config.js
    module.exports = {
      rollup (config, options) {
         config = tsdxRollupPluginPostCSS(config);
         return config;
      }
    }

    This has some limited extensibility to general Rollup users, but not that much because any overrides would be specific to some plugins. Extensibility to general Rollup users is preferred.

    The major problem with it is that it doesn't account for if we add new configurations to tsdx.config.js. Top of mind is being able to more easily re-configure existing plugins similarly to how customize-cra works, so that one doesn't have to do hacky config.plugins.map((plugin) => plugin.name !== myPlugin.name ? plugin : ... and so that they don't need to match the internal config and can just override it where necessary

  2. The plugin operates on the entire tsdx.config.js, looking like:

    const tsdxConfigPluginPostCSS = require('tsdx-config-plugin-postcss');
    
    module.exports = tsdxConfigPluginPostCSS({
      // any other customizations, for instance
      rollup(config, options) {
        // for instance
        if (options.format === 'esm') {
          config.preserveModules = true;
        }
        return config;
      }
      // for instance, if exists in the future
      addRollupPluginTypeScript2Options(options) {
        options.abortOnError = false;
      }
    })

    This adds some future-proofing to these plugins and allows for ones that configure multiple areas of tsdx.config.js that may become available in the future. The catch is that it has basically no extensibility outside of TSDX

  3. Plain old Rollup Plugins. Instead of writing TSDX specific plugins, write regular Rollup plugins. Can wrap an existing plugin and override it for simplicity.

    This has the most extensibility to the ecosystem, but has a significant barrier to entry and still requires some hackiness to use with TSDX in the case of overrides.

    It could be done as an add-on to the above options though, i.e. a user could release the Rollup plugin and a TSDX plugin that makes use of it.

    The big question here is does extensibility to broader Rollup matter? These likely won't be complex configs and rather just simple combinations or defaults, which already have limited extensibility due to them being specific to developer preference.

    "Core" plugins that are maintained internally could definitely be written this way however, and they would make up most of the use-cases folks use (see below).

    A good portion of TSDX could be re-written or exposed as a Rollup plugin in and of itself as well (or as multiple plugins).

  4. Like 1., but operating only on certain parts, like e.g. only on config.plugins or config.output, etc.
    Harder to name these and fragments the API

  5. Allow both 1. & and 2. with different names. Similarly harder to name and fragments the API

  6. Let users share whatever and just document things.
    Users can name things similarly despite different usage and makes for fragile, unexpected, or highly inconsistent behavior and usage patterns

  7. Have core official plugins only, and no others.
    Not that extensible, but we can cover the core use cases of CSS, images, etc so that most users are satisfied.
    Means much less worry about breaking the API. Would significantly break the current API and usage however. Means more maintenance/feature request load on TSDX core to implement new plugins, however. And decisions therein about what to support and what not to.

TSDX core can also maintain some of the most common plugins itself, to guarantee compatible versions are always available for these common use cases, e.g. postcss, images/SVGs, etc.
These common plugins would also have integration tests against current TSDX to ensure they work, similar to an externalized version of #627 .
These would be maintained similarly to Presets in #634 with a monorepo.

Naming

The naming part is pretty key, because TSDX can be used for a lot of things. These things currently only impact tsdx.config.js, which currently only impacts tsdx build. But maybe we'll allow plugins for tsdx test or lint etc in the future. Or maybe tsdx.config.js will have more options that aren't specific to build. So I'd prefer to be more specific on the naming so we can still have the option to add things in the future without adding lots of confusion or renames, etc.

Who does this impact? Who is this for?

All tsdx.config.js users. Anyone who, say, wants to use postcss right now or images right now.

Describe alternatives you've considered

Included above.

Additional context

I'll need to add all the links, but I've mentioned this idea in a number of different places.

#509 (comment)
#389 (comment). Links to #110 and #183 which give ideas too.
#379 (comment)
#525 (comment)

@agilgur5 agilgur5 changed the title [RFC] TSDX Build/Config/Rollup Shareable Plugins [RFC] Shareable Plugins (for TSDX Build/Config, i.e. tsdx.config.js or Rollup in general) Mar 23, 2020
@agilgur5 agilgur5 added the kind: discussion Discussion on changes to make label Mar 24, 2020
@agilgur5 agilgur5 added the scope: integration Related to an integration, not necessarily to core (but could influence core) label Aug 19, 2020
@agilgur5 agilgur5 pinned this issue Aug 22, 2020
@agilgur5 agilgur5 added this to the Future Non-breaking milestone Oct 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: discussion Discussion on changes to make scope: integration Related to an integration, not necessarily to core (but could influence core)
Projects
None yet
Development

No branches or pull requests

1 participant