🔄 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