Help us understand the problem. What is going on with this article?

PostCSSをwebpackでサクッと動かせるサンプル

間違っているなどありましたらご指摘お願いいたします:bow:

参考

確認バージョン

  • webpack 4

最小限で動かす

参考:michael-ciniawsky/postcss-load-config: Autoload Config for PostCSS

サンプルはこちら

bash
npm init -y
npm i -D webpack webpack-cli style-loader css-loader postcss-loader postcss-nested
./webpack.config.js
module.exports = {
    mode: 'development',
    module: {
        rules: [{
            test: /\.pcss/,
            use: [
                'style-loader',
                'css-loader',
                {
                    loader: 'postcss-loader',
                    options: { plugins: [ require('postcss-nested') ] },
                },
            ],
        }]
    }
};

loaderはuse: []の配列の下から順に適用されていきます。

今回の例では、.pcss ファイルに対して、

  1. postcss-loader がプラグインを使用して、cssでネストした書き方をプレーンなcssに変換
  2. css-loader でcssをjsにバンドルする機能
  3. style-loader<head> の最後尾に <style> を追加する機能

という順で適用されていきます

./src/index.js
import './style.pcss';
./src/style.pcss
p {
    color: seagreen;
    span {
        color: deepskyblue;
    }
}
./index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="dist/main.js"></script>
</head>
<body>
    <p>Heloo <span>World!</span></p>
</body>
</html>
bash
npx webpack

PostCSSを使ってcssをネストして書くことができました

image.png

PostCSSの設定を別ファイルにする

サンプルはこちら

bash
npm init -y
npm i -D webpack webpack-cli style-loader css-loader postcss-loader postcss-nested

.postcssrc.json

./webpack.config.js
module.exports = {
    mode: 'development',
    module: {
        rules: [{
            test: /\.pcss/,
            use: ['style-loader', 'css-loader', 'postcss-loader'],
        }]
    }
};
./.postcssrc.json
{
    "plugins": {
        "postcss-nested": {}
    }
}
bash
npx webpack

先ほどと同じように実行されることが確認できました。

image.png

.postcssrc.yml

yamlで記述することもできます

.postcssrc.yml
plugins:
  postcss-nested: {}

.postcssrc.js or postcss.config.js

設定ファイル内にロジックが必要な場合はこちらで記述する

この例ではロジックはないですが、以下のようにするとjsonやyamlの設定ファイルと同じように動かすことができました

.postcssrc.js
module.exports = {
    plugins: {
        'postcss-nested': {}
    }
};
postcss.config.js
module.exports = {
    plugins: {
        'postcss-nested': {}
    }
};

cssファイルにする

サンプルはこちら

jsにcssをバンドルするという方法でやってきましたが、
最終的にcssファイルを出力し、htmlからlinkタグでcssを取得する方法でやってみます

参考

bash
npm init -y
npm i -D webpack webpack-cli css-loader postcss-loader postcss-nested extract-text-webpack-plugin@next

↑ webpack 4だと、extract-text-webpack-plugin だとうまく動かないため、 extract-text-webpack-plugin@next をインストールするようにしましょう ※2019/02/23現在

./webpack.config.js
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
    mode: 'development',
    entry: './src/style.pcss',
    output: {
        path: `${__dirname}/dist`,
        filename: '[name].css', // 生成するjsファイル名
    },
    module: {
        rules: [{
            test: /\.pcss/,
            use: ExtractTextPlugin.extract({
                use: [
                    'css-loader',
                    {
                        loader: 'postcss-loader',
                        options: { plugins: [ require('postcss-nested') ] },
                    },
                ]
            }),
        }]
    },
    plugins: [
        new ExtractTextPlugin('[name].css'), // cssファイルを生成されたjsファイルと同じ名前にし上書きする -> cssファイルのみ出力という結果になる
    ],
};
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" href="dist/main.css">
</head>
<body>
    <p>Heloo <span>World!</span> from css file</p>
</body>
</html>

cssファイルを出力しhtmlから読み込むことができました

image.png

ソースマップを有効にする

サンプルはこちら

bash
npm init -y
npm i -D webpack webpack-cli style-loader css-loader postcss-loader postcss-nested
./webpack.config.js
module.exports = {
    mode: 'development',
    module: {
        rules: [{
            test: /\.pcss/,
            use: [
                'style-loader',
                {
                    loader: 'css-loader',
                    options: {
                        sourceMap: true,
                    }
                },
                {
                    loader: 'postcss-loader',
                    options: { 
                        sourceMap: true,
                        plugins: [ require('postcss-nested') ] 
                    },
                },
            ],
        }]
    }
};

ソースマップが有効になりました

image.png

sassと併用する

サンプルはこちら

bash
npm init -y
npm i -D webpack webpack-cli style-loader css-loader postcss-loader autoprefixer sass-loader node-sass 
./webpack.config.js
module.exports = {
    mode: 'development',
    module: {
        rules: [{
            test: /\.scss/,
            use: [
                'style-loader',
                'css-loader',
                {
                    loader: 'postcss-loader',
                    options: { plugins: [ require('autoprefixer') ] },
                },
                'sass-loader',
            ],
        }]
    }
};
./src/style.scss
body {
    background: yellowgreen;
    div {
        transform: scale(.7);
    }
}
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="dist/main.js"></script>
</head>
<body>
    <div>BOX</div>
</body>
</html>

scssとpostcssからのautoprefixerを併用できました

image.png

css-loader@import を使う際の注意点

@importの動作を確認

  • まずcss-loaderなどを使わない状態の@importの動作を確認
sample.css
@import "import.css";

p {
    font-weight: bold;
}
import.css
body {
    background: yellowgreen;
}

sample.cssとimport.cssで2回通信が発生しています

image.png

  • 次にcss-loaderを使った場合の@importの動作を確認
bash
npm init -y
npm i -D webpack webpack-cli style-loader css-loader postcss-loader postcss-nested
./webpack.config.js
module.exports = {
    mode: 'development',
    module: {
        rules: [{
            test: /\.css/,
            use: ['style-loader', 'css-loader'],
        }]
    }
};
./src/index.js
import './sample.css';
./src/sample.css
@import "import.css";

p {
    font-weight: bold;
}
./src/import.css
body {
    background: yellowgreen;
}
bash
npx webpack

通信は、./dist/main.jsを取得する1回だけとなり、<style>タグが2つ追加されるという動きになります

image.png

  • この@importをpostcssと使うときにデフォルトだとうまくいきません
./webpack.config.js
module.exports = {
    mode: 'development',
    module: {
        rules: [{
            test: /\.pcss/,
            use: [
                'style-loader',
                'css-loader',
                {
                    loader: 'postcss-loader',
                    options: { plugins: [require('postcss-nested')] },
                },
            ],
        }]
    }
};
./src/index.js
import './sample.pcss';
./src/sample.pcss
@import "import.pcss";

div {
    h1 {
        color: green;
    }
}
./src/import.pcss
div {
    h2 {
        color: red;
    }
}
bash
npx webpack

image.png

このように、postcss-nestedsample.pcssには適用されますが、import.pcssには適用されていません。
プレーンなcssの構文としては間違っているため、h2のcolor:red;も反映されていません。


importLoadersを設定するとうまくいく

./webpack.config.js
module.exports = {
    mode: 'development',
    module: {
        rules: [{
            test: /\.pcss/,
            use: [
                'style-loader',
                {
                    loader: 'css-loader',
                    options: {
                        importLoaders: 1, // importするときに適用するloaderの数を設定、sassとpostcssを使っていた場合は「2」と設定する
                    },
                },
                {
                    loader: 'postcss-loader',
                    options: { plugins: [require('postcss-nested')] },
                },
            ],
        }]
    }
};
bash
npx webpack

image.png

@importで取得した内容にも、postcss-loaderが適用されたことが確認できました。

サンプルはこちら

参考:Clarify importLoaders documentation? · Issue #228 · webpack-contrib/css-loader

postcss-importを使っても良い

postcss-importを使ってimportすることでも、↑の問題を回避することができるようでした

bash
npm init -y
npm i -D webpack webpack-cli style-loader css-loader postcss-loader postcss-nested postcss-import
./webpack.config.js
module.exports = {
    mode: 'development',
    module: {
        rules: [{
            test: /\.pcss/,
            use: [
                'style-loader',
                'css-loader',
                {
                    loader: 'postcss-loader',
                    options: { plugins: [
                        require('postcss-import'),
                        require('postcss-nested'), 
                    ]},
                },
            ],
        }]
    }
};

image.png

サンプルはこちら


最後まで読んでいただいてありがとうございましたm(_ _)m

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした