Efficiently handle external resources in your userscripts:
// Declare resources in the editor's Resources section:
// Name: jquery, URL: https://code.jquery.com/jquery-3.6.0.min.js
// Name: styles, URL: https://example.com/custom.css
// Use resources in your script
const jqueryCode = GM_getResourceText('jquery');
const customCSS = GM_getResourceText('styles');
// Inject jQuery if not already present
if (typeof $ === 'undefined') {
eval(jqueryCode);
}
// Apply custom styles
GM_addStyle(customCSS);
Make secure cross-origin requests with GM_xmlhttpRequest:
// Advanced request with timeout and retry logic
function makeRequest(url, retries = 3) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'GET',
url: url,
timeout: 10000,
headers: {
'User-Agent': 'CodeTweak UserScript',
'Accept': 'application/json'
},
onload: (response) => {
if (response.status === 200) {
resolve(JSON.parse(response.responseText));
} else if (retries > 0) {
setTimeout(() => {
makeRequest(url, retries - 1)
.then(resolve)
.catch(reject);
}, 1000);
} else {
reject(new Error(`HTTP ${response.status}`));
}
},
onerror: () => {
if (retries > 0) {
setTimeout(() => {
makeRequest(url, retries - 1)
.then(resolve)
.catch(reject);
}, 1000);
} else {
reject(new Error('Network error'));
}
}
});
});
}
Enable comprehensive debugging for development:
// Add debug logging to your scripts
const DEBUG = GM_getValue('debug_mode', false);
function debugLog(...args) {
if (DEBUG) {
console.log('[UserScript Debug]', ...args);
}
}
// Use throughout your script
debugLog('Script initialized');
debugLog('Processing element:', element);
debugLog('API response:', data);
Implement robust error handling in your userscripts:
// Wrap your main script logic
(function() {
'use strict';
try {
// Your script code here
initializeScript();
} catch (error) {
console.error('UserScript Error:', error);
// Optional: Report errors
GM_setValue('last_error', {
message: error.message,
stack: error.stack,
timestamp: Date.now()
});
// Optional: Show user notification
if (typeof GM_notification !== 'undefined') {
GM_notification({
text: 'Script encountered an error. Check console for details.',
title: 'UserScript Error'
});
}
}
})();
Monitor your script's performance impact:
// Performance monitoring wrapper
function measurePerformance(name, fn) {
const start = performance.now();
const result = fn();
const end = performance.now();
const duration = end - start;
console.log(`${name} took ${duration.toFixed(2)}ms`);
// Store performance data
const perfData = GM_getValue('performance_data', {});
perfData[name] = (perfData[name] || []).concat(duration).slice(-10);
GM_setValue('performance_data', perfData);
return result;
}
// Usage
measurePerformance('DOM Processing', () => {
document.querySelectorAll('.target').forEach(processElement);
});
Always validate data from external sources:
// Validate stored data
function getSafeValue(key, defaultValue, validator) {
const value = GM_getValue(key, defaultValue);
if (typeof validator === 'function' && !validator(value)) {
console.warn(`Invalid stored value for ${key}, using default`);
return defaultValue;
}
return value;
}
// Usage
const userSettings = getSafeValue('settings', {}, (val) => {
return typeof val === 'object' && val !== null;
});
const maxRetries = getSafeValue('max_retries', 3, (val) => {
return typeof val === 'number' && val >= 0 && val <= 10;
});
Best practices for external API communication:
Built-in tools for troubleshooting:
// Check CodeTweak status
console.log('CodeTweak version:', chrome.runtime.getManifest().version);
// List all stored values
console.log('Stored keys:', GM_listValues());
// Check enabled APIs
console.log('Available APIs:', Object.keys(window).filter(k => k.startsWith('GM_')));
// Monitor performance
const observer = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
if (entry.duration > 100) {
console.warn('Slow operation detected:', entry.name, entry.duration + 'ms');
}
});
});
observer.observe({entryTypes: ['measure']});