You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为新Webpack项目创建类似vue-cli的菜单式配置?

How to Build an Interactive Menu-Driven Setup for Your Webpack Templates

Hey there! Great question—those interactive setup flows you saw in vue-cli are perfect for simplifying configurations when you’ve got a core template with lots of options. Here’s exactly how you can replicate this for your own Webpack projects:

Core Tools You’ll Need

The magic behind vue-cli’s interactive prompts comes from Inquirer.js, a popular library for creating command-line user interfaces. You’ll also want a template engine (like Handlebars) to dynamically replace values in your template files, and Node’s built-in fs module for file operations.

Step-by-Step Implementation

1. Set Up Your Template Project Structure

First, organize your files like this:

my-webpack-template/
├── templates/          # Your base template files
│   ├── package.json.hbs  # Template with placeholder variables
│   ├── webpack.config.js.hbs
│   └── .eslintrc (optional)
├── setup.js            # Your interactive setup script
└── package.json

2. Install Dependencies

Run these commands to install the required packages:

npm install inquirer handlebars --save-dev

3. Write the Interactive Setup Script

Create setup.js with code like this to define your prompts and handle user input:

const inquirer = require('inquirer');
const fs = require('fs');
const handlebars = require('handlebars');
const path = require('path');

// Define your interactive questions
const questions = [
  {
    type: 'input',
    name: 'projectName',
    message: 'Project name:',
    default: 'my-custom-project'
  },
  {
    type: 'input',
    name: 'projectDescription',
    message: 'Project description:',
    default: 'A custom Webpack-powered project'
  },
  {
    type: 'input',
    name: 'author',
    message: 'Author:',
    default: `${process.env.USER} <${process.env.USER}@example.com>`
  },
  // Add custom options for your core template
  {
    type: 'confirm',
    name: 'enableEslint',
    message: 'Enable ESLint for code linting?',
    default: true
  },
  {
    type: 'list',
    name: 'cssPreprocessor',
    message: 'Choose a CSS preprocessor:',
    choices: ['Sass', 'Less', 'Stylus', 'None'],
    default: 'Sass'
  },
  {
    type: 'checkbox',
    name: 'additionalFeatures',
    message: 'Select additional features:',
    choices: [
      { name: 'Hot Module Replacement', value: 'hmr' },
      { name: 'PWA Support', value: 'pwa' },
      { name: 'Unit Testing with Jest', value: 'jest' }
    ]
  }
];

// Run the prompts and process answers
inquirer.prompt(questions).then(answers => {
  // Create the target project directory
  const projectDir = path.join(process.cwd(), answers.projectName);
  fs.mkdirSync(projectDir, { recursive: true });

  // Process and write template files
  const templateFiles = fs.readdirSync('./templates');
  templateFiles.forEach(file => {
    if (file.endsWith('.hbs')) {
      // Compile Handlebars template
      const templatePath = path.join('./templates', file);
      const templateContent = fs.readFileSync(templatePath, 'utf8');
      const compiledTemplate = handlebars.compile(templateContent);
      const outputContent = compiledTemplate(answers);
      
      // Remove .hbs extension for the final file
      const outputFileName = file.replace('.hbs', '');
      const outputPath = path.join(projectDir, outputFileName);
      fs.writeFileSync(outputPath, outputContent);
    } else {
      // Copy non-template files (like .eslintrc) conditionally
      if (file === '.eslintrc' && answers.enableEslint) {
        const sourcePath = path.join('./templates', file);
        const outputPath = path.join(projectDir, file);
        fs.copyFileSync(sourcePath, outputPath);
      }
    }
  });

  console.log(`✅ Project "${answers.projectName}" has been set up successfully!`);
});

4. Create Template Files with Placeholders

For example, your templates/package.json.hbs would include variables that match the answer keys from your prompts:

{
  "name": "{{projectName}}",
  "version": "1.0.0",
  "description": "{{projectDescription}}",
  "author": "{{author}}",
  "scripts": {
    "build": "webpack --mode production",
    "dev": "webpack serve --mode development {{#if additionalFeatures.includes('hmr')}}--hot{{/if}}"
  },
  "devDependencies": {
    "webpack": "^5.0.0",
    "webpack-cli": "^4.0.0",
    {{#if enableEslint}}"eslint": "^8.0.0",{{/if}}
    {{#if cssPreprocessor !== 'None'"{{cssPreprocessor.toLowerCase()}}-loader": "^10.0.0",{{/if}}
    {{#if additionalFeatures.includes('jest')}}"jest": "^27.0.0",{{/if}}
  }
}

5. Run the Setup Script

Add a script to your package.json to make it easy to run:

{
  "scripts": {
    "init": "node setup.js"
  }
}

Then users can run:

npm run init

Or if you want to make it a global CLI tool, add a bin entry to package.json and run npm link:

{
  "bin": {
    "my-webpack-init": "./setup.js"
  }
}

Now users can run:

my-webpack-init

Key Notes

  • Question Types: Inquirer supports many types (input, confirm, list, checkbox, etc.)—mix and match to fit your options.
  • Conditional Logic: Use Handlebars helpers or plain JavaScript to add conditional logic (like including ESLint only if the user opted in).
  • Error Handling: Add try/catch blocks around file operations to handle cases where the project directory already exists.

内容的提问来源于stack exchange,提问作者sn4ke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:23:52