error - TypeError: Cannot set properties of undefined (setting 'entry')
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const resolve = require('resolve');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const Webpackbar = require('webpackbar');
const CopyPlugin = require('copy-webpack-plugin');
const CircularDependencyPlugin = require('circular-dependency-plugin');
const PnpWebpackPlugin = require('pnp-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
// const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const SafePostCssParser = require('postcss-safe-parser');
const postcssNormalize = require('postcss-normalize');
// const { CleanWebpackPlugin } = require("clean-webpack-plugin");
// const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
// const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
const ESLintPlugin = require('eslint-webpack-plugin');
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('react-dev-utils/ForkTsCheckerWebpackPlugin');
const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
const redirectServedPath = require('react-dev-utils/redirectServedPathMiddleware');
const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware');
const evalSourceMapMiddleware = require('react-dev-utils/evalSourceMapMiddleware');
const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
const paths = require('./paths');
const modules = require('./modules');
const getClientEnvironment = require('./env');
const { MFSU } = require('@umijs/mfsu');
const mfsu = new MFSU({
implementor: webpack,
buildDepWithESBuild: {},
});
// Check if TypeScript is setup
const useTypeScript = fs.existsSync(paths.appTsConfig);
// Get the path to the uncompiled service worker (if it exists).
const { swSrc } = paths;
const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1));
const isEnvDevelopment = env.raw.NODE_ENV === 'development';
const isEnvProduction = env.raw.NODE_ENV === 'production';
const isEnvProductionProfile =
isEnvProduction && process.argv.includes('--profile');
const getStyleLoaders = (testReg, loader, options) => {
function applyLoaders(isCSSModules) {
const loaders = [
isEnvDevelopment && require.resolve('style-loader'),
isEnvProduction && {
loader: MiniCssExtractPlugin.loader,
// css is located in `static/css`, use '../../' to locate index.html folder
// in production `paths.publicUrlOrPath` can be a relative path
options: paths.publicUrlOrPath.startsWith('.')
? {
// publicPath: 'auto',
hmr: isEnvDevelopment,
}
: {},
},
{
loader: require.resolve('css-loader'),
options: {
importLoaders: loader ? 1 : 0,
...(isCSSModules
? {
modules: {
localIdentName: '[local]___[hash:base64:5]',
},
}
: {}),
},
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
ident: 'postcss',
plugins: [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009',
},
stage: 3,
}),
postcssNormalize(),
],
},
sourceMap: isEnvDevelopment,
},
},
].filter(Boolean);
if (loader) {
loaders.push(
{
loader: require.resolve(loader),
options: options || {},
},
);
}
return loaders;
}
return {
test: testReg,
oneOf: [
{
resourceQuery: /modules/,
use: applyLoaders(true),
},
{
use: applyLoaders(false),
},
],
};
};
const config = {
mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',
devtool: isEnvProduction ? false : 'cheap-module-source-map', //"eval-cheap-module-source-map"
entry:{
main: [paths.appSrc + '/index.jsx']
},
output: {
// The build folder.
path: isEnvProduction ? paths.appBuild : undefined,
pathinfo: false,
// There will be one main bundle, and one file per asynchronous chunk.
// In development, it does not produce real files.
filename: isEnvProduction
? 'static/js/[name].[contenthash:8].js'
: isEnvDevelopment && 'static/js/bundle.js',
publicPath: paths.publicUrlOrPath,
// Point sourcemap entries to original disk location (format as URL on Windows)
devtoolModuleFilenameTemplate: isEnvProduction
? (info) =>
path
.relative(paths.appSrc, info.absoluteResourcePath)
.replace(/\\/g, '/')
: isEnvDevelopment &&
((info) => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
},
resolve: {
modules: ['node_modules', paths.appNodeModules].concat(
modules.additionalModulePaths || [],
),
extensions: paths.moduleFileExtensions
.map((ext) => `.${ext}`)
.filter((ext) => useTypeScript || !ext.includes('ts')),
alias: {
'@': path.resolve(process.cwd(), 'src'),
'react-native': 'react-native-web',
// Allows for better profiling with ReactDevTools
...(isEnvProductionProfile && {
'react-dom$': 'react-dom/profiling',
'scheduler/tracing': 'scheduler/tracing-profiling',
}),
...(modules.webpackAliases || {}),
},
// 不能设为 false,因为 tnpm 是通过 link 处理依赖,设为 false tnpm 下会有大量的冗余模块
symlinks: true,
mainFields: ['browser', 'module', 'jsnext:main', 'main'],
plugins: [
PnpWebpackPlugin,
],
},
resolveLoader: {
plugins: [
// Also related to Plug'n'Play, but this time it tells webpack to load its loaders
// from the current package.
PnpWebpackPlugin.moduleLoader(module),
],
},
optimization: {
// moduleIds: isEnvDevelopment ? 'named':'deterministic',
// chunkIds: isEnvDevelopment ? 'named':'deterministic',
minimize: isEnvProduction,
removeAvailableModules: isEnvProduction,
removeEmptyChunks: isEnvProduction,
moduleIds: 'deterministic',
chunkIds: 'deterministic',
mangleExports: 'deterministic',
usedExports: true,
minimizer: [
new TerserPlugin({
test: /\.js(\?.*)?$/i,
parallel: !process.env.CI,
extractComments: false,
terserOptions: {
// https://github.com/webpack-contrib/terser-webpack-plugin#terseroptions
parse: {
ecma: 8,
},
compress: {
ecma: 5,
warnings: false,
comparisons: false,
inline: 2,
// turn off flags with small gains to speed up minification
arrows: false,
collapse_vars: false, // 0.3kb
comparisons: false,
computed_props: false,
hoist_funs: false,
hoist_props: false,
hoist_vars: false,
inline: false,
loops: false,
negate_iife: false,
properties: false,
reduce_funcs: false,
reduce_vars: false,
switches: false,
toplevel: false,
typeofs: false,
// a few flags with noticable gains/speed ratio
// numbers based on out of the box vendor bundle
booleans: true, // 0.7kb
if_return: true, // 0.4kb
sequences: true, // 0.7kb
unused: true, // 2.3kb
// required features to drop conditional branches
conditionals: true,
dead_code: true,
evaluate: true,
},
mangle: {
safari10: true,
},
// Added for profiling in devtools
keep_classnames: isEnvProductionProfile,
keep_fnames: isEnvProductionProfile,
output: {
ecma: 5,
comments: false,
// Turned on because emoji and regex is not minified properly using default
// https://github.com/facebook/create-react-app/issues/2488
ascii_only: true,
},
},
}),
new CssMinimizerPlugin(),
// new OptimizeCssAssetsPlugin({})
].filter(Boolean),
splitChunks: isEnvDevelopment
? false
: {
chunks: 'async',
minSize: 30720,
minChunks: 1,
maxAsyncRequests: 6,
maxInitialRequests: 4,
automaticNameDelimiter: '-',
cacheGroups: {
common: {
name: 'common',
chunks: 'all',
priority: -20,
minChunks: 2,
reuseExistingChunk: true,
},
vendors: {
name: 'vendors',
test: /[\\/]node_modules[\\/]/,
chunks: 'all',
priority: -10,
},
react: {
name: 'react',
test: /[\\/]node_modules[\\/](scheduler|react|react-dom|prop-types)/,
chunks: 'all',
enforce: true,
},
antd: {
name: 'antd',
test: /[\\/]node_modules[\\/](@ant-design|antd)[\\/]/,
chunks: 'all',
},
},
},
},
module: {
strictExportPresence: true,
rules: [
{ parser: { requireEnsure: false } },
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
{
test: /\.(js|jsx|ts|tsx)$/,
include: paths.appSrc,
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: true,
// See #6846 for context on why cacheCompression is disabled
cacheCompression: false,
compact: isEnvProduction,
presets: [
[
'@babel/preset-react',
{
runtime: 'automatic',
},
],
],
plugins: [
'lodash',
'@babel/plugin-transform-runtime',
...mfsu.getBabelPlugins(),
].filter(Boolean),
},
},
],
},
getStyleLoaders(/\.(css)(\?.*)?$/),
getStyleLoaders(/\.(less)(\?.*)?$/, 'less-loader', {
sourceMap: isEnvDevelopment,
lessOptions: {
javascriptEnabled: true,
},
}),
getStyleLoaders(/\.(scss|sass)(\?.*)?$/, 'sass-loader', {
sourceMap: isEnvDevelopment,
}),
{
test: /\.(txt|text|md)$/,
type: 'asset/resource',
},
{
test: /\.(bmp|png|jpe?g|gif|webp|ico|svg|eot|woff|woff2|ttf)(\?.*)?$/,
type: 'asset/inline',
},
{
test: /\.html$/,
use: 'html-loader',
},
{
test: /\.(mp4|webm)$/,
type: 'asset/inline',
},
{
test: [/\.avif$/],
type: 'asset/inline',
},
],
},
[isEnvDevelopment ? 'devServer' : 'ignoreWarnings']: isEnvDevelopment
? {
onBeforeSetupMiddleware(devServer) {
for (const middleware of mfsu.getMiddlewares()) {
devServer.app.use(middleware);
}
},
}
: [],
stats: {
assets: false,
moduleAssets: false,
runtime: false,
runtimeModules: false,
modules: false,
entrypoints: false,
},
experiments: {
topLevelAwait: true,
},
plugins: [
new Webpackbar(),
new CircularDependencyPlugin({
exclude: /a\.js|node_modules/, // exclude node_modules
failOnError: false, // show a warning when there is a circular dependency
}),
new HtmlWebpackPlugin(
Object.assign(
{},
{
inject: true,
template: paths.appHtml,
},
isEnvProduction
? {
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
}
: undefined,
),
),
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
new ModuleNotFoundPlugin(paths.appPath),
new webpack.DefinePlugin(env.stringified),
isEnvDevelopment && new WatchMissingNodeModulesPlugin(paths.appNodeModules),
isEnvProduction &&
new CompressionPlugin({
algorithm: 'gzip',
// cache: true,
// threshold: 10240,
}),
new CopyPlugin({
patterns: [
{ from: paths.appPublic, to: path.join(paths.appBuild, '/public') },
// { from: path.join(paths.appSrc,"/locales" ), to: path.join(paths.appBuild,"/public/locales" ) },
],
options: {
concurrency: 100,
},
}),
isEnvProduction &&
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: 'static/css/[name].[contenthash:8].css',
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
ignoreOrder: true, // Enable to remove warnings about conflicting order
}),
isEnvProduction &&
new WebpackManifestPlugin({
fileName: 'assert-manifest.json',
publicPath: paths.publicUrlOrPath,
generate: (seed, files, entrypoints) => {
const manifestFiles = files.reduce((manifest, file) => {
manifest[file.name] = file.path;
return manifest;
}, seed);
const entrypointFiles = entrypoints.main.filter(
(fileName) => !fileName.endsWith('.map'),
);
return {
files: manifestFiles,
entrypoints: entrypointFiles,
};
},
}),
isEnvProduction &&
new WorkboxWebpackPlugin.GenerateSW({
clientsClaim: true, // 让浏览器立即 servece worker 被接管
skipWaiting: true, // 更新 sw 文件后,立即插队到最前面
dontCacheBustURLsMatching: /\.[0-9a-f]{8}\./,
exclude: [/\.map$/, /assert-manifest\.json$/, /LICENSE/],
// importWorkboxFrom: 'cdn',
navigateFallback: `${paths.publicUrlOrPath}index.html`,
navigateFallbackDenylist: [
// Exclude URLs starting with /_, as they're likely an API call
new RegExp('^/_'),
// Exclude any URLs whose last part seems to be a file extension
// as they're likely a resource and not a SPA route.
// URLs containing a "?" character won't be blacklisted as they're likely
// a route with query params (e.g. auth callbacks).
new RegExp('/[^/?]+\\.[^/]+$'),
],
// Bump up the default maximum size (2mb) that's precached,
// to make lazy-loading failure scenarios less likely.
// See https://github.com/cra-template/pwa/issues/13#issuecomment-722667270
maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
}),
// TypeScript type checking
useTypeScript &&
new ForkTsCheckerWebpackPlugin({
typescript: resolve.sync('typescript', {
basedir: paths.appNodeModules,
}),
async: isEnvDevelopment,
checkSyntacticErrors: true,
resolveModuleNameModule: process.versions.pnp
? `${__dirname}/pnpTs.js`
: undefined,
resolveTypeReferenceDirectiveModule: process.versions.pnp
? `${__dirname}/pnpTs.js`
: undefined,
tsconfig: paths.appTsConfig,
reportFiles: [
// This one is specifically to match during CI tests,
// as micromatch doesn't match
// '../cra-template-typescript/template/src/App.tsx'
// otherwise.
'../**/src/**/*.{ts,tsx}',
'**/src/**/*.{ts,tsx}',
'!**/src/**/__tests__/**',
'!**/src/**/?(*.)(spec|test).*',
'!**/src/setupProxy.*',
'!**/src/setupTests.*',
],
silent: true,
// The formatter is invoked directly in WebpackDevServerUtils during development
formatter: isEnvProduction ? typescriptFormatter : undefined,
}),
].filter(Boolean),
// Turn off performance processing because we utilize
// our own hints via the FileSizeReporter
performance: false,
};
mfsu.setWebpackConfig({
config,
});
module.exports = config;
该配置,我确信入口指向的./src/index.jsx 正确,执行卡在:http://localhost:8080/mf-va_remoteEntry.js 该地址的获取上。
✔ Webpack Compiled successfully in 22.77s
[webpack-dev-server] Project is running at:
[webpack-dev-server] Loopback: http://localhost:8080/
[webpack-dev-server] On Your Network (IPv4): http://192.168.18.5:8080/
[webpack-dev-server] On Your Network (IPv6): http://[fe80::e88f:90d2:ae93:e0a6]:8080/
[webpack-dev-server] Content not from webpack is served from 'D:\WebTest\antdfront2-git\public' directory
[webpack-dev-middleware] wait until bundle finished: /
webpack 5.64.1 compiled successfully in 22785 ms
error - TypeError: Cannot set properties of undefined (setting 'entry')
at DepBuilder.getWebpackConfig (D:\WebTest\antdfront2-git\node_modules@umijs\mfsu\dist\depBuilder\depBuilder.js:78:25)
at DepBuilder.
at processTicksAndRejections (node:internal/process/task_queues:96:5)
✔ Webpack Compiled successfully in 25.66s
[webpack-dev-middleware] wait until bundle finished: /static/js/bundle.js.map webpack 5.64.1 compiled successfully in 25662 ms
环境: win10 node 16.13
工程复现:可以使用以上配置,替换:https://github.com/X-neuron/antdFront.git 项目中的 webpack/webpack.config.js , npm run dev 即可
暂不支持 win,手上没有 win 机器,求 PR。
@sorrycc 同样的问题在Mac OS 也出现了,我是用 Webpack5 + Vue 去搭建项目的。我有个 demo 可以复现,https://github.com/unknownzjc/example-webpack-vue-mfsu
我把 @umijs/mfsu 的版本修改成 beta.9 就正常了。现在 npm 上发布的那个 beta.1 的版本不太对劲,不支持 esbuild