blog icon indicating copy to clipboard operation
blog copied to clipboard

使用webpack-chain新增scss配置

Open xianzou opened this issue 5 years ago • 3 comments

使用webpack-chain新增scss配置

使用飞冰的脚手架来开发区块的时候发现飞冰默认的样式解析规则是通过匹配test: /\.module\.scss$/来进行css modules,但是因为项目的原因需要修改规则,.scss文件都需要被css modules

ice-scripts 内部的基础 webpack 配置都是通过 webpack-chain 生成的,它通过 webpack 配置链式操作的 API,并可以定义具体 loader 规则和 webpack 插件的名称,可以让开发者更加细粒度修改 webpack 配置。

原先修改方案,修改ice.config.js


module.exports = {
    plugins: [
        'ice-plugin-fusion',
        'ice-plugin-block',
        [
            'ice-plugin-moment-locales', {
                locales: ['zh-cn'],
            },
        ],
    ],
    chainWebpack: config => {
		config.module.rule('css').use('css-loader')
         .loader('css-loader')
         .tap(options => {
             options.modules = true;
             options.localIdentName = '[local]___[hash:base64:5]';
             return options;
         });
    },
};

修改之后发现虽然所有的.scss文件被css modules了,但是node_modules中的scss样式确不能被解析了,经过查看 所有定义的 rule 配置 发现只能自己先加一套规则来处理:

const Config = require('webpack-chain');
module.exports = {
  chainWebpack: (config) => {
    // 输出所有定义的 rule 配置
    console.log(Config.toString(config.module.toConfig().rules));

    // 输出指定 rule 的配置
    const ruleName = 'scss';
    console.log(Config.toString(
      config.module.rule(ruleName).toConfig(),
    ));
  }
}

处理方案,修改ice.config.js

const fs = require('fs');
const path = require('path');

module.exports = {
    plugins: [
        'ice-plugin-fusion',
        'ice-plugin-block',
        [
            'ice-plugin-moment-locales', {
                locales: ['zh-cn'],
            },
        ],
    ],
    chainWebpack: config => {
        // 给样式文件增加一层css文件夹,防止有字体图标库的时候会出现字体路径错误
        config.plugin('MiniCssExtractPlugin').tap(([args]) => [
            Object.assign({}, args, {
                filename: 'css/[name].css',
            }),
        ]);
        // 项目添加jquery支持
        config
            .plugin('env')
            .use(require.resolve('webpack/lib/ProvidePlugin'), [{ jQuery: 'jquery' }]);
        // 新增一套规则
        config.module
            .rule('new-rule-scss')
            .test(/\.(sa|sc|c)ss$/)
            .use('css-hot-loader')
            .loader(path.join(__dirname, '/node_modules/css-hot-loader/index.js'))
            .end()
            .use('MiniCssExtractPlugin.loader')
            .loader(path.join(__dirname, '/node_modules/mini-css-extract-plugin/dist/loader.js'))
            .options({
                publicPath: '../',
            })
            .end()
            .use('css-loader')
            .loader(path.join(__dirname, '/node_modules/css-loader/index.js'))
            .options({
                sourceMap: true,
                modules: true,
                localIdentName: '[folder]--[local]--[hash:base64:7]',
            })
            .end()
            .use('postcss-loader')
            .loader(path.join(__dirname, '/node_modules/postcss-loader/src/index.js'))
            .options({
                sourceMap: true,
                plugins: [function () { /* omitted long function */ }],
            })
            .end()
            .use('sass-loader')
            .loader(path.join(__dirname, '/node_modules/sass-loader/dist/cjs.js'))
            .options({
                sourceMap: true,
            })
            .end()
            .use('ice-skin-loader')
            .loader(path.join(__dirname, '/node_modules/ice-skin-loader/lib/index.js'))
            .options({
                themeFile: false,
                themeConfig: {},
            });

        config.module.rule('scss').exclude.add(/src/); // 排除原来scss-loader包含src目录
        config.module.rule('css').exclude.add(/src/); // 排除原来css-loader包含scr目录
        config.module.rule('new-rule-scss').include.add(/src/); // 新的scss规则只包含src目录
       
       // 输入到本地文件,方便查看rules的配置信息
        // const fd = fs.openSync('test.json', 'w');

        // fs.writeSync(fd, config.toString(config.module.toConfig().rules));
        // fs.closeSync(fd);
    },
};

这样我们src下面的.scss文件就能被正常的css modules了,同时node_modules下的.scss文件也生效了。

xianzou avatar Nov 28 '19 03:11 xianzou

如果是jquery区块,需要配置如下:

        // 指定jquery区块的HtmlWebpackPlugin模板
        config.plugin('HtmlWebpackPlugin').tap(args => [{ ...(args[0] || {}), template: path.join(process.cwd(), './src/index.html') }]);
        // 清楚入口文件配置
        config.entryPoints.clear();
        // 修改入口文件
        config.entry('index').add('./src/index.js'); // jqeury代码直接写在index.js中
        // 防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖
        // 从 CDN 引入 jQuery,而不是把它打包
        config.externals({
            jquery: 'jQuery',
        });
        // 项目添加jquery支持
        config
            .plugin('env')
            .use(require.resolve('webpack/lib/ProvidePlugin'), [{ jQuery: 'jquery' }]);

index.html代码如下:

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <link rel="icon" href="https://img.alicdn.com/tps/TB1kBU7NpXXXXXLXXXXXXXXXXXX-160-160.png" type="image/x-icon">
    <link rel="shortcut icon" href="https://img.alicdn.com/tps/TB1kBU7NpXXXXXLXXXXXXXXXXXX-160-160.png">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
    <title>ICE BLOCK</title>
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="mountNode">
        <div id="test">
            jquery模板测试
        </div>
    </div>
  </body>
</html>

xianzou avatar Dec 17 '19 03:12 xianzou

在webpack的Html中使用如下编译之后生效:

<img src="../../content/images/logo.png">

使用如下确不生效:

<div style="background-image: url('../../content/images/logo.png')">

解决办法:

{
  test: /\.(html)$/,
  include: path.join(__dirname, 'src/views'),
  use: {
    loader: 'html-loader',
    options: {
      interpolate: true ### 关键是这个属性
    }
  }
}

html:

<div style="background-image: url('../../content/images/logo.png')">
webpack-chain配置修改:
// 处理 html中的图片
config.module.rule('new-html-loader-rule').test(/\.html$/)
    .use('html-loader')
    .loader(path.join(__dirname, '/node_modules/html-loader/index.js'))
    .options({
    interpolate: true,
});

xianzou avatar Jan 17 '20 12:01 xianzou

大佬,我目前想在所有的类之前添加 前缀 ,配置如下 image 用的是 postcss-prefixwrap 这个包,本地编译的时候报错了 image 应该是所有的less 文件都无法识别,请问是什么原因

jimStyle88 avatar Aug 10 '20 09:08 jimStyle88