Gasket Framework

repository·main·Indexed 40 days ago

https://github.com/godaddy/gasket

A robust, pluggable, and render-agnostic framework for rapid delivery of modern JavaScript web applications. Gasket uses a plugin-based architecture to provide commands, lifecycles, and structures for building complex apps, featuring a core lifecycle system (init, configure, prepare, ready) and a CLI for application creation via templates and presets.

Tokens
227.9K
Snippets
864
Records
1.1K
Agent score
49%

What's inside Gasket

  1. Overview of Gasket Framework

    main
    Gasket is a framework maker for JavaScript applications. It allows developers to construct apps and frameworks using various presets and plugins. The core capabilities of a Gasket application—such as specific commands, lifecycles, and data structures—are enabled by the plugins you choose to include in your project.
  2. Key changes in Gasket v7

    main

    Gasket v7 introduces several architectural shifts designed to increase transparency and flexibility:

    • Removal of Gasket CLI: Core tasks like transpilation and bundling are now delegated to the primary framework (e.g., Next.js) rather than a dedicated Gasket CLI.
    • Lifecycle Simplification: The 'magic files' previously located in the lifecycles directory have been removed to reduce complexity and increase transparency.
    • ESM Support: Applications are now fully aligned with ECMAScript Modules (ESM).
    • TypeScript Support: Full support for TypeScript is available for both Gasket applications and in-app plugins.
    • Next.js 14 Support: Supports both App Router and Page Router, including a custom server option.
    • Multiple Instances: Developers can now create multiple Gasket instances within a single application for greater control.
  3. What is Gasket and how does it work?

    main

    Gasket is a tooling ecosystem designed to help developers compose Node.js frameworks by assembling reusable elements into feature-rich applications. Instead of using static starter repos or monolithic generators, Gasket uses a modular approach based on Plugins and Presets.

    Core Components:

    • CLI: The foundation for generating apps and interacting with them. It provides standard commands like build, start, and create.
    • Plugins: Composable packages that integrate libraries and provide features. Plugins are not just for scaffolding; they persist in the app to provide runtime functionality. They work by hooking into various Lifecycles.
    • Lifecycles: Specific stages of an app's process (e.g., the create lifecycle) that plugins can hook into to execute logic, install libraries, or generate code.
    • Presets: A collection of plugins stamped together to form a reusable framework. When you use a preset with the create command, the resulting app is pre-configured with all the features defined by those plugins.
  4. What is Gasket and the API Preset?

    main

    Gasket is a framework maker designed to provide a platform of patterns, integrations, and functionality for building JavaScript web applications and APIs. It uses a plugin architecture where functionality is added via plugins.

    Presets are predefined collections of plugins bundled together for specific project types. The Gasket API Preset is specifically designed for creating APIs. It includes plugins for:

    • Adding Express to your application.
    • Enabling http and https functionality.
    • Generating Swagger API documentation.
  5. Access server-side data without Redux using @gasket/data

    main
    Gasket 6 has decoupled from Redux to allow for more flexible state management. The @gasket/data package is now the primary way to access server-side data and configurations from the client side without requiring a Redux store. This is supported by the @gasket/nextjs package, which injects a GasketData script into the DOM to make server-side data available to the browser.
  6. Understand Gasket lifecycles

    main

    Gasket executes a sequence of lifecycles during instantiation. There are two synchronous lifecycles followed by two asynchronous lifecycles. To ensure the application only proceeds once the instance is fully initialized, wait for the isReady promise to resolve.

    Lifecycle Order

    1. init (Sync): Earliest entry point. Used for setting up initial state.
    2. configure (Sync): Allows registered plugins to adjust the configuration object before proceeding.
    3. prepare (Async): Used for setup requiring asynchronous operations (e.g., fetching remote config).
    4. ready (Async): The final lifecycle. Signals the instance is fully initialized.

    Usage Pattern

    import gasket from './gasket.js';
    
    gasket.isReady.then(() => {
      // The instance is now fully initialized
      gasket.actions.doSomething();
    });
    import gasket from './gasket.js';
    
    gasket.isReady.then(() => {
      gasket.actions.doSomething();
    });
  7. Configure tsconfig.server.json for Next.js Custom Servers

    main

    If your Next.js app uses nextServerType: 'customServer' or nextDevProxy: true, the plugin generates a tsconfig.server.json. This file provides a separate configuration for server-side TypeScript compilation to distinguish it from client-side bundling.

    Key characteristics of tsconfig.server.json:

    • Module system: Uses NodeNext (optimized for Node.js runtime) instead of bundler.
    • Compilation: Configured to compile to dist/ (enables emission).
    • Scope: Includes only server files; excludes React components.
    • Exclusions: Excludes the Next.js plugin (as the server doesn't use the Next.js bundler) and does not support JSX.
  8. Implement the metadata lifecycle hook

    main

    Plugins can implement the metadata lifecycle hook to describe their own metadata and the metadata of their supporting modules. The object returned by this hook will replace the existing metadata for that plugin. This allows plugins to modify their own metadata at runtime.

    // gasket-plugin-example.js
    export default {
      name: 'example',
      hooks: {
        /**
         * @param {Gasket} gasket - The Gasket API
         * @param {PluginData} data - This plugin's initial metadata
         * @returns {Object}
         */
        async metadata(gasket, data) {
          return {
            ...data,
            // adding extra data to this plugin's metadata
            extra: 'information',
            // add metadata for details of this plugin
            lifecycles: [{
              name: 'some-data',
              description: 'Allows plugins to do something with data',
              method: 'exec',
              parent: 'start'
            }],
            // Metadata for these modules will be loaded
            // Declare as strings or objects with additional data
            modules: [
              {
                name: 'module-name',
                version: '7.0.0',
                description: 'module-name description',
                link: 'README.md'
              }
            ]
          }
        },
        /**
         * An example lifecycle hook which utilizes metadata
         *
         * @param {Gasket} gasket - The Gasket API
         */
        async example(gasket) {
          const { metadata } = gasket;
    
          if (metadata.plugins.find(pluginData => pluginData.name === 'gasket-plugin-something')) {
            // only perform some action if a certain plugin is also registered
          }
        }
      }
    }
  9. Customize cache keys with serviceWorkerCacheKey

    main

    The serviceWorkerCacheKey lifecycle hook allows plugins to define how the service worker content is cached. By providing functions that return a string based on the req (request) and res (response) objects, you can prevent unnecessary recompositions for every unique request. If the generated key matches an existing cache entry, the cached content is returned directly.

    // Shorthand example: Cache based on a 'market' cookie
    export default {
      name: 'sample-plugin',
      hooks: {
        serviceWorkerCacheKey: () => (req, res) => req.cookies.market || 'en-US'
      }
    }
  10. Understand @gasket/plugin-typescript lifecycle

    main
    The @gasket/plugin-typescript is a create-time only plugin. It is NOT installed in the final application. Instead, it is used by Gasket presets during the create-gasket-app process to configure TypeScript, generate necessary configuration files (like tsconfig.json), and set up scripts. Once the application is created, the plugin is discarded.
  11. Understand peer dependency version updates

    main

    In this monorepo, Changesets automatically updates peer dependency versions from ranges (e.g., ^7) to specific versions (e.g., ^7.3.5) during the release process. This is a built-in behavior designed to ensure version consistency across the monorepo and cannot be disabled via configuration.

    Example Behavior: If @gasket/plugin-logger is at version 7.3.5, a package with the following dependency:

    "peerDependencies": {
      "@gasket/plugin-logger": "^7"
    }

    will be automatically updated to:

    "peerDependencies": {
      "@gasket/plugin-logger": "^7.3.5"
    }

    Workarounds:

    • Manual Updates: Revert the peer dependency changes in the generated "Version Packages" PR before merging.
    • Post-process Script: Implement a script that runs after changeset version to revert the specific version changes.