webpack少打包结果缓存偶尔失败

问题描述 投票:0回答:1

当我将webpack4.x升级到5.88.1时,我使用了webpack的缓存功能来提高构建速度。 但在某些无法稳定复现的情况下,webpack缓存的较少编译的代码会出现错误。

比如我的less代码是:

.hover-visible(@cls) {
  & .@{cls} {
    visibility: hidden;
  }

  &:hover {
    & .@{cls} {
      visibility: visible;
    }
  }
}

.fx-resize-pane {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;

  &.expand {
    .left-pane {
      .hover-visible(sidebar-toggle);
    }
  }
}

在node_modules/.cache/webpack/0.pack中,缓存的代码如下:

.fx-resize-pane {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
.expand .left-pane {
  visibility: hidden;
}
.expand .left-pane:hover {
  visibility: visible;
}

我很难理解错误发生在哪里,并且在不升级 webpack5 的情况下从未出现过此类问题。 更重要的是,这种问题无法稳定重现,所以我无法调试代码。

enter image description here enter image description here

版本:

  • “webpack”:“5.88.1”
  • “webpack-cli”:“5.1.4”
  • “更少”:“3.11.1”
  • “less-loader”:“11.1.2”

配置:

// webpack.config.common.js
const path = require('path');
const _ = require('lodash');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const PugWebpackPlugin = require('html-webpack-pug-plugin');
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const glob = require('glob');
const PugSizeWebpackPlugin = require("./plugins/webpack.plugins.pug.size");
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const basePath = path.resolve(__dirname, '../');
const outputPath = path.join(basePath, 'dist');
const htmlPluginArray = [];
const WebpackPluginsPublicPathPlugin = require('./plugins/webpack.plugins.public.path');
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
const LIB_PRIORITY = 100;
const ASSET_PRIORITY = 10;


function getEntry() {
    const entry = {};
    // 读取入口
    glob.sync(path.resolve(basePath, 'views/*/*.pug')).forEach(function (filePath) {
        const [p, appName, fileName] = filePath.match(/\/views\/(.+)\/(.+).pug/);
        const entryPath = path.join(basePath, 'views/' + appName + '/index.tsx');
        if (!['base', 'auth-redirect', 'report-edit'].includes(appName)) {
            entry[appName] = [
                path.resolve(basePath, './build/entry/index.js'),
                'core-js',
                entryPath
            ];
        }
        // 多页面配置
        htmlPluginArray.push({
            template: path.join(basePath, 'views/' + appName + '/' + fileName + '.pug'),
            filename: fileName + '.pug',
            chunks: [appName]
        });
    });
    return entry;
}

function getHtmlPlugin() {
    return htmlPluginArray.map(function (config) {
        return new HtmlWebpackPlugin({
            template: config.template,
            filename: config.filename,
            chunks: config.chunks,
            minify: false,
            inject: 'body'
        });
    });
}

let commonConfig = {
    entry: getEntry(),
    output: {
        filename: '[name].js',
        chunkFilename: '[name].js',
        path: outputPath,
        publicPath: '/pc/',
        pathinfo: false
    },
    cache: {
        type: "filesystem",
        buildDependencies: {
            config: [__filename]
        }
    },
    resolve: {
        extensions: ['.js', '.jsx', '.ts', '.tsx'],
        alias: {
            '~': path.resolve(basePath, 'src'),
            '~crm': path.resolve(basePath, 'src/pages/crm'),
            '~form-design': path.resolve(basePath, 'src/pages/form-edit/container/form-design'),
            'jquery': path.resolve(basePath, 'node_modules/jquery/dist/jquery.slim.min.js'),
            'socket.io-client': path.resolve(basePath, 'node_modules/socket.io-client/dist/socket.io.js'),
            '@fx-ui/jdy-design/icons': path.resolve(basePath, 'node_modules/@fx-ui/jdy-design/lib/icons')
        }
    },
    module: {
        rules: [
            {
                test: /.worker.js$/,
                use: [
                    {
                        loader: 'worker-loader',
                        options: {
                            inline: 'fallback'
                        }
                    }],
                include: path.join(basePath, 'src/workers')
            },
            {
                test: /.tsx?$/,
                use: [
                    'thread-loader',
                    'babel-loader',
                    {
                        loader: 'esbuild-loader',
                        options: {
                            target: 'es2015',
                            tsconfigRaw: require('../tsconfig.json')
                        }
                    }
                ],
                exclude: /node_modules/
            },
            {
                test: /.jsx?$/,
                include: [/[\\/]node_modules[\\/](.*tslib|d3|@antv.*)/],
                exclude: [
                    /[\\/]node_modules[\\/](?!.*tslib|d3|@antv).*/
                ],
                use: ['babel-loader']
            },
            {
                test: /\.css/,
                use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader']
            },
            {
                test: /\.less$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader',
                    'less-loader',
                    {
                        loader: 'style-resources-loader',
                        options: {
                            patterns: [path.join(basePath, 'src/styles/lib/index.less')]
                        }
                    }
                ],
                exclude: /node_modules/
            },
            {
                test: /\.(ttf|eot|woff|woff2)(\?.+)?$/,
                type: 'asset/resource',
                generator: {
                    filename: '[contenthash:12][ext]'
                }
            },
            {
                test: /\.(jpe?g|png|gif|svg)(\?.+)?$/,
                type: 'asset',
                parser: {
                    dataUrlCondition: { maxSize: 8192 }
                },
                generator: {
                    filename: '[contenthash:12][ext]'
                },
                exclude: [path.join(basePath, 'asset'), path.join(basePath, 'src/assets/svgicons')]
            },
            {
                test: /\.svg$/,
                use: [
                    'babel-loader',
                    {
                        loader: '@svgr/webpack',
                        options: {
                            babel: false,
                            icon: true
                        }
                    }
                ],
                include: path.join(basePath, 'src/assets/svgicons')
            }
        ]
    },
    plugins: [
        new CleanWebpackPlugin({
            cleanAfterEveryBuildPatterns: ['!*.pug']
        }),
        new webpack.ProvidePlugin({
            $: 'jquery',
            jQuery: 'jquery',
            "React": "react"
        }),
        new webpack.DefinePlugin({
            APP_ENV: JSON.stringify(process.env.APP_ENV)
        }),
        new MonacoWebpackPlugin({
            languages: ['json', 'javascript', 'python', 'typescript']
        }),
        ...getHtmlPlugin(),
        new PugWebpackPlugin()
    ],
    stats: {
        children: false,
        entrypoints: false,
        modules: false,
    },
    optimization: {
        moduleIds: 'deterministic',
        runtimeChunk: {
            name: 'manifest'
        },
        removeAvailableModules: false,
        removeEmptyChunks: false,
        splitChunks: {
            chunks: 'async',
            cacheGroups: {
                // ......
            }
        }
    }
};


module.exports = commonConfig;
//webpack.dev.config.js
const { merge } = require('webpack-merge');
const commonConfig = require('./webpack.config.common');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
const chalk = require('chalk');
const path = require('path');

const devConfig = merge(commonConfig, {
    output: {
        filename: '[name].js',
        chunkFilename: '[name].js',
    },
    mode: 'development',
    devtool: 'eval-cheap-module-source-map',
    watch: true,
    watchOptions: {
        ignored: /node_modules/
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: '[name].css',
            ignoreOrder: true
        }),
        // 显示打包进度
        new ProgressBarPlugin({
            width: 100,
            format: `webpack build [:bar] ${chalk.green.bold(':percent')} (:elapsed seconds)`,
            clear: false
        })
    ]
});

module.exports = devConfig

为什么会发生这种情况以及如何解决

webpack caching less less-loader
1个回答
0
投票

问题已经解决了,原因是Less版本的问题,当我将Less版本升级到4.1.3后,问题解决了。

© www.soinside.com 2019 - 2024. All rights reserved.