Skip to content

Commit c158977

Browse files
author
y-yamasaki
committed
Merge branch 'develop'
2 parents c3eba1f + b1ed658 commit c158977

8 files changed

Lines changed: 542 additions & 2 deletions

File tree

assets/data/blogList.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,36 @@
147147
"thumbnail": "data:image/png;base64,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",
148148
"contentPath": "blog/blog_00008.html"
149149
},
150+
{
151+
"id": "blog_00015",
152+
"title": "p5.jsで背景アニメーションを実装してみた",
153+
"date": "2024-06-28T00:00:00.000Z",
154+
"category": "技術メモ",
155+
"description": "静的なポートフォリオサイトに動きを取り入れるため、p5.jsを使って背景アニメーションを実装しました。導入から10パターンの実装まで、初心者の目線で振り返ります。",
156+
"tags": [
157+
"p5js",
158+
"javascript",
159+
"creative-coding",
160+
"animation"
161+
],
162+
"thumbnail": "assets/img/ogp.png",
163+
"contentPath": "blog/blog_00015.html"
164+
},
165+
{
166+
"id": "blog_00014",
167+
"title": "CSSのリファクタリングを手軽にしてみた",
168+
"date": "2024-06-27T00:00:00.000Z",
169+
"category": "開発ログ",
170+
"description": "個人開発のWebサイトで溜まりがちな「使われていないCSS」をNode.jsスクリプトでサクッと検出して整理しました。",
171+
"tags": [
172+
"css",
173+
"refactoring",
174+
"nodejs",
175+
"automation"
176+
],
177+
"thumbnail": "assets/img/ogp.png",
178+
"contentPath": "blog/blog_00014.html"
179+
},
150180
{
151181
"id": "blog_00003",
152182
"title": "Odin でコンテキストエディター作ってみた",

blog/blog_00012.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ <h1 class="post-detail__title">静的サイトにお問い合わせフォーム
7171

7272
<section class="post-detail__body markdown-body">
7373
<p>こんにちは!パン君です。</p>
74-
<p>このポートフォリオサイトは GitHub Pages でホスティングしている静的なWebサイトです。<br>常駐サーバーでトンネル通信をPlayit.ggを利用して行っていますが、数週間前からトンネルの作成が出来ずに困っています...
74+
<p>このポートフォリオサイトは GitHub Pages でホスティングしている静的なWebサイトです。 </p>
75+
<p>そしてお問い合わせを実装するにはメールに送信するための仕組みがいります。
76+
API実装を常駐サーバーでトンネル通信をPlayit.ggを利用して行っていますが、数週間前からトンネルの作成が出来ずに困っています...
7577
(公式には連絡したのですが...)</p>
7678
<p>そこで今回は、<strong>Google Apps Script (GAS)</strong> を簡易的なバックエンドAPIとして利用し、完全無料でメール送信機能を実装しました。</p>
7779
<h2>なぜ GAS (Google Apps Script) なのか</h2>

blog/blog_00014.html

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
<!doctype html>
2+
<html lang="ja">
3+
<head prefix="og: https://ogp.me/ns#">
4+
<meta charset="UTF-8" />
5+
<title>CSSのリファクタリングを手軽にしてみた | PanKUN Blog</title>
6+
<meta name="viewport" content="width=device-width, initial-scale=1" />
7+
<meta name="description" content="個人開発のWebサイトで溜まりがちな「使われていないCSS」をNode.jsスクリプトでサクッと検出して整理しました。" />
8+
9+
<!-- Canonical -->
10+
<link rel="canonical" href="https://breadmotion.github.io/WebSite/blog/blog_00014.html" />
11+
12+
<!-- JSON-LD -->
13+
<script type="application/ld+json">
14+
{
15+
"@context": "https://schema.org",
16+
"@type": "BlogPosting",
17+
"mainEntityOfPage": {
18+
"@type": "WebPage",
19+
"@id": "https://breadmotion.github.io/WebSite/blog/blog_00014.html"
20+
},
21+
"headline": "CSSのリファクタリングを手軽にしてみた",
22+
"description": "個人開発のWebサイトで溜まりがちな「使われていないCSS」をNode.jsスクリプトでサクッと検出して整理しました。",
23+
"image": [
24+
"assets/img/ogp.png"
25+
],
26+
"datePublished": "2024-06-27T00:00:00.000Z",
27+
"dateModified": "2024-06-27T00:00:00.000Z",
28+
"author": {
29+
"@type": "Person",
30+
"name": "PanKUN",
31+
"url": "https://breadmotion.github.io/WebSite"
32+
},
33+
"publisher": {
34+
"@type": "Organization",
35+
"name": "PanKUN",
36+
"logo": {
37+
"@type": "ImageObject",
38+
"url": "https://breadmotion.github.io/WebSite/assets/img/favicon-192.png"
39+
}
40+
}
41+
}
42+
</script>
43+
44+
<meta property="og:title" content="CSSのリファクタリングを手軽にしてみた | PanKUN Blog" />
45+
<meta property="og:description" content="個人開発のWebサイトで溜まりがちな「使われていないCSS」をNode.jsスクリプトでサクッと検出して整理しました。" />
46+
<meta property="og:type" content="article" />
47+
<meta property="og:url" content="https://breadmotion.github.io/WebSite/blog/blog_00014.html" />
48+
<meta property="og:image" content="assets/img/ogp.png" />
49+
<meta property="og:site_name" content="PanKUN" />
50+
<meta property="og:email" content="pankun.dev@gmail.com" />
51+
52+
<meta name="twitter:card" content="summary_large_image" />
53+
<meta name="twitter:title" content="CSSのリファクタリングを手軽にしてみた" />
54+
<meta name="twitter:description" content="個人開発のWebサイトで溜まりがちな「使われていないCSS」をNode.jsスクリプトでサクッと検出して整理しました。" />
55+
<meta name="twitter:image" content="assets/img/ogp.png" />
56+
57+
<link rel="stylesheet" href="../assets/css/base.css" />
58+
<link rel="stylesheet" href="../assets/css/layout.css" />
59+
<link rel="stylesheet" href="../assets/css/blog.css" />
60+
</head>
61+
<body data-page="blog">
62+
<div class="page-shell">
63+
<main class="main-container">
64+
<article class="post-detail reveal-on-scroll">
65+
<header class="post-detail__header">
66+
<p class="post-detail__meta">Thu Jun 27 2024 09:00:00 GMT+0900 (日本標準時) / 開発ログ</p>
67+
<h1 class="post-detail__title">CSSのリファクタリングを手軽にしてみた</h1>
68+
<p class="post-detail__description">個人開発のWebサイトで溜まりがちな「使われていないCSS」をNode.jsスクリプトでサクッと検出して整理しました。</p>
69+
<p class="post-detail__tags"><a class="tag" href="../blog.html?tag=css">css</a> <a class="tag" href="../blog.html?tag=refactoring">refactoring</a> <a class="tag" href="../blog.html?tag=nodejs">nodejs</a> <a class="tag" href="../blog.html?tag=automation">automation</a></p>
70+
</header>
71+
72+
<section class="post-detail__body markdown-body">
73+
<p>こんにちは!パン君です。</p>
74+
<p>機能追加やデザイン変更を繰り返しているうちにCSSファイルの中に**「これ、どこで使ってるんだっけ?」**というクラスが増えてきました。</p>
75+
<ul>
76+
<li>デザイン案Aで書いたけど、結局B案にしたから使わなくなったボタンのクラス</li>
77+
<li>共通化しようとして作ったけど、結局固有クラスを使ったから放置されたスタイル</li>
78+
</ul>
79+
<p>などなど。<br>放置しても動くのですが、ファイルサイズも無駄ですし何より精神衛生上よろしくありません。</p>
80+
<p>そこで、今回はこれらをリファクタリングすることにしました。</p>
81+
<hr>
82+
<h2>手動で探すのは無理</h2>
83+
<p>とはいえ、CSSファイルに書かれているクラス名を一つずつ検索して「使用箇所ゼロ」を確認するのは苦行です。
84+
世の中には <code>PurgeCSS</code> などの便利なツールもありますが、ビルドプロセスに組み込むのが少し大変だったり設定が複雑だったりします。</p>
85+
<p>今回は**「もっと手軽に、ざっくりでいいから不要なものを消したい」**というモチベーションだったので、Node.jsで簡単なスクリプトを書いて検出することにしました。</p>
86+
<h2>自作スクリプトの方針</h2>
87+
<ol>
88+
<li><code>assets/css/</code> フォルダ内のCSSファイルを全部読み込む。</li>
89+
<li>正規表現でクラス名(<code>.classname</code>)とID名(<code>#idname</code>)を抽出する。</li>
90+
<li>プロジェクト内の全ファイル(HTML, JS, MDなど)をスキャンする。</li>
91+
<li>「抽出したクラス名が、どのファイルにも一度も登場しない」場合、それを<strong>未使用候補</strong>として出力する。</li>
92+
</ol>
93+
<p>これだけです。厳密な構文解析(AST)などはせず、単純な文字列検索(<code>includes</code>)で判定します。
94+
その分、「クラス名と偶然同じ単語が文章中にあったら検知漏れする」という弱点はありますが、**「使っていないものを安全に削除する」**という目的には十分です。</p>
95+
<pre><code class="language-javascript">// tools/find-unused-css.js (抜粋)
96+
97+
const cssContent = fs.readFileSync(cssFile, &#39;utf8&#39;);
98+
const selectors = extractSelectors(cssContent); // 正規表現で抽出
99+
100+
selectors.forEach(sel =&gt; {
101+
let isUsed = false;
102+
for (const content of contents) {
103+
// 単純な文字列検索
104+
if (content.includes(sel.name)) {
105+
isUsed = true;
106+
break;
107+
}
108+
}
109+
110+
if (!isUsed) {
111+
console.log(`[UNUSED] ${sel.name}`);
112+
}
113+
});
114+
</code></pre>
115+
<h2>実行結果</h2>
116+
<p>スクリプトを実行してみると、いくつかの未使用クラスが見つかりました。</p>
117+
<pre><code>Checking assets\css\layout.css...
118+
[UNUSED] .section--soft
119+
120+
Checking assets\css\top.css...
121+
[UNUSED] .btn-outline
122+
</code></pre>
123+
<p>確認してみると、
124+
<code>section--soft</code> は初期デザイン案で作ったカードのバリエーション、
125+
<code>btn-outline</code> は枠線のみのボタンで、現在は塗りつぶしボタンしか使っていませんでした。</p>
126+
<p>これらは完全に不要なので迷わず削除!
127+
CSSファイルが少しスリムになりました。</p>
128+
<h2>まとめ</h2>
129+
<p>リファクタリングというと大掛かりな作業をイメージしがちですが、
130+
<strong>「気になったら小さなスクリプトを書いてサクッと調べる」</strong>
131+
というアプローチなら、日常的にコードをきれいに保てそうです。</p>
132+
<p>自分の手で作ったツールで自分のサイトを改善していくのは、エンジニアならではの楽しみですね。</p>
133+
134+
</section>
135+
</article>
136+
</main>
137+
</div>
138+
139+
<script src="../assets/js/layout.js" defer></script>
140+
<script src="../assets/js/ui.js"></script>
141+
142+
<canvas id="menuAnimationCanvas"></canvas>
143+
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
144+
<script src="../assets/js/particles.js"></script>
145+
</body>
146+
</html>

0 commit comments

Comments
 (0)