Skip to main content

Course Progress

Loading...

🔄 Theme Development Workflow

Master professional WordPress theme development processes

Learn efficient workflows, tools, and best practices for theme development

Learning Objectives

  • Understand professional theme development workflow
  • Set up efficient development environment
  • Master build tools and task automation
  • Implement continuous integration
  • Organize project structure effectively
  • Manage dependencies and packages
  • Automate repetitive tasks
  • Streamline deployment process

Professional Theme Development Process

A well-structured workflow is essential for efficient theme development. It ensures consistency, reduces errors, and speeds up the development process.

Key Workflow Components

  • Version Control: Track changes and collaborate
  • Local Development: Safe testing environment
  • Build Process: Compile and optimize assets
  • Testing: Quality assurance
  • Deployment: Push to production
  • Maintenance: Updates and bug fixes

Development Workflow Stages

1 Planning

  • Requirements gathering
  • Design mockups
  • Feature specification
  • Project timeline
  • Technology stack

2 Setup

  • Development environment
  • Version control
  • Build tools
  • Dependency management
  • Project structure

3 Development

  • Code implementation
  • Asset creation
  • Feature development
  • Regular commits
  • Code reviews

4 Testing

  • Unit testing
  • Integration testing
  • Browser testing
  • Performance testing
  • Security testing

5 Deployment

  • Build optimization
  • Staging deployment
  • Final testing
  • Production release
  • Post-deployment check

6 Maintenance

  • Bug fixes
  • Security updates
  • Feature updates
  • Performance optimization
  • Documentation updates

Theme Project Structure

my-theme/
├── src/ # Source files
│   ├── scss/
│   │   ├── style.scss
│   │   ├── _variables.scss
│   │   ├── _mixins.scss
│   │   └── components/
│   ├── js/
│   │   ├── main.js
│   │   ├── navigation.js
│   │   └── modules/
│   └── images/
│       └── *.{jpg,png,svg}
├── dist/ # Compiled/built files
│   ├── css/
│   │   └── style.min.css
│   ├── js/
│   │   └── bundle.min.js
│   └── images/
│       └── *.{jpg,png,svg}
├── inc/ # PHP includes
│   ├── customizer.php
│   ├── template-functions.php
│   └── template-tags.php
├── template-parts/
│   ├── content/
│   ├── header/
│   └── footer/
├── languages/
│   └── *.pot
├── tests/ # Test files
│   ├── unit/
│   └── integration/
├── style.css # Theme header
├── functions.php
├── index.php
├── package.json
├── composer.json
├── webpack.config.js
├── .gitignore
├── .eslintrc.js
├── .stylelintrc
├── phpcs.xml
└── README.md

Build Tools and Automation

Package.json Configuration

{
  "name": "my-wordpress-theme",
  "version": "1.0.0",
  "description": "Custom WordPress Theme",
  "main": "index.js",
  "scripts": {
    "dev": "webpack --mode development --watch",
    "build": "webpack --mode production",
    "sass": "sass src/scss:dist/css --watch",
    "lint:css": "stylelint 'src/scss/**/*.scss'",
    "lint:js": "eslint src/js",
    "format": "prettier --write 'src/**/*.{js,scss}'",
    "test": "jest",
    "bundle": "npm run build && npm run zip",
    "zip": "zip -r theme.zip . -x node_modules/\\* .git/\\* src/\\* tests/\\*"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0",
    "@babel/preset-env": "^7.20.0",
    "@wordpress/scripts": "^24.0.0",
    "autoprefixer": "^10.4.0",
    "babel-loader": "^9.0.0",
    "clean-webpack-plugin": "^4.0.0",
    "css-loader": "^6.7.0",
    "cssnano": "^5.1.0",
    "eslint": "^8.30.0",
    "jest": "^29.0.0",
    "mini-css-extract-plugin": "^2.7.0",
    "postcss": "^8.4.0",
    "postcss-loader": "^7.0.0",
    "prettier": "^2.8.0",
    "sass": "^1.57.0",
    "sass-loader": "^13.2.0",
    "stylelint": "^14.16.0",
    "terser-webpack-plugin": "^5.3.0",
    "webpack": "^5.75.0",
    "webpack-cli": "^5.0.0"
  },
  "browserslist": [
    "> 1%",
    "last 2 versions"
  ]
}

Webpack Configuration

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = (env, argv) => {
    const isProduction = argv.mode === 'production';
    
    return {
        entry: {
            main: './src/js/main.js',
            customizer: './src/js/customizer.js'
        },
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: 'js/[name].min.js'
        },
        module: {
            rules: [
                {
                    test: /\.js$/,
                    exclude: /node_modules/,
                    use: {
                        loader: 'babel-loader',
                        options: {
                            presets: ['@babel/preset-env']
                        }
                    }
                },
                {
                    test: /\.scss$/,
                    use: [
                        MiniCssExtractPlugin.loader,
                        'css-loader',
                        {
                            loader: 'postcss-loader',
                            options: {
                                postcssOptions: {
                                    plugins: [
                                        require('autoprefixer'),
                                        ...(isProduction ? [require('cssnano')] : [])
                                    ]
                                }
                            }
                        },
                        'sass-loader'
                    ]
                },
                {
                    test: /\.(png|jpg|gif|svg)$/,
                    type: 'asset/resource',
                    generator: {
                        filename: 'images/[name][ext]'
                    }
                }
            ]
        },
        plugins: [
            new CleanWebpackPlugin(),
            new MiniCssExtractPlugin({
                filename: 'css/[name].min.css'
            })
        ],
        optimization: {
            minimize: isProduction,
            minimizer: [
                new TerserPlugin({
                    terserOptions: {
                        compress: {
                            drop_console: true
                        }
                    }
                })
            ]
        },
        devtool: isProduction ? false : 'source-map',
        watch: !isProduction,
        watchOptions: {
            ignored: /node_modules/
        }
    };
};

Gulp Alternative Setup

const gulp = require('gulp');
const sass = require('gulp-sass')(require('sass'));
const autoprefixer = require('gulp-autoprefixer');
const cleanCSS = require('gulp-clean-css');
const uglify = require('gulp-uglify');
const concat = require('gulp-concat');
const sourcemaps = require('gulp-sourcemaps');
const imagemin = require('gulp-imagemin');
const browserSync = require('browser-sync').create();

// Compile SCSS
gulp.task('sass', function() {
    return gulp.src('src/scss/**/*.scss')
        .pipe(sourcemaps.init())
        .pipe(sass().on('error', sass.logError))
        .pipe(autoprefixer())
        .pipe(cleanCSS())
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest('dist/css'))
        .pipe(browserSync.stream());
});

// Compile JavaScript
gulp.task('js', function() {
    return gulp.src('src/js/**/*.js')
        .pipe(sourcemaps.init())
        .pipe(concat('main.min.js'))
        .pipe(uglify())
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest('dist/js'))
        .pipe(browserSync.stream());
});

// Optimize Images
gulp.task('images', function() {
    return gulp.src('src/images/**/*')
        .pipe(imagemin([
            imagemin.gifsicle({interlaced: true}),
            imagemin.mozjpeg({quality: 75, progressive: true}),
            imagemin.optipng({optimizationLevel: 5}),
            imagemin.svgo({
                plugins: [{removeViewBox: true}, {cleanupIDs: false}]
            })
        ]))
        .pipe(gulp.dest('dist/images'));
});

// Watch files
gulp.task('watch', function() {
    browserSync.init({
        proxy: 'localhost:8080', // Your local WordPress URL
        notify: false
    });
    
    gulp.watch('src/scss/**/*.scss', gulp.series('sass'));
    gulp.watch('src/js/**/*.js', gulp.series('js'));
    gulp.watch('src/images/**/*', gulp.series('images'));
    gulp.watch('**/*.php').on('change', browserSync.reload);
});

// Default task
gulp.task('default', gulp.series('sass', 'js', 'images', 'watch'));

// Build task
gulp.task('build', gulp.series('sass', 'js', 'images'));

Essential Development Tools

Version Control
  • Git
  • GitHub/GitLab/Bitbucket
  • SourceTree/GitKraken
Code Editors
  • VS Code
  • PHPStorm
  • Sublime Text
Local Development
  • Local by Flywheel
  • Docker
  • XAMPP/MAMP
Build Tools
  • Webpack
  • Gulp
  • Grunt
Package Managers
  • NPM
  • Yarn
  • Composer
Testing Tools
  • PHPUnit
  • Jest
  • Cypress

PHP Dependencies with Composer

composer.json

{
    "name": "yourname/wordpress-theme",
    "description": "Custom WordPress Theme",
    "type": "wordpress-theme",
    "license": "GPL-2.0-or-later",
    "authors": [
        {
            "name": "Your Name",
            "email": "email@example.com"
        }
    ],
    "require": {
        "php": ">=7.4"
    },
    "require-dev": {
        "squizlabs/php_codesniffer": "^3.7",
        "wp-coding-standards/wpcs": "^2.3",
        "dealerdirect/phpcodesniffer-composer-installer": "^0.7",
        "phpunit/phpunit": "^9.5"
    },
    "scripts": {
        "lint": "phpcs",
        "lint:fix": "phpcbf",
        "test": "phpunit"
    },
    "config": {
        "allow-plugins": {
            "dealerdirect/phpcodesniffer-composer-installer": true
        }
    }
}

PHP CodeSniffer Configuration (phpcs.xml)

<?xml version="1.0"?>
<ruleset name="WordPress Theme Coding Standards">
    <description>Custom rules for WordPress theme development</description>
    
    <!-- Files to check -->
    <file>.</file>
    
    <!-- Exclude paths -->
    <exclude-pattern>*/vendor/*</exclude-pattern>
    <exclude-pattern>*/node_modules/*</exclude-pattern>
    <exclude-pattern>*/dist/*</exclude-pattern>
    <exclude-pattern>*/tests/*</exclude-pattern>
    
    <!-- Use WordPress coding standards -->
    <rule ref="WordPress">
        <!-- Exclude some rules -->
        <exclude name="WordPress.Files.FileName.InvalidClassFileName"/>
    </rule>
    
    <!-- Set minimum supported WP version -->
    <config name="minimum_supported_wp_version" value="5.9"/>
    
    <!-- Check for PHP cross-version compatibility -->
    <config name="testVersion" value="7.4-"/>
    <rule ref="PHPCompatibilityWP"/>
</ruleset>

Continuous Integration Setup

GitHub Actions Workflow (.github/workflows/ci.yml)

name: CI

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        php-version: ['7.4', '8.0', '8.1']
        
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup PHP
      uses: shivammathur/setup-php@v2
      with:
        php-version: ${{ matrix.php-version }}
        tools: composer, cs2pr
        
    - name: Install Composer dependencies
      run: composer install --prefer-dist --no-progress
      
    - name: Run PHP CodeSniffer
      run: composer lint
      
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'npm'
        
    - name: Install NPM dependencies
      run: npm ci
      
    - name: Run ESLint
      run: npm run lint:js
      
    - name: Run StyleLint
      run: npm run lint:css
      
    - name: Build assets
      run: npm run build
      
    - name: Run tests
      run: |
        composer test
        npm test
        
    - name: Upload artifacts
      uses: actions/upload-artifact@v3
      with:
        name: theme-build
        path: |
          dist/
          *.php
          style.css
          screenshot.png

Development Workflow Checklist

  • Set up local development environment
  • Initialize Git repository
  • Create project structure
  • Set up build tools (Webpack/Gulp)
  • Configure linting tools
  • Install dependencies (NPM/Composer)
  • Set up testing framework
  • Configure CI/CD pipeline
  • Create development branch
  • Implement feature branches
  • Write tests for features
  • Run linting and formatting
  • Build and optimize assets
  • Test in multiple browsers
  • Create pull requests
  • Conduct code reviews
  • Merge to main branch
  • Tag releases
  • Deploy to staging
  • Deploy to production

Best Practices

Workflow Best Practices

  • Automate everything: Reduce manual tasks
  • Version control always: Commit early and often
  • Use branching strategy: Git Flow or GitHub Flow
  • Write meaningful commits: Clear commit messages
  • Test before deploying: Never deploy untested code
  • Document your process: Keep README updated
  • Use environment variables: Separate config from code
  • Regular backups: Before major changes
  • Monitor performance: Track build times
  • Keep dependencies updated: Regular updates
Never commit sensitive information like API keys, passwords, or database credentials to version control. Use environment variables or config files that are gitignored.
Create npm scripts for common tasks to standardize your workflow across team members and make onboarding new developers easier.

Practice Exercise

💻
Set Up Professional Workflow

Create a complete development workflow for your theme:

  1. Initialize Git repository
  2. Create project structure
  3. Set up package.json with scripts
  4. Configure Webpack or Gulp
  5. Set up Sass compilation
  6. Configure JavaScript bundling
  7. Add linting tools
  8. Create composer.json
  9. Set up GitHub Actions
  10. Document workflow in README

Additional Resources