WordPress主题开发:Webpack实现修改文件自动FTP上传方案咨询
Hey there! I get it—switching from Prepros to Webpack gives you way more control over your WordPress theme build process, but losing that seamless save-and-upload feature stings. Let's break down the most flexible, customizable ways to replicate (and even improve) that functionality.
方案1:扩展webpack-ftp-upload-plugin的自定义能力
You mentioned this plugin feels limited, but we can supercharge it with Webpack's built-in tools to get the granular control you need:
精准筛选上传文件
Use theglobpackage to define exactly which file extensions or paths you want to upload. This lets you target WordPress-specific files like.phptemplates, compiled.css/.js, and media assets while ignoring build artifacts or node modules:const WebpackFtpUpload = require('webpack-ftp-upload-plugin'); const glob = require('glob'); module.exports = { // ... other Webpack config plugins: [ new WebpackFtpUpload({ host: 'your-server-host', port: 21, username: 'ftp-username', password: 'ftp-password', remotePath: '/wp-content/themes/your-theme/', // Include only the extensions you care about localPath: glob.sync('./**/*.{php,css,js,png,jpg,svg}'), // Exclude files you don't want to upload exclude: ['./node_modules/**', './dist/*.map'] }) ] };仅上传修改后的文件
Hook into Webpack's watch events to track changed files dynamically, so you don't re-upload everything on every save (just like Prepros did):let modifiedFiles = []; const WebpackFtpUpload = require('webpack-ftp-upload-plugin'); module.exports = { // ... other config plugins: [ { apply: (compiler) => { // Track files changed during watch mode compiler.hooks.watchRun.tap('TrackModifiedFiles', (compiler) => { modifiedFiles = compiler.modifiedFiles || []; }); // Trigger upload only for changed files after build compiler.hooks.afterEmit.tapAsync('UploadModifiedFiles', (compilation, callback) => { if (modifiedFiles.length > 0) { const filteredFiles = modifiedFiles.filter(file => /\.(php|css|js|png|jpg)$/.test(file) ); if (filteredFiles.length > 0) { new WebpackFtpUpload({ // ... FTP config localPath: filteredFiles }).apply(compiler); } } callback(); }); } } ], watch: true };
方案2:完全自定义上传脚本(最灵活)
If you want full control over every detail of the upload process (like using secure SFTP instead of plain FTP), skip pre-built plugins and use a low-level library like ssh2-sftp-client to build your own Webpack plugin.
Install dependencies
npm install ssh2-sftp-client --save-devBuild your custom plugin
Add this to your Webpack config (or a separate file you require):const Client = require('ssh2-sftp-client'); class CustomFtpUploadPlugin { constructor(options) { this.options = options; this.sftp = new Client(); } apply(compiler) { compiler.hooks.afterEmit.tapAsync('CustomFtpUpload', async (compilation, callback) => { // Filter files to only include your target extensions const changedFiles = Object.keys(compilation.fileDependencies).filter(file => this.options.includeExtensions.some(ext => file.endsWith(ext)) ); if (changedFiles.length === 0) { callback(); return; } try { // Connect to SFTP server await this.sftp.connect({ host: this.options.host, port: this.options.port || 22, username: this.options.username, password: this.options.password }); // Upload each changed file for (const file of changedFiles) { const remotePath = `${this.options.remoteThemePath}/${file.replace('./', '')}`; await this.sftp.put(file, remotePath); console.log(`✅ Uploaded: ${file} → ${remotePath}`); } await this.sftp.end(); } catch (err) { console.error('❌ FTP Upload Error:', err); } callback(); }); } } // Use the plugin in your config module.exports = { // ... other Webpack settings plugins: [ new CustomFtpUploadPlugin({ host: 'your-server-host', username: 'sftp-username', password: 'sftp-password', remoteThemePath: '/wp-content/themes/your-theme', // Define exactly which extensions to upload includeExtensions: ['.php', '.css', '.js', '.png', '.jpg', '.svg'] }) ], watch: true };This setup lets you:
- Use SFTP (more secure than plain FTP)
- Fully customize included/excluded file types
- Track upload status with clear logging
- Handle errors gracefully
方案3:并行文件监听(独立脚本)
If you want to upload raw files (like uncompiled .php templates) without tying them to Webpack's build process, use chokidar to watch files independently and trigger uploads in real-time.
Install dependencies
npm install chokidar ssh2-sftp-client --save-devCreate a watch script (e.g.
ftp-watch.js)const chokidar = require('chokidar'); const Client = require('ssh2-sftp-client'); const sftp = new Client(); const config = { host: 'your-server-host', username: 'sftp-username', password: 'sftp-password', remoteThemePath: '/wp-content/themes/your-theme', watchPaths: ['./**/*.{php,css,js,png,jpg}'], ignorePaths: ['./node_modules/**', './dist/*.map'] }; // Connect to server once sftp.connect(config).then(() => { console.log('🔌 Connected to server, watching for file changes...'); }); // Watch for file changes const watcher = chokidar.watch(config.watchPaths, { ignored: config.ignorePaths, persistent: true }); // Upload on file change or addition watcher.on(['change', 'add'], async (file) => { try { const remotePath = `${config.remoteThemePath}/${file.replace('./', '')}`; await sftp.put(file, remotePath); console.log(`✅ Uploaded: ${file}`); } catch (err) { console.error('❌ Upload failed for', file, ':', err); } });Run alongside Webpack
Add a script to yourpackage.json:"scripts": { "dev": "webpack --watch & node ftp-watch.js" }Now when you run
npm run dev, Webpack builds your assets while the watch script uploads any changed files in real-time.
Final Recommendation
For most WordPress theme developers, 方案2 (Custom Webpack Plugin) is the sweet spot—it integrates seamlessly with your existing workflow, supports secure SFTP, and gives you full control over every aspect of the upload process. If you need to upload non-compiled files independently, pair it with 方案3 (Parallel Watch Script) for maximum flexibility.
内容的提问来源于stack exchange,提问作者JJ Gerrish




