216 lines
6.6 KiB
Python
216 lines
6.6 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Frontend Optimization Script for MYP Platform
|
|
Optimizes JavaScript and CSS files for better performance
|
|
"""
|
|
|
|
import os
|
|
import gzip
|
|
import shutil
|
|
import hashlib
|
|
from pathlib import Path
|
|
|
|
def minify_file(content, file_type='js'):
|
|
"""Basic minification - removes comments and extra whitespace"""
|
|
if file_type == 'js':
|
|
# Remove single-line comments
|
|
lines = content.split('\n')
|
|
cleaned_lines = []
|
|
for line in lines:
|
|
# Skip lines that are only comments
|
|
stripped = line.strip()
|
|
if stripped.startswith('//'):
|
|
continue
|
|
# Remove inline comments
|
|
if '//' in line:
|
|
line = line.split('//')[0].rstrip()
|
|
cleaned_lines.append(line)
|
|
content = '\n'.join(cleaned_lines)
|
|
|
|
# Remove multi-line comments
|
|
import re
|
|
content = re.sub(r'/\*[\s\S]*?\*/', '', content)
|
|
|
|
# Remove extra whitespace
|
|
content = re.sub(r'\s+', ' ', content)
|
|
content = re.sub(r'\s*([{}();,:])\s*', r'\1', content)
|
|
|
|
elif file_type == 'css':
|
|
# Remove CSS comments
|
|
import re
|
|
content = re.sub(r'/\*[\s\S]*?\*/', '', content)
|
|
|
|
# Remove extra whitespace
|
|
content = re.sub(r'\s+', ' ', content)
|
|
content = re.sub(r'\s*([{}:;,])\s*', r'\1', content)
|
|
|
|
return content.strip()
|
|
|
|
def compress_file(file_path, force=False):
|
|
"""Compress file with gzip"""
|
|
gz_path = file_path + '.gz'
|
|
|
|
# Skip if already compressed and not forcing
|
|
if os.path.exists(gz_path) and not force:
|
|
return False
|
|
|
|
with open(file_path, 'rb') as f_in:
|
|
with gzip.open(gz_path, 'wb', compresslevel=9) as f_out:
|
|
shutil.copyfileobj(f_in, f_out)
|
|
|
|
return True
|
|
|
|
def optimize_js_files(js_dir):
|
|
"""Optimize JavaScript files"""
|
|
js_path = Path(js_dir)
|
|
optimized_count = 0
|
|
|
|
for js_file in js_path.glob('*.js'):
|
|
# Skip already minified files
|
|
if js_file.name.endswith('.min.js'):
|
|
continue
|
|
|
|
min_file = js_file.with_suffix('.min.js')
|
|
|
|
# Skip if minified version already exists
|
|
if min_file.exists():
|
|
continue
|
|
|
|
print(f"Optimizing {js_file.name}...")
|
|
|
|
# Read and minify
|
|
content = js_file.read_text(encoding='utf-8')
|
|
minified = minify_file(content, 'js')
|
|
|
|
# Write minified version
|
|
min_file.write_text(minified, encoding='utf-8')
|
|
|
|
# Compress both versions
|
|
compress_file(str(js_file))
|
|
compress_file(str(min_file))
|
|
|
|
optimized_count += 1
|
|
|
|
return optimized_count
|
|
|
|
def optimize_css_files(css_dir):
|
|
"""Optimize CSS files"""
|
|
css_path = Path(css_dir)
|
|
optimized_count = 0
|
|
|
|
for css_file in css_path.glob('*.css'):
|
|
# Skip already minified files
|
|
if css_file.name.endswith('.min.css'):
|
|
continue
|
|
|
|
min_file = css_file.with_suffix('.min.css')
|
|
|
|
# Skip if minified version already exists
|
|
if min_file.exists():
|
|
continue
|
|
|
|
print(f"Optimizing {css_file.name}...")
|
|
|
|
# Read and minify
|
|
content = css_file.read_text(encoding='utf-8')
|
|
minified = minify_file(content, 'css')
|
|
|
|
# Write minified version
|
|
min_file.write_text(minified, encoding='utf-8')
|
|
|
|
# Compress both versions
|
|
compress_file(str(css_file))
|
|
compress_file(str(min_file))
|
|
|
|
optimized_count += 1
|
|
|
|
return optimized_count
|
|
|
|
def create_bundle_js(js_dir):
|
|
"""Create bundled JavaScript file with core utilities"""
|
|
js_path = Path(js_dir)
|
|
|
|
# Core files to bundle in order
|
|
core_files = [
|
|
'core-utilities.js',
|
|
'dark-mode.js',
|
|
'user-dropdown.js'
|
|
]
|
|
|
|
bundle_content = []
|
|
|
|
for file_name in core_files:
|
|
file_path = js_path / file_name
|
|
if file_path.exists():
|
|
content = file_path.read_text(encoding='utf-8')
|
|
bundle_content.append(f"/* === {file_name} === */\n{content}\n")
|
|
|
|
if bundle_content:
|
|
bundle_path = js_path / 'core-bundle.min.js'
|
|
bundled = '\n'.join(bundle_content)
|
|
minified = minify_file(bundled, 'js')
|
|
bundle_path.write_text(minified, encoding='utf-8')
|
|
compress_file(str(bundle_path))
|
|
print(f"Created core bundle: {bundle_path.name}")
|
|
|
|
def main():
|
|
"""Main optimization function"""
|
|
base_dir = Path(__file__).parent.parent
|
|
static_dir = base_dir / 'static'
|
|
js_dir = static_dir / 'js'
|
|
css_dir = static_dir / 'css'
|
|
|
|
print("Starting frontend optimization...")
|
|
|
|
# Optimize JavaScript
|
|
js_count = optimize_js_files(js_dir)
|
|
print(f"Optimized {js_count} JavaScript files")
|
|
|
|
# Optimize CSS
|
|
css_count = optimize_css_files(css_dir)
|
|
print(f"Optimized {css_count} CSS files")
|
|
|
|
# Create JavaScript bundle
|
|
create_bundle_js(js_dir)
|
|
|
|
# Compress performance-optimized.css if not already done
|
|
perf_css = css_dir / 'performance-optimized.css'
|
|
if perf_css.exists():
|
|
compress_file(str(perf_css), force=True)
|
|
# Create minified version
|
|
min_perf_css = css_dir / 'performance-optimized.min.css'
|
|
if not min_perf_css.exists():
|
|
content = perf_css.read_text(encoding='utf-8')
|
|
minified = minify_file(content, 'css')
|
|
min_perf_css.write_text(minified, encoding='utf-8')
|
|
compress_file(str(min_perf_css))
|
|
|
|
# Compress core-utilities files
|
|
core_js = js_dir / 'core-utilities.js'
|
|
core_css = css_dir / 'core-utilities.css'
|
|
|
|
if core_js.exists():
|
|
compress_file(str(core_js), force=True)
|
|
# Create minified version
|
|
min_core_js = js_dir / 'core-utilities.min.js'
|
|
if not min_core_js.exists():
|
|
content = core_js.read_text(encoding='utf-8')
|
|
minified = minify_file(content, 'js')
|
|
min_core_js.write_text(minified, encoding='utf-8')
|
|
compress_file(str(min_core_js))
|
|
|
|
if core_css.exists():
|
|
compress_file(str(core_css), force=True)
|
|
# Create minified version
|
|
min_core_css = css_dir / 'core-utilities.min.css'
|
|
if not min_core_css.exists():
|
|
content = core_css.read_text(encoding='utf-8')
|
|
minified = minify_file(content, 'css')
|
|
min_core_css.write_text(minified, encoding='utf-8')
|
|
compress_file(str(min_core_css))
|
|
|
|
print("\nOptimization complete!")
|
|
print("Remember to update templates to use minified versions in production.")
|
|
|
|
if __name__ == "__main__":
|
|
main() |