HTML 코드 최소화(minify)용으로 wyrihaximus/html-compress 패키지를 사용하고 있었는데 PHP 8.3에서 TypeError가 발생했다. 이미 작년 12월에 버그 패치 PR이 올라와 있음에도 수개월간 아무런 응답이 없다. (Uncaught TypeError with PHP 8.3 and id attribute)
새로운 버전이 배포될 것이라는 기대를 버리고 다른 패키지들을 찾아봤지만 마땅한 것을 찾지 못했다. 그래서 직접 구현하기로 했다.
/** * DOM Document minify * * @param \DOMDocument $doc * @return void */ function minifyDOMDocument(\DOMDocument $doc): void { $xpath = new \DOMXPath($doc); { $nodes = $xpath->query('//comment()'); foreach ($nodes as $node) { $node->parentNode->removeChild($node); } } { $nodes = $xpath->query('//text()'); foreach ($nodes as $node) { if ($node->nodeType === XML_CDATA_SECTION_NODE) { $node->nodeValue = preg_replace('/^\s+|\s+$/m', '', $node->nodeValue); } else { $value = preg_replace('/\s+/', ' ', $node->nodeValue); $node->nodeValue = $value; } } } }
주석 노드 지우기, CSS나 JS 코드의 앞뒤 공백 제거, 텍스트 노드의 공백 최소화 정도만 하는 간결한 함수이다.
PHP에서 HTML을 다룰때 보통 DOMDocument를 사용하므로 최소화할 HTML 코드를 문자열 대신에 DOMDocument 객체를 함수의 인자로 받았다.
HTML 코드를 문자열로 받고 함수 내부에서 DOMDocument 객체를 생성해도 되지 않을지가 궁금할텐데 DOMDocument가 HTML을 읽어 들일 때 다음과 같은 다양한 상황이 존재한다.
$doc = new \DOMDocument(); $doc->loadHTML($html, LIBXML_NOERROR | LIBXML_HTML_NODEFDTD | LIBXML_NOBLANKS);
때문에 함수 밖에서 호출자의 입맛대로 만들어진 DOMDocument 객체를 받아서 처리하는 것이 낫다.
HTML 코드를 더 줄이기 위해서 HTML 코드를 출력 시 속성 값에 공백이 없으면 따옴표를 제거하는 등의 처리를 추가 할 수 있지만 코드가 줄어드는 양에 비해서 예상치 못한 버그가 발생할 위험성을 생각하면 딱 이 정도가 최적이라고 생각한다.
PHP 패키지로 만들기에는 코드가 짧기에 필요하다면 각자의 프로젝트에 유틸 클래스의 정적 메소드로 만들어 사용하는 정도로 충분하다.