ä½¿ç¨ PostCSS å¤ç CSS ç loaderã
妿è¦ä½¿ç¨ææ°çæ¬çè¯ï¼ä½ éè¦ä½¿ç¨ webpack v5ãå¦æä½¿ç¨ webpack v4 çè¯ï¼ä½ éè¦å®è£ postcss-loader v4ã
为äºä½¿ç¨æ¬ loaderï¼ä½ éè¦å®è£
postcss-loader å postcssï¼
npm install --save-dev postcss-loader postcss
ç¶åæ·»å æ¬ loader çç¸å
³é
ç½®å°ä½ ç webpack çé
ç½®æä»¶ãä¾å¦ï¼
In the following configuration the plugin
postcss-preset-envis used, which is not installed by default.
file.js
import css from 'file.css';webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
[
'postcss-preset-env',
{
// å
¶ä»é项
},
],
],
},
},
},
],
},
],
},
};æè ä½¿ç¨ PostCSS æ¬èº«ç é ç½®æä»¶ï¼
postcss.config.js
module.exports = {
plugins: [
[
'postcss-preset-env',
{
// å
¶ä»é项
},
],
],
};Loader å°ä¼èªå¨æç´¢é ç½®æä»¶ã
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader', 'postcss-loader'],
},
],
},
};æåï¼éè¿ä½ 忬¢çæ¹å¼è¿è¡ webpackã
| åç§° | ç±»å | é»è®¤å¼ | æè¿° |
|---|---|---|---|
execute | {Boolean} | undefined | å¨ CSS-in-JS ä¸å¯å¨ PostCSS Parser æ¯æ |
postcssOptions | {Object|Function} | Postcss.processçé»è®¤å¼ | 设置 PostCSS é项䏿件 |
sourceMap | {Boolean} | compiler.devtool | å¼å¯ / å ³é source map ççæ |
implementation | {Function|String} | postcss | 为 PostCSS 设置对åºå®ç°å¹¶ä½¿ç¨ |
executeç±»åï¼Boolean
é»è®¤å¼ï¼undefined
å¦æä½ å¨ JS æä»¶ä¸ç¼åæ ·å¼ï¼è¯·ä½¿ç¨ postcss-js parserï¼å¹¶ä¸æ·»å execute é项ã
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.style.js$/,
use: [
'style-loader',
{
loader: 'css-loader',
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
parser: 'postcss-js',
},
execute: true,
},
},
],
},
],
},
};postcssOptionsç±»åï¼Object|Function
é»è®¤å¼ï¼undefined
å
许设置 PostCSS é项 åæä»¶ã
æ¯æææç PostCSS é项ã
è¿æ¯é
ç½®æä»¶ä¸ç¹æ®ç é
ç½® é项ãå®å¦ä½å·¥ä½ãå¦ä½é
ç½®åæ¥ä¸æ¥çé¨åå°ä¼æè¯¦ç»çæè¿°ã
å 为å¯è½ä¼å¯¼è´ source map ä¸é误çæä»¶è·¯å¾ï¼æä»¬ä¸æ¨èä½¿ç¨æå®ç fromãto å map é项ã
å¦æä½ éè¦ source mapï¼è¯·ä½¿ç¨ sourcemap é项ã
Object设置 pluginsï¼
webpack.config.js (recommended)
const myOtherPostcssPlugin = require('postcss-my-plugin');
module.exports = {
module: {
rules: [
{
test: /\.sss$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
'postcss-import',
['postcss-short', { prefix: 'x' }],
require.resolve('my-postcss-plugin'),
myOtherPostcssPlugin({ myOption: true }),
// åºå¼çï¼å°ä¼å¨ä¸ä¸ä¸ªä¸»è¦çæ¬ä¸ç§»é¤
{ 'postcss-nested': { preserveEmpty: true } },
],
},
},
},
],
},
};webpack.config.js ï¼åºå¼çï¼å°ä¼å¨ä¸ä¸ä¸ªä¸»è¦çæ¬ä¸ç§»é¤ï¼
module.exports = {
module: {
rules: [
{
test: /\.sss$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: {
'postcss-import': {},
'postcss-short': { prefix: 'x' },
},
},
},
},
],
},
};设置 syntaxï¼
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.sss$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
// å¯ä»¥æ¯ `String`
syntax: 'sugarss',
// å¯ä»¥æ¯ `Object`
syntax: require('sugarss'),
},
},
},
],
},
};设置 parserï¼
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.sss$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
// å¯ä»¥æ¯ `String`
parser: 'sugarss',
// å¯ä»¥æ¯ `Object`
parser: require('sugarss'),
// å¯ä»¥æ¯ `Function`
parser: require('sugarss').parse,
},
},
},
],
},
};设置 stringifierï¼
webpack.config.js
const Midas = require('midas');
const midas = new Midas();
module.exports = {
module: {
rules: [
{
test: /\.sss$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
// å¯ä»¥æ¯ `String`
stringifier: 'sugarss',
// å¯ä»¥æ¯ `Object`
stringifier: require('sugarss'),
// å¯ä»¥æ¯ `Function`
stringifier: midas.stringifier,
},
},
},
],
},
};Functionwebpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(css|sss)$/i,
loader: 'postcss-loader',
options: {
postcssOptions: (loaderContext) => {
if (/\.sss$/.test(loaderContext.resourcePath)) {
return {
parser: 'sugarss',
plugins: [
['postcss-short', { prefix: 'x' }],
'postcss-preset-env',
],
};
}
return {
plugins: [
['postcss-short', { prefix: 'x' }],
'postcss-preset-env',
],
};
},
},
},
],
},
};configç±»åï¼Boolean|String
é»è®¤å¼ï¼undefined
å 许使ç¨é ç½®æä»¶è®¾ç½®é项ã å¨é ç½®æä»¶ä¸æå®çé项å°ä¼å loader option è¿è¡åå¹¶ï¼å¹¶ä¸ loader option å°ä¼è¦çé ç½®æä»¶ä¸çé项ã
Loader å°ä¼ä»ä¸é¢å ä¸ªå°æ¹æç´¢ç®å½æ æ¥å¯»æ¾é ç½®æä»¶ï¼
package.json ä¸ç postcss 屿§.postcssrc æä»¶.postcss.jsonã.postcss.yamlã.postcss.ymlã.postcss.js æè
.postcss.cjs æä»¶postcss.config.js æè
postcss.config.cjs 导åºä¸ä¸ªå¯¹è±¡ç CommonJS 模åï¼æ¨èï¼ä½¿ç¨ Objectï¼
postcss.config.jsï¼æ¨èï¼
module.exports = {
// ä½ å¯ä»¥æå®ä¸é¢æå°çææé项 https://postcss.org/api/#processoptions
// parser: 'sugarss',
plugins: [
// PostCSS æä»¶
['postcss-short', { prefix: 'x' }],
'postcss-preset-env',
],
};ä½¿ç¨ Functionï¼
postcss.config.jsï¼æ¨èï¼
module.exports = (api) => {
// `api.file` - æä»¶è·¯å¾
// `api.mode` - webpack ç `mode` 屿§å¼ï¼è¯·æ¥é
https://webpack.js.org/configuration/mode/
// `api.webpackLoaderContext` - å¨å¤ææ
åµä¸ä½¿ç¨ç loader ä¸ä¸æ
// `api.env` - `api.mode` çå«åï¼ä¸ `postcss-cli` å
¼å®¹
// `api.options` - `postcssOptions` çé项
if (/\.sss$/.test(api.file)) {
return {
//ä½ å¯ä»¥æå®ä¸é¢æå°çææé项 https://postcss.org/api/#processoptions here
parser: 'sugarss',
plugins: [
// PostCSS æä»¶
['postcss-short', { prefix: 'x' }],
'postcss-preset-env',
],
};
}
return {
// ä½ å¯ä»¥æå®ä¸é¢æå°çææé项 https://postcss.org/api/#processoptions
plugins: [
// PostCSS æä»¶
['postcss-short', { prefix: 'x' }],
'postcss-preset-env',
],
};
};postcss.config.jsï¼åºå¼çï¼å°ä¼å¨ä¸ä¸ä¸ªä¸»è¦çæ¬ä¸ç§»é¤ï¼
module.exports = {
// ä½ å¯ä»¥æå®ä¸é¢æå°çææé项 https://postcss.org/api/#processoptions
// parser: 'sugarss',
plugins: {
// PostCSS æä»¶
'postcss-short': { prefix: 'x' },
'postcss-preset-env': {},
},
};ä½ å¯ä»¥å¨ä¸åçç®å½ä¸ä½¿ç¨ä¸åç postcss.config.js æä»¶ã
é
ç½®æä»¶ç寻æ¾ä» path.dirname(file) å¼å§æ ¹æ®æä»¶æ åä¸å¯»æ¾ï¼ç´è³æ¾å°ä¸ä¸ªé
ç½®æä»¶ã
|â components
| |â component
| | |â index.js
| | |â index.png
| | |â style.css (1)
| | |â postcss.config.js (1)
| |â component
| | |â index.js
| | |â image.png
| | |â style.css (2)
|
|â postcss.config.js (1 && 2 (recommended))
|â webpack.config.js
|
|â package.jsonå¨è®¾ç½® postcss.config.js ä¹åï¼å° postcss-loader æ·»å å° webpack.config.js ä¸ã
ä½ å¯ä»¥åç¬ä½¿ç¨å®ï¼æè
ä¸ css-loader ç»å使ç¨ï¼æ¨èï¼ã
å¨ css-loader å style-loader ä¹å使ç¨å®ï¼ä½æ¯å¨å
¶ä»é¢å¤çå¨ï¼ä¾å¦ï¼sass|less|stylus-loaderï¼ä¹åä½¿ç¨ ï¼å 为 webpack loader ä»å³å°å·¦ / ä»åºå°é¡¶æ§è¡ï¼ã
webpack.config.js ï¼æ¨èï¼
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1,
},
},
'postcss-loader',
],
},
],
},
};å¼å¯ / å ³éèªå¨å è½½é ç½®ã
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
config: false,
},
},
},
],
},
};å 许æå®é ç½®æä»¶è·¯å¾ã
webpack.config.js
const path = require('path');
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
loader: 'postcss-loader',
options: {
postcssOptions: {
config: path.resolve(__dirname, 'custom.config.js'),
},
},
},
],
},
};sourceMapç±»åï¼Boolean
é»è®¤å¼ï¼ä¾èµäº compiler.devtool çå¼
é»è®¤æ
åµä¸ source map ççæä¾èµäº devtoolé项ã
é¤ eval å false å¤ï¼å
¶ä»çå¼é½å°æå¼ source map çæã
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader', options: { sourceMap: true } },
{ loader: 'postcss-loader', options: { sourceMap: true } },
{ loader: 'sass-loader', options: { sourceMap: true } },
],
},
],
},
};æ¿ä»£è®¾ç½®ï¼
webpack.config.js
module.exports = {
devtool: 'source-map',
module: {
rules: [
{
test: /\.css$/i,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{ loader: 'postcss-loader' },
{ loader: 'sass-loader' },
],
},
],
},
};implementationç±»åï¼Function | String
é»è®¤å¼ï¼postcss
ç¹æ®ç implementation é项å³å®ä½¿ç¨ PostCSS åªä¸ªå®ç°ãéè½½æ¬å°å®è£
ç postcss ç peerDependency çæ¬ã
æ¤é项åªå¯¹åºå±å·¥å ·çä½è ææï¼ä»¥ä¾¿äº PostCSS 7 å° PostCSS 8 çè¿æ¸¡ã
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{
loader: 'postcss-loader',
options: { implementation: require('postcss') },
},
{ loader: 'sass-loader' },
],
},
],
},
};webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{
loader: 'postcss-loader',
options: { implementation: require.resolve('postcss') },
},
{ loader: 'sass-loader' },
],
},
],
},
};ä½ éè¦å®è£
sugarssï¼
npm install --save-dev sugarss
ä½¿ç¨ SugarSS 奿³åæå¨ã
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.sss$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: { importLoaders: 1 },
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
parser: 'sugarss',
},
},
},
],
},
],
},
};ä½ éè¦å®è£
autoprefixerï¼
npm install --save-dev autoprefixer
ä½¿ç¨ autoprefixer æ·»å åååç¼ã
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: { importLoaders: 1 },
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
[
'autoprefixer',
{
// é项
},
],
],
},
},
},
],
},
],
},
};â ï¸
postcss-preset-envå å«autoprefixerï¼å æ¤å¦æä½ å·²ç»ä½¿ç¨äº preset å°±æ éåç¬æ·»å å®äºãæ´å¤ ä¿¡æ¯
ä½ éè¦å®è£
postcss-preset-envï¼
npm install --save-dev postcss-preset-env
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: { importLoaders: 1 },
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
[
'postcss-preset-env',
{
// é项
},
],
],
},
},
},
],
},
],
},
};ä»ä¹æ¯ CSS Modulesï¼è¯· é
读ã
å¨ postcss-loader 䏿²¡æé¢å¤ç设置ã
为äºä½¿ä»ä»¬æ£å¸¸å·¥ä½ï¼è¯·æ·»å css-loader ç importLoaders é项ã
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
importLoaders: 1,
},
},
'postcss-loader',
],
},
],
},
};postcss-jsä½ éè¦å®è£
postcss-jsï¼
npm install --save-dev postcss-js
å¦æä½ æ³å¤çåå¨ JavaScript ä¸çæ ·å¼ï¼é£ä¹ä½ éè¦ä½¿ç¨ postcss-js parserã
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.style.js$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
},
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
parser: 'postcss-js',
},
execute: true,
},
},
'babel-loader',
],
},
],
},
};æ¥ä¸æ¥ä½ å°±å¯ä»¥åä¸é¢è¿æ ·ä¹¦åæ ·å¼äº
import colors from './styles/colors';
export default {
'.menu': {
color: colors.main,
height: 25,
'&_link': {
color: 'white',
},
},
};â ï¸ å¦æä½ æ£å¨ä½¿ç¨ Babel ä¸ä¸ºäºç¨åºæ£å¸¸å·¥ä½ï¼ä½ éè¦è¿è¡ä¸é¢çæ¥éª¤ï¼
- æ·»å
babel-plugin-add-module-exportså°ä½ çé ç½®ä¸ã- ä½ éè¦å¨æ¯ä¸ä¸ªæ ·å¼æ¨¡å䏿ä¸ä¸ªé»è®¤å¯¼åºã
ä½¿ç¨ mini-css-extract-pluginã
webpack.config.js
const isProductionMode = process.env.NODE_ENV === 'production';
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
mode: isProductionMode ? 'production' : 'development',
module: {
rules: [
{
test: /\.css$/,
use: [
isProductionMode ? MiniCssExtractPlugin.loader : 'style-loader',
'css-loader',
'postcss-loader',
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: isProductionMode ? '[name].[contenthash].css' : '[name].css',
}),
],
};è¦å°èµæºä» PostCSS æä»¶åå° webpackï¼éè¦å result.messages 䏿·»å 䏿¡æ¶æ¯ã
䏿¡ç¬¦åè§èçæ¶æ¯åºè¯¥å å«ä¸é¢çåæ®µï¼
type = asset - æ¶æ¯ç±»åï¼å¿
éåæ®µï¼å¹¶ä¸åºè¯¥ä¸º assetï¼file - æä»¶åç§°ï¼å¿
éï¼content - æä»¶å
容ï¼å¿
éï¼sourceMap - sourceMapinfo - èµæºä¿¡æ¯webpack.config.js
const customPlugin = () => (css, result) => {
result.messages.push({
type: 'asset',
file: 'sprite.svg',
content: '<svg>...</svg>',
});
};
const postcssPlugin = postcss.plugin('postcss-assets', customPlugin);
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [postcssPlugin()],
},
},
},
],
},
],
},
};å½éè¦å¨æä»¶ååæ¶è¿è¡éæ°ç¼è¯æ¶ï¼webpack 为äºçè§£è¿æ ·çæä½éè¦æ·»å å¿ è¦çä¾èµã
ç±ä¸¤ç§æ¹å¼æ·»å ä¾èµï¼
result.messages ä¸è§¦åæ¶æ¯ãæ¶æ¯åºè¯¥å å«ä¸é¢ä¸¤ä¸ªå段ï¼
type = dependency - æ¶æ¯ç±»åï¼å¿
éåæ®µï¼å¹¶ä¸åºè¯¥ä¸º dependencyãcontext-dependencyãbuild-dependency æ missing-dependencyï¼file - æä»¶çç»å¯¹è·¯å¾ï¼å¿
éï¼webpack.config.js
const path = require('path');
const customPlugin = () => (css, result) => {
result.messages.push({
type: 'dependency',
file: path.resolve(__dirname, 'path', 'to', 'file'),
});
};
const postcssPlugin = postcss.plugin('postcss-assets', customPlugin);
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [postcssPlugin()],
},
},
},
],
},
],
},
};loaderContextãwebpack.config.js
const path = require('path');
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
config: path.resolve(__dirname, 'path/to/postcss.config.js'),
},
},
},
],
},
],
},
};postcss.config.js
module.exports = (api) => ({
plugins: [
require('path/to/customPlugin')({
loaderContext: api.webpackLoaderContext,
}),
],
});customPlugin.js
const path = require('path');
const customPlugin = (loaderContext) => (css, result) => {
loaderContext.webpack.addDependency(
path.resolve(__dirname, 'path', 'to', 'file')
);
};
module.exports = postcss.plugin('postcss-assets', customPlugin);å¦æä½ è¿æ²¡æè¯»è¿æä»¬çè´¡ç®æåï¼è¯·è±ä¸ç¹æ¶é´é 读å®ã