diff --git a/README.md b/README.md index 09f0c03..947a8c3 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,24 @@ # UserScript Project Template -[![GitHub license](https://img.shields.io/github/license/JosunLP/UserScriptProjectTemplate)](https://github.com/JosunLP/UserScriptProjectTemplate/blob/main/LICENSE) -[![GitHub issues](https://img.shields.io/github/issues/JosunLP/UserScriptProjectTemplate)](https://github.com/JosunLP/UserScriptProjectTemplate/issues) -[![GitHub stars](https://img.shields.io/github/stars/JosunLP/UserScriptProjectTemplate)](https://github.com/JosunLP/UserScriptProjectTemplate/stargazers) +[![GitHub license](https://img.shields.io/github/license/JosunLP/UserScriptProjectTemplate?style=for-the-badge)](https://github.com/JosunLP/UserScriptProjectTemplate/blob/main/LICENSE) +[![GitHub issues](https://img.shields.io/github/issues/JosunLP/UserScriptProjectTemplate?style=for-the-badge)](https://github.com/JosunLP/UserScriptProjectTemplate/issues) +[![GitHub stars](https://img.shields.io/github/stars/JosunLP/UserScriptProjectTemplate?style=for-the-badge)](https://github.com/JosunLP/UserScriptProjectTemplate/stargazers) +[![GitHub forks](https://img.shields.io/github/forks/JosunLP/UserScriptProjectTemplate?style=for-the-badge)](https://github.com/JosunLP/UserScriptProjectTemplate/network) + +[![TypeScript](https://img.shields.io/badge/TypeScript-5.4+-blue?logo=typescript&style=for-the-badge)](https://www.typescriptlang.org/) +[![Vite](https://img.shields.io/badge/Vite-7.0+-646CFF?logo=vite&style=for-the-badge)](https://vitejs.dev/) +[![ESLint](https://img.shields.io/badge/ESLint-8.57+-4B32C3?logo=eslint&style=for-the-badge)](https://eslint.org/) +[![Prettier](https://img.shields.io/badge/Prettier-3.6+-F7B93E?logo=prettier&style=for-the-badge)](https://prettier.io/) +[![Node.js](https://img.shields.io/badge/Node.js-18+-339933?logo=node.js&style=for-the-badge)](https://nodejs.org/) + +[![Tampermonkey](https://img.shields.io/badge/Tampermonkey-Compatible-00485B?logo=tampermonkey&style=for-the-badge)](https://www.tampermonkey.net/) +[![Greasemonkey](https://img.shields.io/badge/Greasemonkey-Compatible-FF6600?logo=firefox&style=for-the-badge)](https://www.greasespot.net/) +[![Violentmonkey](https://img.shields.io/badge/Violentmonkey-Compatible-663399?logo=violentmonkey&style=for-the-badge)](https://violentmonkey.github.io/) +[![Mobile Support](https://img.shields.io/badge/Mobile-Support-00C851?logo=android&style=for-the-badge)](https://github.com/JosunLP/UserScriptProjectTemplate#mobile-browser-support) + +[![Last Commit](https://img.shields.io/github/last-commit/JosunLP/UserScriptProjectTemplate?style=for-the-badge)](https://github.com/JosunLP/UserScriptProjectTemplate/commits) +[![Contributors](https://img.shields.io/github/contributors/JosunLP/UserScriptProjectTemplate?style=for-the-badge)](https://github.com/JosunLP/UserScriptProjectTemplate/graphs/contributors) +[![Repository Size](https://img.shields.io/github/repo-size/JosunLP/UserScriptProjectTemplate?style=for-the-badge)](https://github.com/JosunLP/UserScriptProjectTemplate) ## Description @@ -10,19 +26,19 @@ A modern, production-ready template for building UserScripts using TypeScript an ## Features -โ€ข ๐Ÿš€ **Modern Tech Stack:** TypeScript, Vite, ESLint, Prettier -โ€ข ๐Ÿ›ก๏ธ **Type Safety:** Strict TypeScript configuration with comprehensive UserScript API definitions -โ€ข ๐Ÿ”ง **Development Tools:** ESLint, Prettier, automated build pipeline -โ€ข ๐ŸŽฏ **Environment Support:** Separate development and production configurations -โ€ข ๐Ÿ“ฆ **Modular Architecture:** Component system with reusable utilities -โ€ข ๐Ÿ’พ **Storage Management:** Type-safe wrapper for GM_setValue/GM_getValue -โ€ข ๐Ÿ› ๏ธ **Build System:** Optimized Vite configuration with automatic header generation -โ€ข ๐ŸŽจ **DOM Utilities:** Helper functions for element manipulation and waiting -โ€ข ๐Ÿ”’ **Error Handling:** Comprehensive error boundary system -โ€ข โšก **Event System:** Type-safe event emitter for module communication -โ€ข ๐Ÿ“ฑ **Mobile Support:** Touch-optimized interface with mobile browser detection -โ€ข ๐Ÿค **Touch Gestures:** Built-in touch event handling and gesture recognition -โ€ข ๐Ÿ“ฒ **Responsive Design:** Mobile-first CSS with safe area support for notched devices +- ๐Ÿš€ **Modern Tech Stack:** TypeScript, Vite, ESLint, Prettier +- ๐Ÿ›ก๏ธ **Type Safety:** Strict TypeScript configuration with comprehensive UserScript API definitions +- ๐Ÿ”ง **Development Tools:** ESLint, Prettier, automated build pipeline +- ๐ŸŽฏ **Environment Support:** Separate development and production configurations +- ๐Ÿ“ฆ **Modular Architecture:** Component system with reusable utilities +- ๐Ÿ’พ **Storage Management:** Type-safe wrapper for GM_setValue/GM_getValue +- ๐Ÿ› ๏ธ **Build System:** Optimized Vite configuration with automatic header generation +- ๐ŸŽจ **DOM Utilities:** Helper functions for element manipulation and waiting +- ๐Ÿ”’ **Error Handling:** Comprehensive error boundary system +- โšก **Event System:** Type-safe event emitter for module communication +- ๐Ÿ“ฑ **Mobile Support:** Touch-optimized interface with mobile browser detection +- ๐Ÿค **Touch Gestures:** Built-in touch event handling and gesture recognition +- ๐Ÿ“ฒ **Responsive Design:** Mobile-first CSS with safe area support for notched devices ## Installation @@ -64,9 +80,9 @@ src/ tools/ โ”œโ”€โ”€ userScriptHeader.ts # UserScript header generator -โ””โ”€โ”€ userScriptHeader.js # Compiled header generator assets/ # Icons and static resources +โ””โ”€โ”€ icon.afdesign ``` ### Configuration @@ -110,6 +126,25 @@ npm run clean # Clean dist folder npm run type-check # TypeScript type checking ``` +### Build Optimization + +The template features advanced build optimization for production: + +| Build Type | File Size | Compressed | Features | +| --------------- | --------- | ---------- | -------------------------------------- | +| **Development** | ~115 KB | ~30 KB | Source maps, debug info, readable code | +| **Production** | ~25 KB | ~6 KB | Minified, tree-shaken, optimized | + +**Production optimizations include:** + +- โšก **Terser minification** with aggressive compression settings +- ๐ŸŒณ **Tree-shaking** to remove unused code +- ๐ŸŽฏ **Dead code elimination** for **DEV** blocks +- ๐Ÿ“ฆ **Module inlining** for single-file output +- ๐Ÿ”ง **Property mangling** for smaller variable names +- ๐Ÿš€ **ES2020 target** for modern JavaScript features +- ๐Ÿ’พ **GZIP compression** reducing size by ~75% + ### Development Workflow 1. **Configure your script** in `header.config.json` @@ -240,10 +275,10 @@ console.log('Portrait mode:', MobileUtils.isPortrait()); ## UserScript Compatibility -โ€ข **Tampermonkey:** Full support with all GM\_\* APIs -โ€ข **Greasemonkey:** Compatible with standard UserScript APIs -โ€ข **Violentmonkey:** Full compatibility -โ€ข **Safari:** Works with userscript managers +- **Tampermonkey:** Full support with all GM\_\* APIs +- **Greasemonkey:** Compatible with standard UserScript APIs +- **Violentmonkey:** Full compatibility +- **Safari:** Works with userscript managers ### Mobile Browser Support @@ -261,11 +296,11 @@ console.log('Portrait mode:', MobileUtils.isPortrait()); ### Mobile Features -โ€ข **Touch Gestures:** Tap, swipe, and pinch detection -โ€ข **Responsive Design:** Mobile-first CSS with viewport adaptation -โ€ข **Safe Area Support:** Automatic handling of notched devices -โ€ข **Orientation Detection:** Portrait/landscape change handling -โ€ข **Mobile-Optimized UI:** Touch-friendly buttons and menus +- **Touch Gestures:** Tap, swipe, and pinch detection +- **Responsive Design:** Mobile-first CSS with viewport adaptation +- **Safe Area Support:** Automatic handling of notched devices +- **Orientation Detection:** Portrait/landscape change handling +- **Mobile-Optimized UI:** Touch-friendly buttons and menus ## Contributing @@ -278,12 +313,12 @@ console.log('Portrait mode:', MobileUtils.isPortrait()); ## Development Guidelines -โ€ข Follow TypeScript best practices -โ€ข Use meaningful variable and function names -โ€ข Add proper error handling -โ€ข Write self-documenting code -โ€ข Follow the established project structure -โ€ข Run `npm run validate` before committing +- Follow TypeScript best practices +- Use meaningful variable and function names +- Add proper error handling +- Write self-documenting code +- Follow the established project structure +- Run `npm run validate` before committing ## License @@ -293,23 +328,9 @@ This project is licensed under the [MIT License](https://opensource.org/licenses **_Jonas Pfalzgraf_** -โ€ข Email: [info@josunlp.de](mailto:info@josunlp.de) -โ€ข GitHub: [@JosunLP](https://github.com/JosunLP) - -## Changelog - -### v0.0.1 (Current) - -โ€ข โœจ Modern TypeScript setup with strict type checking -โ€ข ๐Ÿ›ก๏ธ Comprehensive UserScript API definitions -โ€ข ๐ŸŽจ Modular architecture with utilities and components -โ€ข ๐Ÿ”ง ESLint and Prettier configuration -โ€ข ๐Ÿ“ฆ Optimized Vite build system -โ€ข ๐Ÿš€ Environment-based configuration -โ€ข ๐Ÿ’พ Type-safe storage management -โ€ข ๐ŸŽฏ Event-driven module system -โ€ข โšก DOM manipulation utilities -โ€ข ๐Ÿ› ๏ธ Automated header generation +- Email: [info@josunlp.de](mailto:info@josunlp.de) +- GitHub: [@JosunLP](https://github.com/JosunLP) +- Website: [josunlp.de](https://josunlp.de) --- diff --git a/package.json b/package.json index 2cc8412..af697bd 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "dev:header": "npm run build-userScriptHeader", "dev:build": "vite build --mode development && npm run build-userScriptHeader", "build": "vite build && npm run build-userScriptHeader", - "build:prod": "vite build --mode production && npm run build-userScriptHeader", + "build:prod": "npm run clean && vite build --mode production && npm run build-userScriptHeader", "build-tooling": "tsc ./tools/userScriptHeader.ts --resolveJsonModule --esModuleInterop", "build-userScriptHeader": "npm run build-tooling && node ./tools/userScriptHeader.js", "validate": "npm run type-check && npm run lint", diff --git a/src/index.ts b/src/index.ts index 933ce8d..af7f181 100644 --- a/src/index.ts +++ b/src/index.ts @@ -25,6 +25,14 @@ class App extends EventEmitter { constructor() { super(); + + // Development-only debug information + if (__DEV__) { + console.log('๐Ÿ”ง UserScript starting in development mode'); + console.log('๐Ÿ“ฆ Version:', __VERSION__); + console.log('๐Ÿ• Build time:', __BUILD_TIME__); + } + this.initialize(); } diff --git a/src/modules/example.ts b/src/modules/example.ts index e6254d4..bc0ea7a 100644 --- a/src/modules/example.ts +++ b/src/modules/example.ts @@ -22,6 +22,7 @@ interface ExampleModuleEvents { export class ExampleModule extends EventEmitter { private isInitialized = false; private actionCount = 0; + private lastActionTime = 0; constructor() { super(); @@ -36,6 +37,7 @@ export class ExampleModule extends EventEmitter { // Load persistent data this.actionCount = Storage.get('exampleModule.actionCount', 0) || 0; + this.lastActionTime = Storage.get('exampleModule.lastActionTime', 0) || 0; // Wait for required DOM elements (example) await this.waitForPageElements(); @@ -164,9 +166,11 @@ export class ExampleModule extends EventEmitter { public performAction(trigger: string): void { this.actionCount++; const timestamp = Date.now(); + this.lastActionTime = timestamp; - // Store the updated count + // Store the updated count and last action time Storage.set('exampleModule.actionCount', this.actionCount); + Storage.set('exampleModule.lastActionTime', timestamp); // Emit event this.emit('actionPerformed', { action: trigger, timestamp }); @@ -205,7 +209,7 @@ export class ExampleModule extends EventEmitter { const stats = { initialized: this.isInitialized, actionCount: this.actionCount, - lastAction: Storage.get('exampleModule.lastActionTime', 0), + lastAction: this.lastActionTime, }; const message = [ @@ -230,6 +234,7 @@ export class ExampleModule extends EventEmitter { Storage.remove('exampleModule.actionCount'); Storage.remove('exampleModule.lastActionTime'); this.actionCount = 0; + this.lastActionTime = 0; console.log('๐Ÿงน Example module data reset'); this.showNotification('Module data reset!'); } diff --git a/src/types/userscript.d.ts b/src/types/userscript.d.ts index d97c422..f7d4011 100644 --- a/src/types/userscript.d.ts +++ b/src/types/userscript.d.ts @@ -94,6 +94,15 @@ declare global { * UnsafeWindow for accessing page's global scope */ const unsafeWindow: Window & typeof globalThis; + + /** + * Build-time constants injected by Vite + */ + const __DEV__: boolean; + const __VERSION__: string; + const __DEBUG__: boolean; + const __USERSCRIPT__: boolean; + const __BUILD_TIME__: string; } export {}; diff --git a/vite.config.ts b/vite.config.ts index 697ba68..45ea70d 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,7 +1,7 @@ -import { resolve } from "path"; -import { defineConfig } from "vite"; -import tsconfigPaths from "vite-tsconfig-paths"; -import pkgjsn from "./package.json"; +import { resolve } from 'path'; +import { defineConfig } from 'vite'; +import tsconfigPaths from 'vite-tsconfig-paths'; +import pkgjsn from './package.json'; export default defineConfig(({ mode }) => { const isDev = mode === 'development'; @@ -9,18 +9,106 @@ export default defineConfig(({ mode }) => { return { build: { rollupOptions: { - input: resolve(__dirname, "src/index.ts"), + input: resolve(__dirname, 'src/index.ts'), output: { entryFileNames: `${pkgjsn.name}${isDev ? '.dev' : ''}.user.js`, - dir: resolve(__dirname, "dist"), + dir: resolve(__dirname, 'dist'), + // Disable code splitting - everything in one file for UserScript + inlineDynamicImports: true, + manualChunks: undefined, + // Optimize output format + format: 'iife', + // Remove unnecessary comments in production + banner: isDev ? undefined : '', + footer: isDev ? undefined : '', + }, + // Prevent any external dependencies + external: [], + // Tree-shaking optimizations + treeshake: { + moduleSideEffects: false, + propertyReadSideEffects: false, + unknownGlobalSideEffects: false, }, }, - sourcemap: isDev ? "inline" : false, + sourcemap: isDev ? 'inline' : false, minify: isDev ? false : 'terser', + // Enhanced Terser options for maximum compression + terserOptions: isDev + ? undefined + : { + compress: { + drop_console: false, // Keep console for UserScript debugging + drop_debugger: true, + pure_funcs: ['console.debug'], + passes: 2, + unsafe: true, + unsafe_arrows: true, + unsafe_comps: true, + unsafe_math: true, + unsafe_methods: true, + unsafe_proto: true, + unsafe_regexp: true, + unsafe_undefined: true, + hoist_funs: true, + hoist_props: true, + hoist_vars: false, + if_return: true, + join_vars: true, + sequences: true, + side_effects: true, + switches: true, + typeofs: true, + booleans: true, + collapse_vars: true, + comparisons: true, + computed_props: true, + conditionals: true, + dead_code: true, + directives: true, + evaluate: true, + expression: false, + global_defs: {}, + keep_fargs: false, + keep_infinity: false, + loops: true, + negate_iife: true, + properties: true, + reduce_funcs: true, + reduce_vars: true, + toplevel: true, + unused: true, + }, + mangle: { + toplevel: true, + safari10: false, + properties: { + regex: /^_/, + }, + }, + format: { + comments: false, + beautify: false, + }, + ecma: 2020, + toplevel: true, + safari10: false, + ie8: false, + }, + // Ensure all assets are inlined + assetsInlineLimit: Number.MAX_SAFE_INTEGER, + // Disable CSS code splitting + cssCodeSplit: false, + // Target modern browsers for better optimization + target: ['es2020', 'chrome80', 'firefox78', 'safari14'], + // Report compressed file sizes + reportCompressedSize: true, + // Chunk size warnings + chunkSizeWarningLimit: 500, }, plugins: [tsconfigPaths()], resolve: { - extensions: [".tsx", ".ts", ".js"], + extensions: ['.tsx', '.ts', '.js'], alias: { '@': resolve(__dirname, 'src'), }, @@ -28,6 +116,31 @@ export default defineConfig(({ mode }) => { define: { __DEV__: isDev, __VERSION__: JSON.stringify(pkgjsn.version), + // Production optimizations + 'process.env.NODE_ENV': JSON.stringify(isDev ? 'development' : 'production'), + // Remove debug code in production + __DEBUG__: isDev, + // UserScript environment flags + __USERSCRIPT__: true, + __BUILD_TIME__: JSON.stringify(new Date().toISOString()), + }, + // Optimize dependencies + optimizeDeps: { + include: [], + exclude: [], + }, + // Enable esbuild optimizations + esbuild: { + target: 'es2020', + legalComments: 'none', + ...(isDev + ? {} + : { + drop: ['debugger'], + minifyIdentifiers: true, + minifySyntax: true, + minifyWhitespace: true, + }), }, }; });