6.3 KiB
Permanent Webpack Caching Fix for Nodegx
Overview
This document provides the complete fix for the webpack caching issues that require constant npm run clean:all during development.
File 1: packages/noodl-editor/webpackconfigs/shared/webpack.renderer.core.js
Change: Disable Babel cache in development
module.exports = {
target: 'electron-renderer',
module: {
rules: [
{
test: /\.(jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
babelrc: false,
// FIXED: Disable cache in development to ensure fresh code loads
cacheDirectory: false,
presets: ['@babel/preset-react']
}
}
},
// ... rest of rules unchanged
]
},
// ... rest unchanged
};
File 2: packages/noodl-editor/webpackconfigs/webpack.renderer.dev.js
Change: Add explicit cache: false for development mode
const webpack = require('webpack');
const child_process = require('child_process');
const merge = require('webpack-merge').default;
const shared = require('./shared/webpack.renderer.shared.js');
const getExternalModules = require('./helpers/get-externals-modules');
let electronStarted = false;
module.exports = merge(shared, {
mode: 'development',
devtool: 'eval-cheap-module-source-map',
// CRITICAL FIX: Disable ALL webpack caching in development
cache: false,
externals: getExternalModules({
production: false
}),
output: {
publicPath: `http://localhost:8080/`
},
// Add infrastructure logging to help debug cache issues
infrastructureLogging: {
level: 'warn',
},
devServer: {
client: {
logging: 'info',
overlay: {
errors: true,
warnings: false,
runtimeErrors: false
}
},
hot: true,
host: 'localhost',
port: 8080,
// ADDED: Disable server-side caching
headers: {
'Cache-Control': 'no-store',
},
onListening(devServer) {
devServer.compiler.hooks.done.tap('StartElectron', (stats) => {
if (electronStarted) return;
if (stats.hasErrors()) {
console.error('Webpack compilation has errors - not starting Electron');
return;
}
electronStarted = true;
console.log('\n✓ Webpack compilation complete - launching Electron...\n');
// ADDED: Build timestamp canary for cache verification
console.log(`🔥 BUILD TIMESTAMP: ${new Date().toISOString()}`);
child_process
.spawn('npm', ['run', 'start:_dev'], {
shell: true,
env: process.env,
stdio: 'inherit'
})
.on('close', (code) => {
devServer.stop();
})
.on('error', (spawnError) => {
console.error(spawnError);
devServer.stop();
});
});
}
}
});
File 3: packages/noodl-editor/webpackconfigs/webpack.renderer.prod.js (if exists)
Keep filesystem caching for production (CI/CD speed benefits):
module.exports = merge(shared, {
mode: 'production',
// Filesystem cache is FINE for production builds
cache: {
type: 'filesystem',
buildDependencies: {
config: [__filename],
},
},
// ... rest of config
});
File 4: packages/noodl-viewer-react/webpack-configs/webpack.common.js
Also disable caching here (the viewer runtime):
module.exports = {
externals: {
react: 'React',
'react-dom': 'ReactDOM'
},
resolve: {
extensions: ['.tsx', '.ts', '.jsx', '.js'],
fallback: {
events: require.resolve('events/'),
}
},
module: {
rules: [
{
test: /\.(jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
babelrc: false,
// FIXED: Disable cache
cacheDirectory: false,
presets: ['@babel/preset-react']
}
}
},
// ... rest unchanged
]
}
};
File 5: New NPM Scripts in package.json
Add these helpful scripts:
{
"scripts": {
"dev": "npm run dev:editor",
"dev:fresh": "npm run clean:cache && npm run dev",
"clean:cache": "rimraf node_modules/.cache packages/*/node_modules/.cache",
"clean:electron": "rimraf ~/Library/Application\\ Support/Electron ~/Library/Application\\ Support/OpenNoodl",
"clean:all": "npm run clean:cache && npm run clean:electron && rimraf packages/noodl-editor/dist",
"dev:nuke": "npm run clean:all && npm run dev"
}
}
File 6: Build Canary (Optional but Recommended)
Add to your entry point (e.g., packages/noodl-editor/src/editor/src/index.ts):
// BUILD CANARY - Verifies fresh code is running
if (process.env.NODE_ENV === 'development') {
console.log(`🔥 BUILD LOADED: ${new Date().toISOString()}`);
}
This lets you instantly verify whether your changes loaded by checking the console timestamp.
Why This Works
Before (Multiple Stale Cache Sources):
Source Code → Babel Cache (stale) → Webpack Cache (stale) → Bundle → Electron Cache (stale) → Browser
After (No Persistent Caching in Dev):
Source Code → Fresh Babel → Fresh Webpack → Bundle → Electron → Browser (no-store headers)
Trade-offs
| Aspect | Before | After |
|---|---|---|
| Initial build | Faster (cached) | Slightly slower |
| Rebuild speed | Same | Same (HMR unaffected) |
| Code freshness | Unreliable | Always fresh |
| Developer sanity | 😤 | 😊 |
The rebuild speed via Hot Module Replacement (HMR) is unaffected because HMR works at runtime, not via filesystem caching.
Verification Checklist
After implementing, verify:
- Add
console.log('TEST 1')to any file - Save the file
- Check that
TEST 1appears in console (without restart) - Change to
console.log('TEST 2') - Save again
- Verify
TEST 2appears (TEST 1 gone)
If this works, you're golden. No more clean:all needed for normal development!
When You Still Might Need clean:all
- After switching git branches with major changes
- After npm install/update
- If you modify webpack config itself
- If something feels "really weird"
But for normal code edits? Never again.