webpack Plugin written by ChatGPT
Zackary Chapple
Posted on December 16, 2022
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
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"
}
}
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;
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;
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;
Install the necessary dependencies for module federation:
npm install --save-dev @module-federation/client
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
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
}
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
}
}
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;
Run webpack to build the project.
npx webpack
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
Create a new Nx workspace:
npx create-nx-workspace my-workspace
In the Nx workspace, create a new library for the webpack plugin:
npx nx g @nrwl/workspace:lib module-federation-logging-plugin
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"
}
}
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
}
}
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"]
}
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';
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
Install the necessary dependencies for module federation:
npm install --save-dev @module-federation/client
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;
Run webpack to build the application:
npx nx run my-app:build
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
}
}
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
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));
};
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();
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!
Posted on December 16, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.