From 724c239fa64786cc0e9772ecd0e7ece764b367b5 Mon Sep 17 00:00:00 2001 From: CarGDev Date: Tue, 1 Jul 2025 21:53:59 -0400 Subject: [PATCH] feat: migrate scaffolding to vite --- README.md | 8 ++-- index.js | 21 ++++---- package.json | 13 ++--- pre-files/vite.config.js | 1 + pre-files/webpack.config.js | 93 ------------------------------------ src/config/vite.config.js | 1 + src/config/webpack.config.js | 1 - src/setup/deps.js | 14 +----- src/setup/devDeps.js | 8 ++-- src/setup/init.js | 12 ++--- src/templates/packageJson.js | 11 +++-- structure.js | 2 +- 12 files changed, 38 insertions(+), 147 deletions(-) create mode 100644 pre-files/vite.config.js delete mode 100644 pre-files/webpack.config.js create mode 100644 src/config/vite.config.js delete mode 100644 src/config/webpack.config.js diff --git a/README.md b/README.md index 243e423..1a63d60 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ # React Crafter -**React Crafter** is a CLI tool designed to quickly scaffold a modern React application with TypeScript, Ant Design, Sass, Webpack, and essential development tools like Husky and linters pre-configured. This tool simplifies the initial setup, allowing developers to start coding with best practices from the get-go. +**React Crafter** is a CLI tool designed to quickly scaffold a modern React application with TypeScript, Ant Design, Sass, Vite, and essential development tools like Husky and linters pre-configured. This tool simplifies the initial setup, allowing developers to start coding with best practices from the get-go. ## Features - **React with TypeScript**: Automatically sets up a React project using TypeScript. - **Ant Design Integration**: Includes Ant Design (antd) for UI components, fully integrated with your project. - **Sass Support**: Configures Sass for better styling with variables, mixins, and more. -- **Webpack Configuration**: Custom Webpack setup for development and production builds. +- **Vite Configuration**: Fast bundler setup for development and production builds. - **Husky & Linters**: Pre-configured Git hooks with Husky, Commitlint, and Prettier to enforce code quality and style. - **Atomic Design Structure**: Creates an atomic design folder structure to organize your components. - **Redux Setup**: Sets up Redux with slices, middleware, and selectors for state management. @@ -53,7 +53,7 @@ Here’s a summary of the commands you can use after setting up your project: npm start ``` - Starts the development server with Webpack. The project is served using Webpack Dev Server with the configuration specified in `webpack.config.js`. + Starts the development server with Vite. The project is served using the Vite dev server. 2. **Build for Production**: @@ -61,7 +61,7 @@ Here’s a summary of the commands you can use after setting up your project: npm run build ``` - Builds the project for production. Webpack compiles the project and outputs the optimized bundle in the `/dist` directory. + Builds the project for production. Vite compiles the project and outputs the optimized bundle in the `dist` directory. 3. **Run Tests**: diff --git a/index.js b/index.js index b83e1ff..2122232 100755 --- a/index.js +++ b/index.js @@ -147,17 +147,17 @@ function printCommandSummary() { console.log(chalk.yellow('\nπŸ”‘ Project Setup Summary:')); console.log(chalk.cyan('\nAvailable Commands:')); - console.log(chalk.green('1. πŸš€ npm start')); + console.log(chalk.green('1. πŸš€ npm run dev')); console.log( chalk.white( - ' Starts the development server with Webpack. The project is served using Webpack Dev Server with the configuration specified in webpack.config.js.' + ' Starts the development server with Vite.' ) ); console.log(chalk.green('\n2. πŸ› οΈ npm run build')); console.log( chalk.white( - ' Builds the project for production. Webpack compiles the project and outputs the optimized bundle in the /dist directory.' + ' Builds the project for production using Vite.' ) ); @@ -270,15 +270,14 @@ function updatePackageJson() { const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); packageJson.scripts = { - start: 'webpack serve --config webpack.config.js --mode development', - build: 'webpack --config webpack.config.js --mode production', + dev: 'vite', + build: 'vite build', + preview: 'vite preview', test: 'echo "Error: no test specified" && exit 0', - 'test:dev': 'react-scripts test', 'pretty-quick': 'pretty-quick', 'lint:prettier': 'node check-format.js', prettier: 'prettier --write . --config .prettierrc', 'prettier:commit': 'node prettier-commit.js', - eject: 'react-scripts eject', prepare: 'husky install', }; @@ -307,8 +306,8 @@ function copyPreConfiguredFiles(destinationPath) { dest: path.join(destinationPath, 'prettier-commit.js'), }, { - src: path.resolve(__dirname, 'pre-files/webpack.config.js'), - dest: path.join(destinationPath, 'webpack.config.js'), + src: path.resolve(__dirname, 'pre-files/vite.config.js'), + dest: path.join(destinationPath, 'vite.config.js'), }, { src: path.resolve(__dirname, 'pre-files/.babelrc'), @@ -340,7 +339,7 @@ function copyPreConfiguredFiles(destinationPath) { function installDependencies(verboseFlag, stdioOption) { const spinner = ora('πŸ”„ Installing additional dependencies...').start(); execSync( - `npm install @babel/core @babel/preset-env @babel/preset-react @reduxjs/toolkit @testing-library/jest-dom @testing-library/react @testing-library/user-event @types/jest @types/node @types/react @types/react-dom ajv antd babel-loader css-loader jest playwright react react-dom react-redux react-scripts redux sass sass-loader style-loader typescript web-vitals webpack webpack-cli ${verboseFlag}`, + `npm install @reduxjs/toolkit @testing-library/jest-dom @testing-library/react @testing-library/user-event @types/jest @types/node @types/react @types/react-dom ajv antd jest playwright react react-dom react-redux redux sass typescript web-vitals ${verboseFlag}`, { stdio: stdioOption } ); spinner.succeed('βœ… Additional dependencies installed.'); @@ -349,7 +348,7 @@ function installDependencies(verboseFlag, stdioOption) { function installDevDependencies(verboseFlag, stdioOption) { const spinner = ora('πŸ”„ Installing additional dev dependencies...').start(); execSync( - `npm install --save-dev @babel/plugin-proposal-private-property-in-object ora prettier @commitlint/cli @commitlint/config-conventional @svgr/webpack dotenv dotenv-webpack husky url-loader webpack-dev-server pretty-quick ${verboseFlag}`, + `npm install --save-dev @babel/plugin-proposal-private-property-in-object ora prettier @commitlint/cli @commitlint/config-conventional dotenv husky pretty-quick vite @vitejs/plugin-react ${verboseFlag}`, { stdio: stdioOption } ); spinner.succeed('βœ… Additional dev dependencies installed.'); diff --git a/package.json b/package.json index c425e22..5118001 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "react-crafter", "version": "1.1.3", - "description": "A CLI tool to quickly scaffold a React application with TypeScript, Ant Design, Sass, Webpack, and essential development tools like Husky and linters pre-configured. Perfect for kickstarting modern React projects with best practices.", + "description": "A CLI tool to quickly scaffold a React application with TypeScript, Ant Design, Sass, Vite, and essential development tools like Husky and linters pre-configured. Perfect for kickstarting modern React projects with best practices.", "main": "index.js", "bin": { "react-crafter": "bin/cli.js" @@ -11,7 +11,7 @@ "typescript", "antd", "sass", - "webpack", + "vite", "cli", "husky", "linter", @@ -59,9 +59,6 @@ "@commitlint/cli": "^19.4.0", "@commitlint/config-conventional": "^19.2.2", "@types/jest": "^29.5.14", - "babel-loader": "^8.2.2", - "css-loader": "^5.1.1", - "dotenv-webpack": "^7.0.2", "eslint": "^9.9.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jsdoc": "^50.2.1", @@ -70,11 +67,9 @@ "jest": "^29.7.0", "prettier": "^3.3.3", "pretty-quick": "^4.0.0", - "sass-loader": "^11.0.1", - "style-loader": "^2.0.0", "ts-jest": "^29.2.5", "ts-node": "^10.9.2", - "webpack": "^5.24.3", - "webpack-cli": "^4.5.0" + "vite": "^5.0.0", + "@vitejs/plugin-react": "^4.0.0" } } diff --git a/pre-files/vite.config.js b/pre-files/vite.config.js new file mode 100644 index 0000000..ccf9066 --- /dev/null +++ b/pre-files/vite.config.js @@ -0,0 +1 @@ +import { defineConfig } from 'vite';\nimport react from '@vitejs/plugin-react';\n\nexport default defineConfig({\n plugins: [react()],\n}); diff --git a/pre-files/webpack.config.js b/pre-files/webpack.config.js deleted file mode 100644 index 7906075..0000000 --- a/pre-files/webpack.config.js +++ /dev/null @@ -1,93 +0,0 @@ -const path = require('path'); -const Dotenv = require('dotenv-webpack'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); -const MiniCssExtractPlugin = require('mini-css-extract-plugin'); - -module.exports = { - mode: 'development', - entry: './src/index.tsx', - target: 'web', - module: { - rules: [ - { - test: /\.(js|jsx|ts|tsx)$/, - exclude: /node_modules/, - use: { - loader: 'babel-loader', - options: { - presets: [ - ['@babel/preset-env', { targets: { esmodules: true } }], - '@babel/preset-react', - '@babel/preset-typescript', - ], - }, - }, - }, - { - test: [/\.s[ac]ss$/i, /\.css$/i], - use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'], - }, - { - test: /\.svg$/, - use: ['@svgr/webpack'], - }, - { - test: /\.(png|jpg|jpeg|gif|bmp|webp|svg)$/, // Handle various image formats - use: [ - { - loader: 'url-loader', - options: { - limit: 8192, // Inline images below 8KB as base64 URLs, otherwise fallback to file-loader - name: '[name].[hash:8].[ext]', - outputPath: 'static/media/', // Output folder for images - esModule: false, // To avoid issues with React's handling of imports - }, - }, - ], - }, - ], - }, - plugins: [ - new Dotenv({ - path: path.resolve(__dirname, '.env'), // Load the .env file from the project root - }), - new HtmlWebpackPlugin({ - template: './public/index.html', - filename: './index.html', - favicon: './public/favicon.ico', - publicPath: process.env.PUBLIC_URL || '/', - inject: true, - }), - new MiniCssExtractPlugin({ - filename: '[name].css', - }), - ], - resolve: { - extensions: ['.js', '.jsx', '.ts', '.tsx'], - alias: { - '@atoms': path.resolve(__dirname, 'src/components/atoms'), - '@molecules': path.resolve(__dirname, 'src/components/molecules'), - '@organisms': path.resolve(__dirname, 'src/components/organisms'), - '@templates': path.resolve(__dirname, 'src/components/templates'), - '@pages': path.resolve(__dirname, 'src/components/pages'), - '@src': path.resolve(__dirname, 'src'), - antd: path.resolve(__dirname, 'node_modules/antd'), - }, - modules: [path.resolve(__dirname, 'src'), 'node_modules'], - }, - output: { - filename: 'app.js', - path: path.resolve(__dirname, 'build', 'js'), - publicPath: process.env.PUBLIC_URL || '/', - }, - devServer: { - historyApiFallback: true, - static: { - directory: path.join(__dirname, 'public'), - }, - compress: true, - port: 3000, - hot: true, - open: true, - }, -}; diff --git a/src/config/vite.config.js b/src/config/vite.config.js new file mode 100644 index 0000000..75bb446 --- /dev/null +++ b/src/config/vite.config.js @@ -0,0 +1 @@ +// Placeholder for vite.config.js diff --git a/src/config/webpack.config.js b/src/config/webpack.config.js deleted file mode 100644 index ceb4b72..0000000 --- a/src/config/webpack.config.js +++ /dev/null @@ -1 +0,0 @@ -// Placeholder for webpack.config.js \ No newline at end of file diff --git a/src/setup/deps.js b/src/setup/deps.js index b0e65e3..a5fddc9 100644 --- a/src/setup/deps.js +++ b/src/setup/deps.js @@ -1,27 +1,15 @@ const deps = [ 'react', 'react-dom', - '@babel/core', - '@babel/preset-env', - 'webpack-cli', - 'webpack', 'web-vitals', 'typescript', - 'style-loader', - 'react-scripts', - 'react-dom', - 'react', - 'jest', - 'babel-loader', - 'ajv', '@types/react-dom', '@types/react', '@types/node', '@types/jest', '@testing-library/user-event', '@testing-library/react', - '@testing-library/jest-dom', - '@babel/preset-react', + '@testing-library/jest-dom' ]; module.exports = { deps }; diff --git a/src/setup/devDeps.js b/src/setup/devDeps.js index 727a932..72d8caa 100644 --- a/src/setup/devDeps.js +++ b/src/setup/devDeps.js @@ -1,16 +1,14 @@ const devDeps = [ 'pretty-quick', - 'webpack-dev-server', - 'url-loader', + 'vite', + '@vitejs/plugin-react', 'husky', - 'dotenv-webpack', 'dotenv', - '@svgr/webpack', '@commitlint/config-conventional', '@commitlint/cli', 'prettier', 'ora', - '@babel/plugin-proposal-private-property-in-object', + '@babel/plugin-proposal-private-property-in-object' ]; module.exports = { devDeps }; diff --git a/src/setup/init.js b/src/setup/init.js index c925da8..492d74c 100644 --- a/src/setup/init.js +++ b/src/setup/init.js @@ -24,15 +24,15 @@ async function initProject(projectDirectory, userInput, options) { console.log(`πŸš€ Creating a new React app in ${root}...`); - const spinner = ora('Installing base Create React App...').start(); + const spinner = ora('Installing base Vite React App...').start(); try { - // Initialize CRA with or without TypeScript - const template = userInput.language === 'TypeScript' ? '--template typescript' : ''; - execSync(`npx create-react-app . ${template} ${verboseFlag}`, { stdio: 'inherit' }); - spinner.succeed('βœ… Base React app created successfully.'); + // Initialize Vite with or without TypeScript + const template = userInput.language === 'TypeScript' ? '--template react-ts' : '--template react'; + execSync(`npm create vite@latest . ${template} ${verboseFlag}`, { stdio: 'inherit' }); + spinner.succeed('βœ… Base Vite app created successfully.'); } catch (error) { - spinner.fail('❌ Failed to create base React app.'); + spinner.fail('❌ Failed to create base Vite app.'); console.error(error); process.exit(1); } diff --git a/src/templates/packageJson.js b/src/templates/packageJson.js index 467e26c..c899b9d 100644 --- a/src/templates/packageJson.js +++ b/src/templates/packageJson.js @@ -1,4 +1,8 @@ // Placeholder for packageJson.js +const fs = require('fs'); +const path = require('path'); +const ora = require('ora'); + function updatePackageJson() { const spinner = ora( 'πŸ“ Updating package.json with custom scripts...' @@ -8,15 +12,14 @@ function updatePackageJson() { const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); packageJson.scripts = { - start: 'webpack serve --config webpack.config.js --mode development', - build: 'webpack --config webpack.config.js --mode production', + dev: 'vite', + build: 'vite build', + preview: 'vite preview', test: 'echo "Error: no test specified" && exit 0', - 'test:dev': 'react-scripts test', 'pretty-quick': 'pretty-quick', 'lint:prettier': 'node check-format.js', prettier: 'prettier --write . --config .prettierrc', 'prettier:commit': 'node prettier-commit.js', - eject: 'react-scripts eject', prepare: 'husky install', }; diff --git a/structure.js b/structure.js index 097b77a..3271a87 100644 --- a/structure.js +++ b/structure.js @@ -27,7 +27,7 @@ const projectStructure = { 'styles.js', 'testing.js', ], - './src/config': ['webpack.config.js', 'babel.config.js'], + './src/config': ['vite.config.js', 'babel.config.js'], './src/templates': [ 'atomicStructure.js', 'packageJson.js',