__webpack_require__ 在部署服务器上找不到模块

__webpack_require__ Module not found on the deployment server

我正在尝试使用 webpack 通过 teamcity 捆绑我的应用程序并将其部署到远程服务器上。我也能够实现它,但是在使用 'node ./dist/main' 应用程序 运行 的最后一步,我收到以下错误。

PS C:\engage-analytics> node .\dist\main.js
node:internal/modules/cjs/loader:928
throw err;
^

Error: Cannot find module '@nestjs/core'
Require stack:
- C:\engage-analytics\dist\main.js
 at Function.Module._resolveFilename (node:internal/modules/cjs/loader:925:15)
 at Function.Module._load (node:internal/modules/cjs/loader:769:27)
 at Module.require (node:internal/modules/cjs/loader:997:19)
 at require (node:internal/modules/cjs/helpers:92:18)
 at Object.@nestjs/core (C:\engage-analytics\dist\main.js:181:18)
 at __webpack_require__ (C:\engage-analytics\dist\main.js:229:32)
 at fn (C:\engage-analytics\dist\main.js:331:21)
 at eval (webpack://nestjs-intro/./src/main.ts?:3:16)
 at Object../src/main.ts (C:\engage-analytics\dist\main.js:52:1)
 at __webpack_require__ (C:\engage-analytics\dist\main.js:229:32) {
code: 'MODULE_NOT_FOUND',
requireStack: [ 'C:\engage-analytics\dist\main.js' ]
}

PS C:\engage-analytics> webpack -v
webpack 5.18.0
webpack-cli 4.4.0

PS C:\engage-analytics> node -v
v15.5.1

当我 运行 在 teamcity 工作目录上执行相同的命令时,我能够启动该应用程序。构建后,我只是将 dist 的内容复制到远程服务器。 这是 package.json,我在 teamcity 服务器上通过 npm 执行突出显示的脚本。

package.json

{
name: "nestjs-intro",
version: "0.0.1",
description: "<p align="center"> <a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo_text.svg" width="320" alt="Nest Logo" /></a> </p>",
author: "",
private: true,
license: "UNLICENSED",
scripts: {
prebuild: "rimraf dist",
**build**: "npm install && npx webpack",
format: "prettier --write "src/**/*.ts" "test/**/*.ts"",
start: "nest start",
start:dev: "nest start --watch",
start:debug: "nest start --debug --watch",
**start:prod**: "node dist/main",
lint: "eslint "{src,apps,libs,test}/**/*.ts" --fix",
test: "jest",
test:watch: "jest --watch",
test:cov: "jest --coverage",
test:debug: "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
test:e2e: "jest --config ./test/jest-e2e.json"
},
dependencies: {
@nestjs/common: "^7.6.5",
@nestjs/core: "^7.5.1",
@nestjs/mongoose: "^7.2.2",
mongoose: "^5.11.3",
reflect-metadata: "^0.1.13",
@nestjs/platform-express: "^7.6.5",
rxjs: "^6.6.3"
},
devDependencies: {
@nestjs/cli: "^7.5.1",
@nestjs/schematics: "^7.1.3",
@nestjs/testing: "^7.5.1",
@types/express: "^4.17.8",
@types/jest: "^26.0.15",
@types/node: "^14.14.6",
@types/supertest: "^2.0.10",
@typescript-eslint/eslint-plugin: "^4.6.1",
@typescript-eslint/parser: "^4.6.1",
eslint: "^7.12.1",
eslint-config-prettier: "7.1.0",
eslint-plugin-prettier: "^3.1.4",
jest: "^26.6.3",
prettier: "^2.2.1",
rimraf: "^3.0.2",
ts-jest: "^26.4.4",
ts-loader: "^8.0.14",
ts-node: "^9.1.1",
tsconfig-paths: "^3.9.0",
tsconfig-paths-webpack-plugin: "^3.3.0",
typescript: "^4.0.5",
webpack: "^5.15.0",
webpack-cli: "^4.4.0"
},
jest: {
moduleFileExtensions: [
"js",
"json",
"ts"
],
rootDir: "src",
testRegex: ".*\.spec\.ts$",
transform: {
^.+\.(t|j)s$: "ts-jest"
},
collectCoverageFrom: [
"**/*.(t|j)s"
],
coverageDirectory: "../coverage",
testEnvironment: "node"
},
main: "webpack.config.js",
}

webpack-config

const webpack = require('webpack');
const path = require('path');
const nodeExternals = require('webpack-node-externals');
// const config = require('config');
const isProduction = typeof process.env.NODE_ENV !== 'undefined' && process.env.NODE_ENV === 'production';
const mode = isProduction ? 'production' : 'development';

module.exports = {
    entry: [
      'webpack/hot/poll?100',
      './src/main.ts',
    ],
    optimization: {
        minimize: false,
    },
    target: 'node',
    mode,
    externals: [
      nodeExternals({
          allowlist: ['webpack/hot/poll?100'],
      }),
    ],
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                loader: 'ts-loader',
                options: {
                  transpileOnly: true
                },
                exclude: /node_modules/,
              }
        ]
    },
    resolve: {
        extensions: ['.tsx', '.ts', '.js'],
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        // new webpack.WatchIgnorePlugin([/\.js$/, /\.d\.ts$/]),        
        new webpack.DefinePlugin(
            { 
                // CONFIG: JSON.stringify(config) 
            }
        ),
    ],
    output: {
        path: path.join(__dirname, 'dist'),
        filename: 'main.js',
    },
};

当使用 nodeExternals 时,webpack 会跳过将 node_modules 捆绑到最终包中,因此您仍然需要 运行 在生产服务器上安装生产依赖项命令。

这是由于某些节点包的低级依赖性而完成的,例如 pg 需要 C++ 绑定或 bcrypt 使用 node-pre-gyp 和 python。将这些依赖项捆绑到您的代码中是不兼容的,这就是为什么需要将它们保留在外部。 There's a lot of discussion that goes more into depth on this here