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

Feat: init create webpack app #4167

Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
f910fe3
feat: init new package and installed deps
maverox May 13, 2024
c175c9d
feat: add template directory from prototype
maverox May 13, 2024
12fbc20
build: typescript init
maverox May 15, 2024
92c2f19
build: set type: module in package.json
maverox May 15, 2024
488f3df
feat: change template to align more with generators package
maverox May 16, 2024
a17fa63
feat: add core logic to run generators and also add types
maverox May 16, 2024
bb6ca9f
chore: add scripts in package.json
maverox May 16, 2024
d5e9fc3
build: change module type to esm in package.json
maverox May 16, 2024
667d50d
feat: add entrypoint executable which wraps the generator cli
maverox May 16, 2024
8f89b98
chore: add ejs and @types/ejs as dependencies
maverox May 18, 2024
d2ca7f6
build: change emit module of tsc to esnext
maverox May 18, 2024
acf5fa5
feat: add ejs template rendering support
maverox May 18, 2024
df39698
feat: add entryPoint prompt
maverox May 18, 2024
93c2142
chore: remove unused code
maverox May 18, 2024
85b06bc
chore: change eslint and cspell silencer
maverox May 19, 2024
88acfd2
build: change plopfile.ts on reviews
maverox May 19, 2024
55e13ec
feat: change the templates
maverox May 19, 2024
897e00b
fix: fix missing comma in tsconfig
maverox May 19, 2024
f9cb74a
chore: change package.json on reviews
maverox May 19, 2024
b6baa6a
docs: change readme based on review
maverox May 19, 2024
d9a0856
fix: customACtionConfig support in plopfile.ts setGenerator config pr…
maverox May 27, 2024
d8ec7e1
feat: add npmInstall custom package
maverox Jun 1, 2024
4c59396
chore: remove redundant code
maverox Jun 1, 2024
04b5f90
fix: typo in prompt
maverox Jun 1, 2024
1bdf924
feat: add skip prompt functionality
maverox Jun 5, 2024
5e6a70b
chore: install commander and remove obsolete deps
maverox Jun 7, 2024
bb5e201
refactor: remove dynamic prompt and revert to previous state
maverox Jun 7, 2024
9bf21bf
feat: create commander cli and implement skip feat
maverox Jun 7, 2024
a295914
refactor: change prompt order to have genPath as first
maverox Jun 8, 2024
e6add83
refactor: change console output format for deps installation
maverox Jun 8, 2024
4ac8bf0
feat: change -s flag to -f|--force and make it default
maverox Jun 8, 2024
d1fb3e7
chore: add 'uzair' as a word for cspell
maverox Jun 8, 2024
2928772
test: create test suite for create-webpack-app package
maverox Jun 8, 2024
3f66230
Update packages/create-webpack-app/README.md
maverox Jun 15, 2024
769e095
Update packages/create-webpack-app/README.md
maverox Jun 15, 2024
cb309df
refactor: migrate cli logic to ts from js
maverox Jun 25, 2024
860e5c2
feat: add conditional file generation based on dynamic action function
maverox Jun 25, 2024
de92604
docs: change doc to align with its features
maverox Jun 25, 2024
b150fa8
feat: change dependency installation to be cross-compatible
maverox Jun 25, 2024
f3315f4
refactor: remove unused var
maverox Jun 25, 2024
19f59ea
feat: add types
maverox Jun 25, 2024
02f04cb
chore: enable eslint for package/create-webpack-app
maverox Jun 25, 2024
284ab14
chore: change module type and fix control flow for errors
maverox Jun 25, 2024
b80f340
feat: add logger utility module
maverox Jul 1, 2024
944bb33
refactor: refactor and implement logger
maverox Jul 1, 2024
b82f4be
feat: change stdio settings for pkgInstall action
maverox Jul 1, 2024
b4cca8f
fix: change conditional prompt to align with original logic
maverox Jul 1, 2024
e3ef415
test: implement test according to package
maverox Jul 1, 2024
0a42c64
fix: changed template package.json to improve compatibility with syntax
maverox Jul 1, 2024
f0196bd
chore: add peerDep webpack-cli and dep colorette
maverox Jul 1, 2024
8e9dfb6
feat: remove projectName and use path only
maverox Jul 4, 2024
ff53355
chore: remove "uzair" as word from cspell.json
maverox Jul 4, 2024
22873e8
chore: remove test/create-webpack-app from .eslintignore
maverox Jul 7, 2024
fdd61df
perf: change generator conditional flows and dependencies attached
maverox Jul 7, 2024
ea92e56
refactor: remove redundant code from test.utils and extend from utils…
maverox Jul 7, 2024
3fb7b98
test: update snapshots and test according to previous two commits
maverox Jul 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
"testname",
"Tobio",
"tsbuildinfo",
"uzair",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh I added this before I knew about Cspell:ignore

I will remove this in the next commit
"uzair" is my name actually

"typeahead",
"wagoid",
"webassembly",
Expand Down
3 changes: 3 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ test/build/config/error-commonjs/syntax-error.js
test/build/config/error-mjs/syntax-error.mjs
test/build/config/error-array/webpack.config.js
test/configtest/with-config-path/syntax-error.config.js

packages/create-webpack-app
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should run ESlint on all packages.


41 changes: 41 additions & 0 deletions packages/create-webpack-app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<div>
<a href="https://github.com/webpack/webpack-cli">
<img width="200" height="200" src="https://webpack.js.org/assets/icon-square-big.svg">
</a>
</div>

# create-webpack-app CLI

## About

- `create-webpack-app` is a cli tool that enables developers to quickly scaffold a new webpack project. It provides a flexible set of commands for developers to increase speed when setting up a custom webpack project. webpack CLI addresses these needs by providing a set of tools to improve the setup of custom webpack configuration.
maverox marked this conversation as resolved.
Show resolved Hide resolved
- It is also going to support several front end frameworks and libraries like React, Angular, Vue, Svelte, etc.
maverox marked this conversation as resolved.
Show resolved Hide resolved
- Webpack Loader and Plugin scaffolding is also supported.

## How to install

```bash
npm install --save-dev @webpack-cli/create-webpack-app
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Installing it locally should not be required, npx create-react-app my-app should work directly.

```

or

```bash
yarn add @webpack-cli/create-webpack-app --dev
```

## Supported arguments and commands

### Usage

All interactions with create-webpack-app are of the form

```bash
npx create-webpack-app [command] [options]
```

### Help Usage

### Available Commands

### Available Options
55 changes: 55 additions & 0 deletions packages/create-webpack-app/bin/cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Command } from "commander";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use the webpack-cli package? It also offers utilities like logger. Checkout the CLI tests for more info.

import { resolve, join } from "path";
import nodePlop from "node-plop";
// Cspell:ignore plopfile, plopfile.js

const program = new Command();
const plop = await nodePlop("./lib/plopfile.js");
const defaultValues = {
init: {
projectPath: resolve(join(process.cwd(), ".")),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Writing this could be cumbersome, how about default to scaffold in the current dir? I think it's a standard to scaffold in the current dir.

Thoughts? @snitin315 @evenstensberg

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we don't have to ask the project path we can just scaffold files in cwd/project-name.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in a recent local commit I have changed the default projectPath to process.cwd() so the generator defaults to
cwd/project-name,
but do you want me to remove the prompt where it asks generation path?(because that is important for bypassing with argument for genPath)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if the user wants to define a custom path they can just name the project like - folder1/folder2/project-name This will create this file hierarchy in the current cwd

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should I name this ?
genPath? or name?

projectName: "webpack-project",
langType: "none",
devServer: true,
htmlWebpackPlugin: true,
workboxWebpackPlugin: true,
cssType: "CSS only",
isCSS: true,
isPostCSS: true,
extractPlugin: "No",
packageManager: "npm",
},
};

program
.version("1.0.0", "-v, --version")
.usage("[command] [options]")
.helpOption("-h, --help", "Display help for command")
.description("A CLI tool to generate a Webpack project");

program
.command("init", { isDefault: true })
.aliases(["i", "c", "create", "new"])
.description("Initialize a new Webpack project")
.argument("[projectPath]", "Path to create the project")
.argument("[projectName]", "Name of the project")
.option("-f, --force", "Skip the prompt and use the default values", false)
.action(function (projectName, projectPath, opts) {
console.log("Initializing a new Webpack project");
const { force } = opts;
const initGenerator = plop.getGenerator("init");
const byPassValues = [];
if (projectName) byPassValues.push(projectName);
if (projectPath) byPassValues.push(projectPath);

if (force) {
console.log("Skipping the prompt and using the default values");
initGenerator.runActions(defaultValues.init);
} else {
initGenerator.runPrompts(byPassValues).then((answers) => {
initGenerator.runActions(answers);
});
}
});

program.parse();
50 changes: 50 additions & 0 deletions packages/create-webpack-app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"name": "create-webpack-app",
"version": "1.0.0",
"description": "CLI for scaffolding webpack projects using default config, framework templates, loader or plugins templates",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/webpack-cli/create-webpack-app.git"
},
"homepage": "https://github.com/webpack/webpack-cli/tree/master/packages/create-webpack-app",
"bugs": "https://github.com/webpack/webpack-cli/issues",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"bin": {
"create-webpack-app": "./bin/cli.js"
},
"type": "module",
"main": "./lib/index.js",
"scripts": {
"build": "tsc --build",
"watch": "tsc --watch"
},
"engines": {
"node": ">=18.12.0"
},
"keywords": [
"webpack",
"cli",
"scaffolding",
"module",
"bundler",
"web",
"frameworks"
],
"files": [
"bin",
"lib",
"!**/*__tests__"
],
"dependencies": {
"commander": "^12.1.0",
"ejs": "^3.1.10",
"node-plop": "^0.32.0"
},
"devDependencies": {
"@types/ejs": "^3.1.5"
}
}
1 change: 1 addition & 0 deletions packages/create-webpack-app/src/generators/default.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// refactored generator will be written here shortly
205 changes: 205 additions & 0 deletions packages/create-webpack-app/src/plopfile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
import { NodePlopAPI, Answers } from "./types";
import { resolve, join } from "path";
import ejs from "ejs";
import { spawn } from "child_process";
export default function (plop: NodePlopAPI) {
const dependencies = ["webpack", "webpack-cli"];
plop.setActionType("pkgInstall", (answers) => {
const options = {
cwd: `${answers.projectPath}/${answers.projectName}`,
encoding: "utf-8",
};
if (answers.devServer) {
dependencies.push("webpack-dev-server");
}
if (answers.htmlWebpackPlugin) {
dependencies.push("html-webpack-plugin", "html-loader");
}
if (answers.workboxWebpackPlugin) {
dependencies.push("workbox-webpack-plugin");
}
if (answers.isPostCSS) {
dependencies.push("postcss-loader", "autoprefixer");
}
console.log(`Installing packages: ${dependencies.join("\n")}`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use logger utility from webpack-cli

const returnMessage = `Project ${answers.projectName} has been successfully created at ${answers.projectPath}/${answers.projectName}`;

const packageManager = answers.packageManager;
const installCommandPrefix = packageManager === "yarn" ? "add" : "install";

const npmInstallPackages = spawn(
`${packageManager}`,
[`${installCommandPrefix}`, ...dependencies],
options,
);
npmInstallPackages.stdout.on("data", (data) => {
console.log(data.toString());
});
npmInstallPackages.stderr.on("data", (data) => {
console.error(data.toString());
});
npmInstallPackages.on("close", (code) => {
if (code !== 0) {
console.error(`child process exited with code ${code}`);
return;
} else {
console.log(returnMessage);
}
});
return "Package Installation Phase..."; // executes before the child process is completed
});
// Define a base generator for the project structure
plop.setGenerator("init", {
description: "Create a basic Webpack project",
prompts: [
{
type: "input",
name: "projectPath",
message: "Enter the project destination:",
default: ".",
filter: (input) => {
return resolve(join(process.cwd(), input));
},
},
{
type: "input",
name: "projectName",
message: "Enter your project name:",
default: "webpack-project",
validate(input, _) {
if (!input.trim()) {
return "Project name cannot be empty";
}
return true;
},
},
{
type: "list",
name: "langType",
message: "Which of the following JS solutions do you want to use?",
choices: ["none", "ES6", "Typescript"],
default: "none",
filter: (input, _) => {
switch (input) {
case "ES6":
dependencies.push("babel-loader", "@babel/core", "@babel/preset-env");
break;
case "Typescript":
dependencies.push("typescript", "ts-loader");
break;
}
return input;
},
},
{
type: "confirm",
name: "devServer",
message: "Would you like to use Webpack Dev server?",
default: true,
},
{
type: "confirm",
name: "htmlWebpackPlugin",
message: "Do you want to simplify the creation of HTML files for your bundle?",
default: true,
},
{
type: "confirm",
name: "workboxWebpackPlugin",
message: "Do you want to add PWA support?",
default: true,
},
{
type: "list",
name: "cssType",
message: "Which of the following CSS solution do you want to use?",
choices: ["none", "CSS only", "SASS", "LESS", "Stylus"],
default: "Css only",
filter: (input, answers) => {
if (input === "none") {
answers.isCSS = false;
answers.isPostCSS = false;
answers.extractPlugin = "No";
} else {
dependencies.push("style-loader", "css-loader");
switch (input) {
case "CSS only":
answers.isCSS = true;
break;
case "SASS":
dependencies.push("sass-loader", "node-sass");
break;
case "LESS":
dependencies.push("less-loader", "less");
break;
case "Stylus":
dependencies.push("stylus-loader", "stylus");
break;
}
}
return input;
},
},
{
type: "confirm",
name: "isCSS",
message: (answers) =>
`Will you be using CSS styles along with ${answers.cssType} in your project?`,
when: (answers) => answers.cssType !== "CSS only",
default: true,
},
{
type: "confirm",
name: "isPostCSS",
message: "Do you want to use PostCSS in your project?",
when: (answers) => answers.isCSS,
default: true,
},
{
type: "list",
name: "extractPlugin",
message: "Do you want to extract CSS into separate files?",
choices: ["No", "Only for Production", "Yes"],
when: (answers) => answers.isCSS,
default: "No",
filter: (input, _) => {
if (input !== "No") {
dependencies.push("mini-css-extract-plugin");
}
return input;
},
},
{
type: "list",
name: "packageManager",
message: "Which package manager do you want to use?",
choices: ["npm", "yarn"],
default: "npm",
validate(input, _) {
if (!input.trim()) {
return "Package manager cannot be empty";
}
return true;
},
},
],
actions: [
{
type: "addMany",
destination: "{{projectPath}}/{{dashCase projectName}}",
base: "../templates/init/default",
templateFiles: "../templates/init/default/**/*",
transform: (content, data) => {
data.entryPoint = data.langType === "Typescript" ? "index.ts" : "index.js";
return ejs.render(content, data);
},
stripExtensions: ["tpl"],
force: true,
verbose: true,
},
{
type: "pkgInstall",
},
],
});
}
24 changes: 24 additions & 0 deletions packages/create-webpack-app/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export type {
ActionConfig,
AddActionConfig,
AddManyActionConfig,
AppendActionConfig,
CustomActionFunction,
ModifyActionConfig,
PlopCfg,
PlopGenerator,
NodePlopAPI,
PlopGeneratorConfig,
Actions,
} from "node-plop";
export interface Answers extends Record<string, any> {}

import { ActionType as ActionTypeBase, CustomActionConfig } from "node-plop";
// extended ACtionType to include custom action config as previously it was not recognizing
export type ActionType = ActionTypeBase | CustomActionConfig<string>;
export type InitOptions = { template: string; force?: boolean };
export type LoaderOptions = { template: string };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RE: slack conv, you should make this generic. You see the pattern

Copy link
Collaborator Author

@maverox maverox May 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I will work on this soon,
I will definitely use the already established types and interfaces in @generators package as inspiration and tweak them.

export type PluginOptions = { template: string };
export type InitGeneratorOptions = { generationPath: string } & InitOptions;
export type LoaderGeneratorOptions = { generationPath: string } & LoaderOptions;
export type PluginGeneratorOptions = { generationPath: string } & PluginOptions;
Loading
Loading