Webpack 插件实现 CSS 样式尺寸单位转换

Posted 飞仔FeiZai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Webpack 插件实现 CSS 样式尺寸单位转换相关的知识,希望对你有一定的参考价值。

实现 CSS 样式尺寸单位转换功能的 Webpack 插件

Webpack 插件实现 CSS 样式尺寸单位转换

实现方式一

插件代码

以下是编写的一个 Webpack 插件,用于将样式文件中以 rpx 为单位的值转换为以 px 为单位的值(换算比率为 1px=2rpx):

const pluginName = "CssSzieConvertPlugin";

class CssSzieConvertPlugin 
  apply(compiler) 
    compiler.hooks.emit.tap(pluginName, (compilation) => 
      for (const chunk of compilation.chunks) 
        for (const file of chunk.files) 
          if (file.endsWith(".css")) 
            const originalSource = compilation.assets[file].source();
            const newSource = originalSource.replace(
              /\\b(\\d+(\\.\\d+)?)(rpx)\\b/g,
              (match, number) => `$number / 2px`
            );
            compilation.assets[file] = 
              source: () => newSource,
              size: () => newSource.length,
            ;
          
        
      
    );
  


module.exports = CssSzieConvertPlugin;

上面的代码创建了一个名为 CssSzieConvertPlugin 的插件类。该插件通过注册到 Webpack 的 emit 钩子上来处理样式文件。

在钩子回调函数中,首先遍历所有的 chunk 和文件,并检查哪些文件是 CSS 文件。通过检查文件扩展名是否为 .css 来识别 CSS 文件。

然后,获取原始文件的源代码,并使用正则表达式 /\\b(\\d+(\\.\\d+)?)(rpx)\\b/g 匹配所有以 rpx 为单位的数字。使用 replace 方法将每个匹配项替换为一个新的值。使用一个回调函数,将匹配项中的数字除以 2,并将单位从 "rpx" 更改为 "px"。

最后,更新 compilation.assets 对象中的文件源代码和大小,以便 Webpack 可以使用更新后的文件替换原始文件。

使用代码

在 Webpack 配置文件中使用这个插件,例如:

const CssSzieConvertPlugin = require("./CssSzieConvertPlugin");

module.exports = 
  // ...
  plugins: [
    new CssSzieConvertPlugin(),
    // ...
  ],
;

这将在 Webpack 构建过程中自动应用编写的插件,并将样式文件中的 rpx 值转换为 px 值。

实现方式二

插件代码

以下是编写的另一个 Webpack 插件,用于将样式文件中以 rpx 为单位的值转换为以 px 为单位的值(换算比率为 1px=2rpx):

const pluginName = "CssSzieConvertPlugin";

class CssSzieConvertPlugin 
  constructor(options) 
    this.options = options || ;
  

  apply(compiler) 
    compiler.hooks.emit.tapAsync(pluginName, (compilation, callback) => 
      const  test = /\\.css$/, exclude = /node_modules/  = this.options;
      const files = Object.keys(compilation.assets).filter(
        (filename) => test.test(filename) && !exclude.test(filename)
      );

      files.forEach((file) => 
        let source = compilation.assets[file].source();

        // 使用正则表达式匹配所有以 rpx 为单位的数字
        if (source.replace) 
          // 解决 TypeError: source.replace is not a function 问题

          source = source.replace(
            /\\b(\\d+(\\.\\d+)?)(rpx)\\b/g,
            (match, p1) => `$p1 / 2px`
          );
        

        // 更新编译后的代码
        compilation.assets[file] = 
          source: () => source,
          size: () => source.length,
        ;
      );

      callback();
    );
  


module.exports = CssSzieConvertPlugin;

该插件类名为 CssSzieConvertPlugin,构造函数接受一个选项对象作为参数,该选项对象包含两个属性:testexclude,它们分别表示要处理的文件类型和要排除的文件。默认情况下,test 属性为 /\\css$/exclude 属性为 /node_modules/

apply 方法中,使用 Webpack 的 emit 钩子来处理样式文件。首先使用选项中的正则表达式来过滤要处理的文件,然后遍历这些文件并对它们的源代码进行处理。

对于每个文件,使用正则表达式 /\\b(\\d+(\\.\\d+)?)(rpx)\\b/g 匹配所有以 rpx 为单位的数字,并将每个匹配项替换为该数字除以 2 的结果。最后,更新编译后的代码,并将更新后的源代码和大小存储在 compilation.assets 对象中。

使用代码

  1. 在 Webpack 配置文件中使用这个插件,例如:

    const CssSzieConvertPlugin = require("./CssSzieConvertPlugin");
    
    module.exports = 
      // ...
      plugins: [
        new CssSzieConvertPlugin(
          test: /\\.wxss/,
          exclude: /node_modules/,
        ),
        // ...
      ],
    ;
    

    这将在 Webpack 构建过程中自动应用编写的插件,并将样式文件中的 rpx 值转换为 px 值。在上面的示例中,指定了要处理的文件类型为 .wxss 文件,并排除了 node_modules 目录中的文件。

  2. 在基于 Webpack 构建工具的 Vue 项目中配置,例如:

    // vue.config.js
    const CssSzieConvertPlugin = require("./CssSzieConvertPlugin");
    
    module.exports = 
      configureWebpack: 
        plugins: [
          new CssSzieConvertPlugin(
            test: /\\.(css|js|html)/,
            exclude: /node_modules/,
          ),
        ],
      ,
    ;
    

Webpack - 如何确定 CSS 文件的输出样式?

【中文标题】Webpack - 如何确定 CSS 文件的输出样式?【英文标题】:Webpack - how to determine output style of CSS file? 【发布时间】:2018-02-14 00:12:49 【问题描述】:

使用 Gulp 将 Sass 转换为 CSS 时,我可以选择 CSS 文件的输出样式:嵌套、展开、紧凑和压缩。我是否有同样的机会使用 Webpack?如果是,你能告诉我如何配置 Webpack 来实现我的目标吗?

下面是我当前的 webpack.config.js - 它将 sass 转换为 css,将 ES6 转换为 ES5,并且运行良好:

const ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = 
    entry: [
        "./js/app.js",
        "./scss/main.scss"
    ],
    output: 
        filename: "./js/out.js"
    ,
    watch: true,
    module: 
        loaders: [
            
                test: /.js$/,
                exclude: /node_modules/,
                loader: "babel-loader",
                query: 
                    presets: ["es2015"]
                
            
        ],
        rules: [
            
                test: /.scss$/,
                use: ExtractTextPlugin.extract(
                    fallbackLoader: "style-loader",
                    use: ["css-loader?-url", "sass-loader?-url"]
                )
            
        ]
    ,
    plugins: [
        new ExtractTextPlugin(
            filename: "./css/main.css",
            disable: false,
            allChunks: true
        )
    ]

提前致谢!

【问题讨论】:

【参考方案1】:

@Arnelle Balane 该勾选的解决方案不适用于升级的 webpack 和 sass-loader。

这是使用的最新工作模型:

“webpack”:“^4.44.1”, "sass-loader": "~9.0.3",

    test: /.scss$/,
    use: ExtractTextPlugin.extract(
        fallbackLoader: "style-loader",
        use: [
          
            loader: 'css-loader'
          , 
          
            loader: 'sass-loader',
            options: 
              sassOptions: 
                outputStyle: 'expanded'
              
            
          
        ]
    )

【讨论】:

【参考方案2】:

您正在使用sass-loader,它在后台使用node-sass。 readme 表示您可以通过指定 options 属性将选项直接传递给 node-sass。您可以通过这种方式传入outputStyle 设置。它看起来像这样:


    test: /.scss$/,
    use: ExtractTextPlugin.extract(
        fallbackLoader: "style-loader",
        use: [
            loader: 'css-loader'
        , 
            loader: 'sass-loader',
            options: 
                outputStyle: 'expanded'
            
        ]
    )

【讨论】:

那个勾选的解决方案不适用于升级的 webpack 和 sass-loader。我已经为那些可能也在努力更新的人添加了一个答案

以上是关于Webpack 插件实现 CSS 样式尺寸单位转换的主要内容,如果未能解决你的问题,请参考以下文章

Webpack - 如何确定 CSS 文件的输出样式?

微信小程序尺寸单位rpx以及样式相关介绍

微信小程序尺寸单位rpx以及样式相关介绍

微信小程序尺寸单位rpx以及样式相关介绍

深入浅出的webpack构建工具---PostCss

rpx是微信小程序WXSS的尺寸单位