Webpack似乎可以成功构建我的代码,但是当我尝试运行所构建的应用程序时,出现以下错误:
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
TypeError: Cannot read property 'call' of undefined
调试表明,我对“ node_modules”的依赖关系很多,没有按预期在modules
映射中列出。
在我的情况下,遇到错误时,moduleId
的值为./node_modules/body-parser/index.js
,并且我通过调试确认了modules
中不包含此moduleId。因此,modules[moduleId]
的值为undefined
。
有人能解释为什么吗?
当我检查modules
时,它包含node_modules
中的其他模块和我自己的模块文件。以下是modules
包含的示例:
{
'./node_modules/css-loader/index.js?!./node_modules/less-loader/dist/cjs.js!./src/shared/App.less': function(module, exports, __webpack_require__) { … }
'./node_modules/express/lib sync recursive': function(module, exports) { … }
'./node_modules/mongoose/lib sync recursive':function(module, exports) { … }
'./node_modules/mongoose/lib sync recursive ^.*\/collection$': function(module, exports, __webpack_require__) { … }
'./node_modules/mongoose/lib sync recursive ^.*\/connection$': function(module, exports, __webpack_require__) { … }
'./node_modules/require_optional sync recursive': function(module, exports) { … }
'./src/server/index.ts': function(module, __webpack_exports__, __webpack_require__) { … }
'./src/shared/App.less': function(module, exports, __webpack_require__) { … }
'./src/shared/common/AdminUserMenu.tsx': function(module, __webpack_exports__, __webpack_require__) { … }
'./src/shared/common/Animated.tsx': function(module, __webpack_exports__, __webpack_require__) { … }
…
}
以下是我的webpack配置:
webpack.shared.config.js
const webpack = require('webpack');
const LoadablePlugin = require('@loadable/webpack-plugin');
// https://developer.epages.com/blog/tech-stories/typescript-codesplitting-treeshaking/
const babelLoader = {
loader: 'babel-loader',
options: {
cacheDirectory: true,
presets: [
[
'@babel/preset-env',
// Leave es6 import/export statements alone so that WebpackConcat can do
// tree shaking
{ modules: false }
],
// Transpile TSX
'@babel/preset-react'
],
plugins: ['@babel/plugin-syntax-dynamic-import']
}
};
module.exports = {
mode: 'production',
// Shh
// stats: 'minimal',
// These are the types of files that webpack will be able to understand
// syntatically. ".js" is required in order to parse third-party modules.
resolve: { extensions: ['.js', '.ts', '.tsx', '.less', '.css'] },
plugins: [
new LoadablePlugin(),
new webpack.optimize.ModuleConcatenationPlugin()
],
stats: {
// Examine stats for all modules
maxModules: Infinity,
// Display bailout reasons
optimizationBailout: true
},
optimization: {
mergeDuplicateChunks: true,
flagIncludedChunks: true,
// Figure out the order of modules that will result in the smallest initial
// bundle
occurrenceOrder: true,
// Tell webpack to consider the 'sideEffects' flag in package.json
sideEffects: true,
providedExports: true,
removeAvailableModules: true,
// Tell webpack which exports are used in modules
usedExports: true,
concatenateModules: true,
// Extract common dependency from the entry modules and place them into
// their shared chunks
splitChunks: {
chunks: 'all'
}
},
module: {
rules: [
// Inline any SVG that is less than 1MB big
{
test: /\.svg$/,
loader: 'url-loader',
options: { limit: 1024 }
},
// Place all static resources referenced in code and markup into a folder
// called 'static' and replace reference to locate them there
{
test: /\.(svg|png|jpg|woff|woff2|eot|ttf)$/,
loader: 'file-loader',
options: {
publicPath: '/static',
name: '[folder]/[name].[ext]'
}
},
// Compile Less (the loaders are run in reverse order)
{
test: /\.less$/,
exclude: /node_modules/,
use: [
// 3) Creates isomorphic style nodes from JS strings
'isomorphic-style-loader',
// 2) Translates CSS into CommonJS
{
loader: 'css-loader',
options: {
modules: true,
importLoaders: 1,
// The pattern with which our class names will be automatically generated
localIdentName: '_[hash:base64:2]'
}
},
// 1) Compiles Less to CSS
'less-loader'
]
},
// Compile TypeScript
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
use: [babelLoader, 'ts-loader']
}
]
}
};
webpack.server.config.js
const path = require('path');
const sharedConfig = require('./webpack.shared.config');
module.exports = {
...sharedConfig,
target: 'node',
entry: { server: './src/server/index.ts' },
output: {
libraryTarget: 'commonjs2',
filename: '[name].server.js',
chunkFilename: '[name].[chunkhash].chunk.server.js',
path: path.resolve(__dirname, 'dist/')
}
};