webpack 自動識別 css modules(cssModule混用)


期望達到的效果

import Test from './test.less';  // 這樣的引入需要css modules
import './test.less';            // 這樣的不需要css modules

雖然 css-loader 自帶一些配置可以用來配置是否開啟當前文件cssModule(配置特殊的文件名,路徑等),但是還是覺得沒有上面的那種用起來方便。

參考 umi css module 的實現,源碼:babel-plugin-auto-css-modules,通過寫 Babel 插件,在 import 的 url 上加上參數,webpack 匹配這個參數,進行不同的配置。

這樣的引入方式也可以消除開啟 css module 后,ant design 組件樣式出錯的問題

Babel 插件

// scripts/plugin/auto-css-modules.js
const { extname } = require('path');
const CSS_EXTNAMES = ['.css', '.scss', '.sass', '.less'];
module.exports = () => {
  return {
    visitor: {
      ImportDeclaration(path) {
        const { specifiers, source } = path.node;
        const { value } = source;
        if (specifiers.length > 0 && CSS_EXTNAMES.includes(extname(value))) {
          source.value = `${value}?css_modules`; // 在路徑末尾加上 css_modules 用於 webpack 匹配該文件,如 import Test from './test.less'; 變成 import Test from './test.less?css_modules';
        }
      },
    },
  };
};

.babelrc 中引入插件

{
  "presets": [
    "@babel/preset-react",
    "@babel/preset-env",
    "@babel/preset-typescript"
  ],
  "plugins": [
    "@babel/plugin-transform-runtime",
    "@babel/plugin-proposal-class-properties",
    "lodash",
    "./scripts/plugin/auto-css-modules.js", // 引入插件
    ["import", {
      "libraryName": "antd",
      "libraryDirectory": "es",
      "style": "css"
    }]
  ]
}

在 webpack 中進行配置

聲明兩個不同的loader配置

// 未開啟 css module 的 loader
const cssLoader = [
  'style-loader',
  !isEnvDevelopment && {
    loader: MiniCssExtractPlugin.loader,
  },
  'css-loader',
  {
    loader: 'postcss-loader',
    options: {
      ident: 'postcss',
      plugins: () => [
        require('postcss-preset-env')({
          autoprefixer: {
            flexbox: 'no-2009',
          },
          stage: 3,
        }),
      ],
    },
  },
  {
    loader: 'less-loader',
    options: {
      javascriptEnabled: true,
    },
  },
];
// 開啟 css module 的 loader
const cssModulesLoader = JSON.parse(JSON.stringify(cssLoader));
cssModulesLoader[2] = {
  loader: 'css-loader',
  options: {
    modules: {
      localIdentName: '[local]_[hash:base64:5]',
    },
  },
};

webpack rules 配置:

module: {
  rules: [
    {
      test: /\.(css|less)$/,
      oneOf: [
        {
          resourceQuery: /css_modules/, // 只要匹配到了這個,就是用css modules,
          use: cssModulesLoader.filter(Boolean),
        },
        {
          use: cssLoader.filter(Boolean),
        },
      ],
    },
  ]
}

這樣配置后,就可以在項目中查看具體的效果了。。。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM