Astroでcssファイル名を無理矢理変更してみた
Astroでscssファイルを複数importしビルドした際に、ファイル名が全て同じになってしまい区別がつきませんでした。。
正直言ってマジでこれも需要があるかどうかわかんないのに、無理矢理変更できるよう組んでみました
css名をstyle-ほにゃららになるように設定しています
以下のように吐き出すよう設定しています
return `assets/[ext]/[name]-[hash][extname]`;
まずimportしてみる
例えばsample.scssとsample02.scssをそれぞれsample.css, sample02.cssのように出力したいと思っても、index.astroでimportすると...
---
(中略)
import "src/scss/style.scss";
import "src/scss/sample.scss";
import "src/scss/sample02.scss";
---
全部index-ほにゃららになります...
style.css, sample.css, sample02.cssと出力されるのが理想なのですが、、、
これでは区別がつきません
import、もしくはindex.astroのstyleタグに記述があるとcssを吐き出すみたいです
scssをimport, index.astroとabout/index.astroのstyleタグに記述があるので3つ吐き出してます
ドキュメントも見ましたが、個別でリネームする手段がなさそうなので作ることとしました
手順
全部書くとbuild項目のところが長くなりすぎるので、npm i npm-run-all
してrun-s
で書きます
sample.scssをsample.cssとして出力する例を書きます
index.astroでのimportは消しておいてください
吐き出し設定は以下のように[name]はやめ、style.scssのみimportさせます
return `assets/[ext]/style-[hash][extname]`;
---
(中略)
import "src/scss/style.scss";
---
sassコンパイル
まずnpm i sass
して、nodeで単純にコンパイルさせます
これでビルド後にsassコンパイルが走り、sample.cssが吐き出されます
{
(中略)
...
"scripts": {
"dev": "astro dev --host",
"start": "astro dev",
"build": "astro build",
"postbuild": "run-s sass",
"sass": "run-s sass:sample",
"sass:sample": "sass src/scss/sample.scss dist/assets/css/sample.css --no-source-map",
}
}
index.astroでの記述
普通にscss読み込ませます。
<link rel="stylesheet" href="src/scss/sample.scss" />
これでdevは読んでくれるので問題ないです。
ただしビルドした後はhtmlファイルなのでscssが読めません
なのでhrefを変更させる必要があります
html書き換え用のjsを作成
まずastro.config.mjsと同階層にjsファイルを作成します
import fs from "fs";
import path from "path";
/**
* ランダムな値を生成
* @param {number} [digit=8] 桁数
* @return {string} 生成されたランダムな桁数分の値を返す
*/
const randomStr = function (digit) {
var patterns = '0123456789abcdefghijklmnopqrstuvwxyz'.split(''),
val = '';
if (typeof digit === 'undefined') digit = 8;
for (var i = 0; i < digit; i++) {
val += patterns[Math.floor(Math.random() * patterns.length)] + '';
}
return val;
};
//デフォルト(import)で読み込むscss
const defaultImportScss = "style.scss";
// src/scss直下のscssファイル一覧取得
const scssFilesList = fs.readdirSync("src/scss").filter((file) => {
if (file.indexOf(".scss") !== -1) return file;
});
// src/scss直下のデフォルトで読み込むscss以外のscssファイル一覧
let scssFilesListExceptStyle = scssFilesList.filter((file) => {
if (file.indexOf(defaultImportScss) === -1) return file;
});
//index.astro内のlinkタグで読み込んだscssのhrefを取得
let srcScssHref = [];
scssFilesListExceptStyle.forEach((fileName) => {
srcScssHref.push(`src/scss/${fileName}`);
});
let indexHtmlList = ""; //.index.html配列
/**
* htmlファイル一覧を配列に格納し変数に代入する関数
*/
function getIndexHtmlList() {
const dirTarget = "dist";
//即時関数getFiles(ファイル情報取得)
(function getFiles(dir) {
var files = fs.readdirSync(dir); // 指定フォルダ内のファイル、サブフォルダを取得
files.forEach(function (file) {
var fullPath = path.join(dir, file); // フルパスを取得
// log(fullPath)
var stats = fs.statSync(fullPath); // ファイル(またはフォルダ)の情報を取得
if (stats.isDirectory()) {
// フォルダの場合
getFiles(fullPath); // getFilesを再帰的に呼び出し
}
if (fullPath.indexOf(".html") !== -1) {
indexHtmlList += fullPath + ",";
}
});
})(dirTarget);
//配列に直し、空要素の削除
indexHtmlList = indexHtmlList.split(",").filter(Boolean);
}
getIndexHtmlList();
/**
* htmlファイル書き換え関数
*/
const rewriteHtml = () => {
indexHtmlList.forEach((index) => {
// *.htmlファイルの読み込み
const indexDocument = fs.readFileSync(index, "utf-8");
//htmlファイル内のlinkタグのhrefに配列srcScssHrefにある値(src/scss/*.scss)が含まれていた場合
srcScssHref.forEach((scss, i) => {
if (indexDocument.indexOf(scss) !== -1) {
//ハッシュ生成
const hash = randomStr();
//ファイルパス名を.cssに変換
const cssName = scssFilesListExceptStyle[i].replace("scss", "css");
//ハッシュを加えたcssファイル名を生成
const cssNameHash = `${cssName.split(".")[0]}-${hash}.css`;
//hrefをscss用からcss用に修正
const result = indexDocument.replace(scss, `./assets/css/${cssNameHash}`);
//html書き込み
fs.writeFileSync(index, result);
//cssファイル名をハッシュ付きに変更
fs.renameSync(
path.join(`./dist/assets/css/`, cssName),
path.join(`./dist/assets/css/`, cssNameHash)
);
}
});
});
};
rewriteHtml();
const defaultImportScss = "style.scss";
これはimportするscssファイルを指定することで
let scssFilesListExceptStyle = scssFilesList.filter((file) => { if (file.indexOf(defaultImportScss) === -1) return file; });
この時、その指定されたscssファイル以外の配列を作ってます
この例で言えば、scssFilesListExceptStyle = ["sample.scss"]
になるってことです
で、その配列をもとにdist内のhtmlを書き換える作業に入ります
全部説明するのはしんどいので省略します
Astroがデフォルトで吐き出すcssにハッシュが付くようにしているので、sample.cssにもハッシュ(正確に言えばただの文字列)を加えるようにしてあります
ただしlinkタグでscss読み込みしていない場合はハッシュがつきません
scriptsにjs実行を登録
先ほどのjsを作って、ビルド後に実行する必要があります
package.jsonを以下のように修正します
{
(中略)
...
"scripts": {
"dev": "astro dev --host",
"start": "astro dev",
"build": "astro build",
- "postbuild": "run-s sass",
+ "postbuild": "run-s sass && run-s scssToCss",
"sass": "run-s sass:sample",
"sass:sample": "sass src/scss/sample.scss dist/assets/css/sample.css --no-source-map",
+ "scssToCss": "node scssToCss.js",
}
}
そうするとこんな感じでハッシュがつきます
hoge.scssもhoge.cssとして出力したいみたいな場合は以下のようにscriptsを追加する必要があります
"sass": "run-s sass:sample && run-s sass:hoge",
"sass:sample": "sass src/scss/sample.scss dist/assets/css/sample.css --no-source-map",
"sass:hoge": "sass src/scss/hoge.scss dist/assets/css/hoge.css --no-source-map",
Discussion