webpack Plugin written by ChatGPT

zchapple

Zackary Chapple

Posted on December 16, 2022

webpack Plugin written by ChatGPT

Introduction

No matter what social media platform you are on if you follow the tech space, or any space for that matter, you are most likely seeing content about ChatGPT or even content generated by ChatGPT.

When it first came out a few weeks ago I played with it, thought it was pretty cool and had my kids start using it to write guided stories with ideas from their imagination. When combined with MidJourney AI generated art the overall experience was quite amazing.

Last night seeing @scriptedalchemy share about his experiences with it I decided to try something a little more challenging.

A lot of my focus lately is on ModuleFederation and webpack. I asked myself what could ChatGPT do with that combination and what would be fun to see. My prompts and directions will be in quote blocks.

The Task

The first question I asked the site:

create a webpack plugin in typescript that wraps module federation and adds additional logging

Below is the first reply:
To create a webpack plugin in TypeScript that wraps module federation and adds additional logging, you can follow these steps:

Create a new TypeScript project and install the necessary dependencies:

npm init -y
npm install --save-dev webpack webpack-cli typescript ts-loader
Enter fullscreen mode Exit fullscreen mode

Create a tsconfig.json file to configure the TypeScript compiler. In the compilerOptions object, set the module option to "commonjs" and the target option to "esnext". This will ensure that the generated JavaScript code is compatible with webpack.

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "esnext"
  }
}
Enter fullscreen mode Exit fullscreen mode

Create a webpack.config.ts file to configure webpack. In the configuration object, set the mode option to "development" and add a resolve object to specify that webpack should resolve TypeScript files.

import { Configuration } from 'webpack';

const config: Configuration = {
  mode: 'development',
  resolve: {
    extensions: ['.ts', '.tsx']
  },
  // Add other configuration options here
};

export default config;
Enter fullscreen mode Exit fullscreen mode

In the webpack.config.ts file, add a module object to specify that webpack should use the ts-loader to transpile TypeScript files.

import { Configuration } from 'webpack';

const config: Configuration = {
  // Other configuration options
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/
      }
    ]
  }
};

export default config;
Enter fullscreen mode Exit fullscreen mode

Create a src directory and add an entry point file, such as src/index.ts. This will be the file that webpack will use as the starting point for the build.

In the webpack.config.ts file, add an entry object to specify the entry point file and a output object to specify the path and filename of the bundled JavaScript file.

import { Configuration } from 'webpack';

const config: Configuration = {
  // Other configuration options
  entry: './src/index.ts',
  output: {
    path: __dirname + '/dist',
    filename: 'bundle.js'
  }
};

export default config;
Enter fullscreen mode Exit fullscreen mode

Install the necessary dependencies for module federation:

npm install --save-dev @module-federation/client
Enter fullscreen mode Exit fullscreen mode

In the webpack.config.ts file, import the ModuleFederationPlugin from the @module-federation/client package and add it to the plugins array in the configuration object. You can also specify the remotes option to specify the remote modules that your application should be able to access.

import { Configuration } from 'webpack';
import { ModuleFederationPlugin } from '@module-federation/client';

const
Enter fullscreen mode Exit fullscreen mode

First issues

You can see that the last code block is incomplete. Sometimes on more lengthy requests the chat bot can time out, I tried, quite literally, asking it to keep going.

keep going

Sure, here are the next steps:

Create a TypeScript interface for the plugin's options. This will allow you to specify the options for the plugin when it is added to the plugins array in the webpack configuration.

export interface ModuleFederationLoggingPluginOptions {
  // Add options here
}
Enter fullscreen mode Exit fullscreen mode

Create a new class for the plugin that extends the ModuleFederationPlugin class and implements the apply method. In the apply method, you can wrap the ModuleFederationPlugin and add additional logging.

import { Compiler, Plugin } from 'webpack';
import { ModuleFederationPlugin } from '@module-federation/client';
import { ModuleFederationLoggingPluginOptions } from './options';

class ModuleFederationLoggingPlugin implements Plugin {
  private readonly options: ModuleFederationLoggingPluginOptions;
  private readonly moduleFederationPlugin: ModuleFederationPlugin;

  constructor(options: ModuleFederationLoggingPluginOptions) {
    this.options = options;
    this.moduleFederationPlugin = new ModuleFederationPlugin(options);
  }

  apply(compiler: Compiler) {
    this.moduleFederationPlugin.apply(compiler);

    // Add additional logging here
  }
}
Enter fullscreen mode Exit fullscreen mode

In the webpack.config.ts file, import the ModuleFederationLoggingPlugin class and add an instance of it to the plugins array in the configuration object. You can also specify the options for the plugin by passing an object to the constructor.

import { Configuration } from 'webpack';
import { ModuleFederationLoggingPlugin } from './module-federation-logging-plugin';

const config: Configuration = {
  // Other configuration options
  plugins: [
    new ModuleFederationLoggingPlugin({
      // Specify options here
    })
  ]
};

export default config;
Enter fullscreen mode Exit fullscreen mode

Run webpack to build the project.

npx webpack
Enter fullscreen mode Exit fullscreen mode

That's it! You have now created a webpack plugin in TypeScript that wraps module federation and adds additional logging.

Modifying the results

Seeing what the results were it was quite verbose, but it does not follow the platform I usually like to use, @nrwl_io's Nx. So I did a redirect on the conversation.

how can I simplify the steps by using Nx

Using Nx (Nrwl Extensions for Angular) can simplify the process of creating a webpack plugin in TypeScript that wraps module federation and adds additional logging. Nx is a set of open-source tools and libraries that can help you develop full-stack applications more efficiently.

To use Nx to create a webpack plugin, follow these steps:

Install the Nx CLI:

npm install -g @nrwl/cli
Enter fullscreen mode Exit fullscreen mode

Create a new Nx workspace:

npx create-nx-workspace my-workspace
Enter fullscreen mode Exit fullscreen mode

In the Nx workspace, create a new library for the webpack plugin:

npx nx g @nrwl/workspace:lib module-federation-logging-plugin
Enter fullscreen mode Exit fullscreen mode

In the library directory, create a tsconfig.json file to configure the TypeScript compiler. In the compilerOptions object, set the module option to "commonjs" and the target option to "esnext". This will ensure that the generated JavaScript code is compatible with webpack.

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "esnext"
  }
}
Enter fullscreen mode Exit fullscreen mode

In the library directory, create a new TypeScript file for the plugin, such as src/module-federation-logging-plugin.ts. In this file, create a new class for the plugin that extends the ModuleFederationPlugin class and implements the apply method. In the apply method, you can wrap the ModuleFederationPlugin and add additional logging.

import { Compiler, Plugin } from 'webpack';
import { ModuleFederationPlugin } from '@module-federation/client';

export class ModuleFederationLoggingPlugin implements Plugin {
  private readonly moduleFederationPlugin: ModuleFederationPlugin;

  constructor(options: any) {
    this.moduleFederationPlugin = new ModuleFederationPlugin(options);
  }

  apply(compiler: Compiler) {
    this.moduleFederationPlugin.apply(compiler);

    // Add additional logging here
  }
}
Enter fullscreen mode Exit fullscreen mode

In the libs/module-federation-logging-plugin/tsconfig.lib.json file, add a typeRoots field to specify the path to the TypeScript declaration files for the webpack and @module-federation/client packages. This will allow the TypeScript compiler to find the type definitions for these packages.

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "../../dist/out-tsc",
    "typeRoots": [
      "node_modules/@types",
      "node_modules/@module-federation/client/node_modules/@types"
    ]
  },
  "include": ["src/**/*.ts"]
}
Enter fullscreen mode Exit fullscreen mode

In the libs/module-federation-logging-plugin/src/index.ts file, export the ModuleFederationLoggingPlugin class. This will allow other projects in the Nx workspace to use the

Second timeout

You can see that I received another timeout due to the length of the response. This time instead of just asking it to continue I tried to get it to pick back up from step 7 which was incomplete.

repeat the content of step 7 and keep going

Sure, here is the content of step 7:

In the libs/module-federation-logging-plugin/src/index.ts file, export the ModuleFederationLoggingPlugin class. This will allow other projects in the Nx workspace to use the plugin.

export { ModuleFederationLoggingPlugin } from './module-federation-logging-plugin';
Enter fullscreen mode Exit fullscreen mode

Here are the next steps:

In the Nx workspace, create a new application that will use the webpack plugin:

npx nx g @nrwl/angular:app my-app
Enter fullscreen mode Exit fullscreen mode

Install the necessary dependencies for module federation:

npm install --save-dev @module-federation/client
Enter fullscreen mode Exit fullscreen mode

In the apps/my-app/src/webpack.config.ts file, import the ModuleFederationLoggingPlugin class from the library and add an instance of it to the plugins array in the webpack configuration object. You can also specify the options for the plugin by passing an object to the constructor.

import { Configuration } from 'webpack';
import { ModuleFederationLoggingPlugin } from '@my-workspace/module-federation-logging-plugin';

const config: Configuration = {
  // Other configuration options
  plugins: [
    new ModuleFederationLoggingPlugin({
      // Specify options here
    })
  ]
};

export default config;
Enter fullscreen mode Exit fullscreen mode

Run webpack to build the application:

npx nx run my-app:build
Enter fullscreen mode Exit fullscreen mode

That's it! You have now used Nx to create a webpack plugin in TypeScript that wraps module federation and adds additional logging.

One more tweak

Just to see how far I can go I wanted to add some documentation. No plugin is complete without documentation right?

can you add swagger documentation to the src/module-federation-logging-plugin.ts file

To add Swagger documentation to the src/module-federation-logging-plugin.ts file, you can use Swagger annotations in the form of JSDoc comments. JSDoc is a documentation standard for JavaScript that is widely supported by tools like Swagger.

Here is an example of how you can add Swagger documentation to the ModuleFederationLoggingPlugin class:

import { Compiler, Plugin } from 'webpack';
import { ModuleFederationPlugin } from '@module-federation/client';


/**
 * A webpack plugin that wraps module federation and adds additional logging.
 *
 * @param {Object} options - The options for the plugin.
 * @param {string} options.remoteName - The name of the remote module.
 * @param {string} options.remoteType - The type of the remote module.
 * @param {string} options.remoteUrl - The URL of the remote module.
 */
export class ModuleFederationLoggingPlugin implements Plugin {
  private readonly moduleFederationPlugin: ModuleFederationPlugin;

  constructor(options: any) {
    this.moduleFederationPlugin = new ModuleFederationPlugin(options);
  }

  apply(compiler: Compiler) {
    this.moduleFederationPlugin.apply(compiler);

    // Add additional logging here
  }
}
Enter fullscreen mode Exit fullscreen mode

You can then use a tool like Swagger UI or ReDoc to generate a documentation website from the Swagger annotations. To do this, you will need to generate a Swagger JSON file from the annotations. There are various tools and libraries that can do this, such as swagger-jsdoc and swagger-ui-express.

Here is an example of how you can use swagger-ui-express to generate a Swagger documentation website:

Install the necessary dependencies:

npm install --save swagger-ui-express swagger-jsdoc
Enter fullscreen mode Exit fullscreen mode

Create a swagger.js file with the following code:

const swaggerUi = require('swagger-ui-express');
const swaggerJSDoc = require('swagger-jsdoc');

// Swagger definition
const swaggerDefinition = {
  openapi: '3.0.0',
  info: {
    title: 'Module Federation Logging Plugin',
    version: '1.0.0',
    description: 'A webpack plugin that wraps module federation and adds additional logging.'
  },
  servers: [
    {
      url: 'http://localhost:3000'
    }
  ]
};

// Options for the swagger-jsdoc library
const options = {
  swaggerDefinition,
  apis: ['./src/module-federation-logging-plugin.ts']
};

// Initialize the Swagger document
const swaggerSpec = swaggerJSDoc(options);

module.exports = app => {
  app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
};
Enter fullscreen mode Exit fullscreen mode

In your application's main file, such as index.js, require the swagger.js file and pass the express app instance to it:

const express = require('express');
const app = express();
Enter fullscreen mode Exit fullscreen mode

Summary

After about 5 minutes I have code that is pretty close to what I was expecting. It has more comments and guidance than I would have created on my own, and for the most part follows some pretty decent best practices.

ChatGTP was able to accept redirects that were pretty technical in nature, with little context, and adjust the output appropriately.

While not a replacement for a developer that is experienced this tooling and process can help to learn new frameworks, patterns and create functionality more rapidly.

Combining highly skilled engineers with ChatGPT will in the near future (if not now) increase their velocity. Combining new engineers with ChatGPT will aid in their exposure to practices that they can then begin to understand and question in their learning journey.

What exciting times we live in!

💖 💪 🙅 🚩
zchapple
Zackary Chapple

Posted on December 16, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

webpack Plugin written by ChatGPT
chatgpt webpack Plugin written by ChatGPT

December 16, 2022