はじめに
前回はhtml-webpack-pluginで複数のhtmlファイルを動的に出力するやり方について紹介しました。
まだの方はこちらを参考にしてください。
今回はwebpackでsassをコンパイルするやり方ついて紹介します。
web制作ではsassのコンパイルは必須ですよね。
webpackでももちろんsassのコンパイルは出来るのですが、いろんなローダーやプラグインを使用しないといけないので意外と面倒です。
sassのコンパイルのやり方が分からない方は参考にしてください。
webpackの使い方まとめについてはこちら。
web制作をする場合のwebpackのテンプレート紹介についてはこちら。
それでは説明に移ります。
使用するプラグイン
webpackでsassをコンパイルするにあたって、使用するローダーとプラグインをまとめておきます。
プラグイン名 | 内容 |
sass-loader | sassをコンパイルしてcssに変換するローダー |
sass | Dart Sassを使えるようにするプラグイン sass-loaderのオプションで使用する |
postcss-loader | PostCSSでcssを処理するためのローダー PostCSSでcssをいろんな形に加工する |
autoprefixcer | ベンダープレフィックスを自動付与するプラグイン postcss-loaderのオプションで使用する |
css-loader | cssをCommonJS形式に変換してjavaScriptで扱えるようにするローダー |
mini-css-extract-plugin | cssファイルとして別ファイルに出力するプラグイン |
sassをコンパイルしてcssファイルに出力するには上記内容を上から順に処理していくことになります。
ディレクトリ構成
今回のディレクトリ構成は以下です。
test
├ node_modules
├ dist
│ └ css
├ src
│ ├ js
│ │ └ index.js
│ ├ scss
│ │ ├ flocss
│ │ │ ├ _footer.scss
│ │ │ └ _header.scss
│ │ └ style.scss
│ └ index.html
├ package-lock.json
├ package.json
├ webpack.common.js
├ webpack.dev.js
└ webpack.prod.js
src/scss/style.scssをコンパイルしてdist/cssフォルダに出力させていきましょう。
webpackでsassをコンパイルするためにエントリポイントのjsファイルにstyle.scssを読み込ませるやり方で説明していきます。
ファイル内容
今回はwebpack.common.js の記述がメインとなるので、それ以外のファイル内容を参考までに示しておきます。
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>index.htmlです</h1>
</body>
</html>
style.scss
@use './flocss/header';
@use './flocss/footer';
index.js
import '../scss/style.scss'; // ここでsassの読み込みをさせる
console.log('index.jsです');
webpack.dev.js
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
const outputFile = '[name]';
module.exports = merge(common(outputFile), {
mode: 'development',
devtool: 'source-map',
});
webpack.prod.js
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
const outputFile = '[name].[chunkhash]';
module.exports = merge(common(outputFile), {
mode: 'production',
});
プラグインをインストールしよう
それではsassをコンパイルするためのローダーとプラグインをインストールしていきましょう。
npm i -D sass-loader sass
下記コマンドをターミナルで実行してsass-loaderとsassをインストールします。
npm i -D sass-loader sass
sass-loader公式
sass公式
npm i -D postcss-loader autoprefixer
こちらも同様にインストールします。
npm i -D postcss-loader autoprefixer
postcss-loader公式
autoprefixcer公式
npm i -D css-loader
こちらも同様にインストールします。
npm i -D css-loader
css-loader公式
npm i -D mini-css-extract-plugin
こちらも同様にインストールします。
npm i -D mini-css-extract-plugin
mini-css-extract-plugin公式
webpack.common.jsを編集する
ローダーとプラグインのインストールが完了したらwebpack.common.jsを編集していきましょう。
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackWatchedGlobEntries = require('webpack-watched-glob-entries-plugin');
// 追加
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const entries = WebpackWatchedGlobEntries.getEntries([path.resolve(__dirname, './src/js/**/*.js')], {
ignore: path.resolve(__dirname, './src/js/**/_*.js'),
})();
const htmlGlobPlugins = (entries, srcPath) => {
return Object.keys(entries).map(
(key) =>
new HtmlWebpackPlugin({
inject: 'body',
filename: `${key}.html`,
template: `${srcPath}/${key}.html`,
chunks: [key],
})
);
};
module.exports = (outputFile) => ({
entry: entries,
output: {
path: path.resolve(__dirname, './dist'),
filename: `./js/${outputFile}.js`,
},
module: {
rules: [
// 追加
{
test: /\.(sa|sc|c)ss$/i,
use: [
// cssファイルとして別ファイルに出力する
MiniCssExtractPlugin.loader,
// cssをCommonJS形式に変換してjavaScriptで扱えるようにする
'css-loader',
{
// PostCSSでcssを処理する
loader: 'postcss-loader',
options: {
postcssOptions: {
// ベンダープレフィックスを自動付与する
plugins: [require('autoprefixer')({ grid: true })],
},
},
},
{
// sassをコンパイルしてcssに変換する
loader: 'sass-loader',
options: {
// Dart Sassを使えるようにする
implementation: require('sass'),
},
},
],
},
{
test: /\.html$/i,
loader: 'html-loader',
},
{
test: /\.(png|jpe?g|gif|svg)$/i,
generator: {
filename: `./image/[name].[contenthash][ext]`,
},
type: 'asset/resource',
},
],
},
plugins: [
new CleanWebpackPlugin(),
new WebpackWatchedGlobEntries(),
// 追加
new MiniCssExtractPlugin({
filename: `./css/${outputFile}.css`,
}),
...htmlGlobPlugins(entries, './src'),
],
});
追加した箇所について説明していきます。
モジュール読み込み
以下の記述でmini-css-extract-pluginを読み込みしています。
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
ローダー処理定義
以下の記述でsassをコンパイルするための処理を定義しています。
{
test: /\.(sa|sc|c)ss$/i,
use: [
// cssファイルとして別ファイルに出力する
MiniCssExtractPlugin.loader,
// cssをCommonJS形式に変換してjavaScriptで扱えるようにする
'css-loader',
{
// PostCSSでcssを処理する
loader: 'postcss-loader',
options: {
postcssOptions: {
// ベンダープレフィックスを自動付与する
plugins: [require('autoprefixer')({ grid: true })],
},
},
},
{
// sassをコンパイルしてcssに変換する
loader: 'sass-loader',
options: {
// Dart Sassを使えるようにする
implementation: require('sass'),
},
},
],
},
autoprefixerでベンダープレフィックスを自動付与させるにはpackage.json を編集する必要があります。
package.json にbrowserslist オプションを追記することで、どのブラウザのいつのバージョンまでベンダープレフィックスを自動付与させるか設定させることができます。
browserslist の値はご自身の環境に合わせて変更してみてください。
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "webpack.common.js",
"scripts": {
"dev": "npx webpack --config ./webpack.dev.js",
"pro": "npx webpack --config ./webpack.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"autoprefixer": "^10.4.2",
"clean-webpack-plugin": "^4.0.0",
"css-loader": "^6.6.0",
"html-loader": "^3.1.0",
"html-webpack-plugin": "^5.5.0",
"mini-css-extract-plugin": "^2.5.3",
"postcss-loader": "^6.2.1",
"sass": "^1.49.7",
"sass-loader": "^12.4.0",
"webpack": "^5.68.0",
"webpack-cli": "^4.9.2",
"webpack-watched-glob-entries-plugin": "^2.2.3"
},
"browserslist": [
"last 2 versions",
"ie >= 11",
"Android >= 4"
]
}
プラグイン追加
以下でwebpackにmini-css-extract-pluginのプラグインを追加させています。
new MiniCssExtractPlugin({
filename: `./css/${outputFile}.css`,
}),
filenameオプションでcssファイルを出力する場所とファイル名を指定しています。
filenameオプションには[name]や[contenthash]などののプレースホルダーを指定することもできます。
コンパイルする
設定が完了したのでコンパイルしてみましょう。
以下のコマンドをターミナルから打ち込みます。
npx webpack --config ./webpack.dev.js
以下のようなメッセージが出力されていれば正しく実行できています。
PS C:\Users\shuuk\OneDrive\デスクトップ\test> npx webpack --config ./webpack.dev.js
assets by chunk 3.32 KiB (name: index) asset ./js/index.js 2.46 KiB [emitted] (name: index) 1 related asset
asset ./css/index.css 881 bytes [emitted] (name: index) 1 related asset
asset ./image/embedded_covid03.7d5f9ce136732547b4ce.jpg 788 KiB [emitted] [immutable] [from: src/image/embedded_covid03.jpg] (auxiliary name: index)
asset index.html 435 bytes [emitted]
Entrypoint index 3.32 KiB (790 KiB) = ./css/index.css 881 bytes ./js/index.js 2.46 KiB 3 auxiliary assets
orphan modules 5.08 KiB (javascript) 788 KiB (asset) 1.08 KiB (runtime) [orphan] 10 modules
runtime modules 279 bytes 1 module
cacheable modules 110 bytes (javascript) 278 bytes (css/mini-extract)
./src/js/index.js 60 bytes [built] [code generated]
./src/scss/style.scss 50 bytes [built] [code generated] css ./node_modules/css-loader/dist/cjs.js!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[0].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[0].use[3]!./src/scss/style.scss 278 bytes [built] [code generated]
webpack 5.68.0 compiled successfully in 1754 ms
PS C:\Users\shuuk\OneDrive\デスクトップ\test>
cssファイルが出力されているはずです。
画像やフォントの読み込みがうまくいかない
ここまででsassをコンパイルするやり方について説明しました。
ただし1点注意として、sassで記述した画像やフォントの指定をwebpackが解決してくれなくてエラーになる場合があります。
原因はsassで記述する際の相対パスの基準が変わるためです。
これらを解決する方法については別記事にて紹介します。
おわりに
以上webpackでsassをコンパイルするやり方ついて紹介しました。
いかがだったでしょうか。
webpackでsassのコンパイルするやり方が分からない方は参考にしてください。
次回はwebpackでsassの画像やフォントのアセットファイルの依存関係を解決するやり方ついて紹介します。
コメント