メインコンテンツへスキップ

HTML, CSS, JavaScriptを圧縮 (minify) するPythonスクリプト

·1495 文字·3 分
目次

はじめに
#

HTML, CSS, JavaScriptを圧縮 (minify) して、ファイル容量を削減するPythonスクリプトを作成しました。

小規模なウェブサイトなどを対象として、ローカルで複数のファイルをまとめてminifyする場面を想定しています。 ローカルでminifyできるツールは多数公開されていますが、圧縮アルゴリズムをブラックボックス化したくなかったためPythonで自作しました。

実行環境はPython 3.9.7です。

圧縮するPythonスクリプト
#

圧縮するPythonスクリプトは以下の通りです。 minifyという名前の関数にしています。

import re

def minify(src_path, dest_path):
    """HTML/CSS/JavaScriptを圧縮する

    Args:
        src_path (str): 圧縮したいファイルのパス
        dest_path (str): 圧縮後に保存するパス
    """
    extention = src_path.split(".")[-1] # 拡張子

    with open(src_path, encoding="utf_8") as f:
        s0 = f.readlines()

    if extention=="html":
        s1 = "".join([s.strip() for s in s0]) # 各行の前後の空白を削除
        s9 = re.sub('<!--.*?-->', '', s1) # コメントの削除
    elif extention=="css":
        s1 = "".join([s.strip() for s in s0]) # 各行の前後の空白を削除
        s2 = re.sub('/\*.*?\*/', '', s1) # コメントの削除
        s3 = re.sub(': +?', ':', s2) # セミコロン後の空白を削除
        s9 = re.sub(' +?{', '{', s3) # '{'前の空白を削除
    elif extention=="js":
        s1 = [s.split("//")[0] for s in s0] # 1行コメント(//以降)を削除
        s2 = "".join([s.strip() for s in s1]) # 各行の前後の空白を削除
        s9 = re.sub('/\*.*?\*/', '', s2) # コメント(/* */)の削除

    with open(dest_path, mode='w', encoding="utf_8") as f:
        f.write(s9)

主な注意点は以下の通りです。

  • JavaScriptは各行の末尾に;を付けている必要がある
  • CSSではショートハンドへの変換は行わない

使用例
#

Pythonスクリプトの実行結果の例を示します。

HTML
#

以下の断片的なHTMLファイルsrc/index.htmlを圧縮し、dest/index.htmlというパスに保存します。

圧縮前

<!--コメント-->
<body>
    <h1>見出し</h1>
    <img src="img/sample.jpg">
</body>

minify関数を以下のように実行します。

minify("src/index.html", "dest/index.html")

圧縮後

インデントやコメント、改行は削除されます。

<body><h1>見出し</h1><img src="img/sample.jpg"></body>

CSS
#

以下のCSSファイルsrc/style.cssを圧縮し、dest/style.cssというパスに保存します。

圧縮前

.main {
    /* 余白の追加 */
    padding: 10px;
}

minify関数を以下のように実行します。

minify("src/style.css", "dest/style.css")

圧縮後

コメントや改行、余分なスペースは削除されます。

.main{padding:10px;}

JavaScript
#

以下のJavaScriptファイルsrc/script.jsを圧縮し、dest/script.jsというパスに保存します。

圧縮前

console.log("Hello World."); // コメント
/*
    コメント
*/
let val = 1;

minify関数を以下のように実行します。

minify("src/script.js", "dest/script.js")

圧縮後

コメントや改行は削除されます。

console.log("Hello World.");let val = 1;

フォルダ単位でまとめてminifyする
#

フォルダ内にあるHTML, CSS, JavaScriptをまとめてminifyすることを考えます。 srcフォルダに圧縮前のファイルがあり、ディレクトリの構造を保ったまま圧縮してdestフォルダに保存するものとします(一般的にはsrcフォルダが開発用、destフォルダが公開用になると思います)。

このときのPythonスクリプトを以下に示します。

import os
import shutil

src = "src"
dest = "dest"

for current_dir, sub_dirs, files_list in os.walk(src):
    for subdir in sub_dirs:
        os.makedirs(dest+"/"+subdir, exist_ok=True)

    for file in files_list:
        extention = file.split(".")[-1] # 拡張子
        file_path = current_dir+"/"+file
        if extention in ["html", "css", "js"]:
            minify(file_path, file_path.replace(src, dest, 1))
        else:
            shutil.copy2(file_path, file_path.replace(src, dest, 1))

os.walk()はフォルダ内のファイル名を再帰的に取得する関数です。

また、ファイルの拡張子を取得して、HTML, CSS, JavaScriptのみminifyします。 それ以外のファイル(画像など)はminifyせずに、shutil.copy2()関数でコピーします。

まとめ
#

HTML, CSS, JavaScriptを圧縮 (minify) して、ファイル容量を削減するPythonスクリプトを作成しました。

Helve
著者
Helve
関西在住、電機メーカ勤務のエンジニア。X(旧Twitter)で新着記事を配信中です

関連記事

【Python】定数を持つ関数の実行を高速化する
·1522 文字·4 分
Pythonの関数において毎回決まった値(定数)を必要とする場合、どのように記述すれば処理が速くなるか検証しました。
Condaの仮想環境をYAMLファイルに保存する
·2095 文字·5 分
Condaで構築した仮想環境をYAML形式のファイルに保存し、再構築する方法を解説する。
KerasのステートフルRNNで学習を高速化する
·3032 文字·7 分
KerasのステートフルRNNについて解説する。
「インデックスファンド比較サイト」をリリース
·1353 文字·3 分
「インデックスファンド比較サイト」をリリースしました。サイトの概要と、使用した技術についてまとめています。
scipy.interpolate.interp2dによる2次元データの補間を解説
·1625 文字·4 分
Pythonの数値解析ライブラリSciPyのinterpolate.interp2dクラスを使って、2次元形状のデータを補間する方法を解説する。補間オプションや、実際の補間例も示す。
PythonでJSONを扱う
·1099 文字·3 分
Pythonの標準ライブラリjsonを使って、JSONデータを辞書型データとして扱う方法を解説する。