当我将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 的情况下从未出现过此类问题。 更重要的是,这种问题无法稳定重现,所以我无法调试代码。
版本:
配置:
// 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
为什么会发生这种情况以及如何解决
问题已经解决了,原因是Less版本的问题,当我将Less版本升级到4.1.3后,问题解决了。