带有 NestJS + Typescript + Webpack + node_modules 的单个文件包

Posted

技术标签:

【中文标题】带有 NestJS + Typescript + Webpack + node_modules 的单个文件包【英文标题】:Single file bundle with NestJS + Typescript + Webpack + node_modules 【发布时间】:2019-08-30 13:08:51 【问题描述】:

怎么样?如何捆绑包含 node_module 的 NestJS 项目以供离线应用?

webpack.config.js

const path = require('path');

module.exports = 
  entry: path.join(__dirname, 'dist/main.js'),
  target: 'node',
  output: 
    filename: 'compiled.js',
    path: __dirname,
  ,
  resolve: 
    alias: 
      node_modules: path.join(__dirname, 'node_modules'),
    ,
    extensions: ['.js'],
  ,
;

package.json


  "name": "kai-brs",
  "version": "0.9.1",
  "author": "Sovgut Sergey",
  "private": true,
  "scripts": 
    "build:webpack": "rimraf dist && tsc -p tsconfig.build.json && webpack dist/main.js -o dist/main.bundle.js --mode=production",
    "build": "tsc -p tsconfig.build.json",
    "format": "prettier --write \"src/**/*.ts\"",
    "start": "ts-node -r tsconfig-paths/register src/main.ts",
    "start:dev": "nodemon",
    "start:debug": "nodemon --config nodemon-debug.json",
    "prestart:prod": "rimraf dist && npm run build",
    "start:prod": "node dist/main.js",
    "lint": "tslint -p tsconfig.json -c tslint.json",
    "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": "^6.0.0",
    "@nestjs/core": "^6.0.0",
    "@nestjs/graphql": "^6.0.5",
    "@nestjs/platform-express": "^6.0.0",
    "@nestjs/typeorm": "^6.0.0",
    "@types/dotenv": "^6.1.1",
    "apollo-server-express": "^2.4.8",
    "dotenv": "^7.0.0",
    "graphql": "^14.2.1",
    "graphql-tools": "^4.0.4",
    "joi": "^14.3.1",
    "mssql": "^5.0.5",
    "multer": "^1.4.1",
    "public-ip": "^3.0.0",
    "reflect-metadata": "^0.1.12",
    "request": "^2.88.0",
    "request-promise": "^4.2.4",
    "rimraf": "^2.6.2",
    "rxjs": "^6.3.3",
    "screenshot-desktop": "^1.7.0",
    "typeorm": "^0.2.16",
    "webpack": "^4.29.6",
    "webpack-cli": "^3.3.0"
  ,
  "devDependencies": 
    "@nestjs/testing": "^6.0.0",
    "@types/express": "^4.16.1",
    "@types/jest": "^23.3.13",
    "@types/joi": "^14.3.2",
    "@types/node": "^10.12.18",
    "@types/supertest": "^2.0.7",
    "jest": "^23.6.0",
    "nodemon": "^1.18.9",
    "prettier": "^1.15.3",
    "supertest": "^3.4.1",
    "ts-jest": "^23.10.5",
    "ts-loader": "^5.3.3",
    "ts-node": "^7.0.1",
    "tsconfig-paths": "^3.7.0",
    "tslint": "5.12.1",
    "typescript": "^3.2.4"
  ,
  "jest": 
    "moduleFileExtensions": [
      "js",
      "json",
      "ts"
    ],
    "rootDir": "src",
    "testRegex": ".spec.ts$",
    "transform": 
      "^.+\\.(t|j)s$": "ts-jest"
    ,
    "coverageDirectory": "../coverage",
    "testEnvironment": "node"
  


现在我有这个错误:(

WARNING in ./node_modules/public-ip/node_modules/got/source/request-as-event-emitter.js 72:18-25
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
 @ ./node_modules/public-ip/node_modules/got/source/as-promise.js
 @ ./node_modules/public-ip/node_modules/got/source/create.js
 @ ./node_modules/public-ip/node_modules/got/source/index.js
 @ ./node_modules/public-ip/index.js
 @ ./dist/service/illumenator.service.js
 @ ./dist/service/illumenator.module.js
 @ ./dist/service.module.js
 @ ./dist/main.js

WARNING in ./node_modules/typeorm/platform/PlatformTools.js 107:27-40
Critical dependency: the request of a dependency is an expression
 @ ./node_modules/typeorm/index.js
 @ ./dist/server.module.js
 @ ./dist/main.js

WARNING in ./node_modules/typeorm/platform/PlatformTools.js 112:23-85
Critical dependency: the request of a dependency is an expression
 @ ./node_modules/typeorm/index.js
 @ ./dist/server.module.js
 @ ./dist/main.js

WARNING in ./node_modules/@nestjs/common/utils/load-package.util.js 8:39-59
Critical dependency: the request of a dependency is an expression
 @ ./node_modules/@nestjs/common/serializer/class-serializer.interceptor.js
 @ ./node_modules/@nestjs/common/serializer/index.js
 @ ./node_modules/@nestjs/common/index.js
 @ ./dist/service.module.js
 @ ./dist/main.js

WARNING in ./node_modules/app-root-path/lib/app-root-path.js 14:10-56
Critical dependency: the request of a dependency is an expression
 @ ./node_modules/app-root-path/index.js
 @ ./node_modules/typeorm/platform/PlatformTools.js
 @ ./node_modules/typeorm/index.js
 @ ./dist/server.module.js
 @ ./dist/main.js

WARNING in ./node_modules/parse5/lib/index.js 55:23-49
Critical dependency: the request of a dependency is an expression
 @ ./node_modules/cli-highlight/dist/index.js
 @ ./node_modules/typeorm/platform/PlatformTools.js
 @ ./node_modules/typeorm/index.js
 @ ./dist/server.module.js
 @ ./dist/main.js

WARNING in ./node_modules/express/lib/view.js 81:13-25
Critical dependency: the request of a dependency is an expression
 @ ./node_modules/express/lib/application.js
 @ ./node_modules/express/lib/express.js
 @ ./node_modules/express/index.js
 @ ./node_modules/@nestjs/platform-express/adapters/express-adapter.js
 @ ./node_modules/@nestjs/platform-express/adapters/index.js
 @ ./node_modules/@nestjs/platform-express/index.js
 @ ./dist/service/illumenator.controller.js
 @ ./dist/service/illumenator.module.js
 @ ./dist/service.module.js
 @ ./dist/main.js

WARNING in ./node_modules/@nestjs/core/helpers/load-adapter.js 8:39-63
Critical dependency: the request of a dependency is an expression
 @ ./node_modules/@nestjs/core/nest-factory.js
 @ ./node_modules/@nestjs/core/index.js
 @ ./dist/main.js

WARNING in ./node_modules/optional/optional.js 6:11-26
Critical dependency: the request of a dependency is an expression
 @ ./node_modules/@nestjs/core/nest-application.js
 @ ./node_modules/@nestjs/core/index.js
 @ ./dist/main.js

WARNING in ./node_modules/keyv/src/index.js 18:14-40
Critical dependency: the request of a dependency is an expression
 @ ./node_modules/cacheable-request/src/index.js
 @ ./node_modules/public-ip/node_modules/got/source/request-as-event-emitter.js
 @ ./node_modules/public-ip/node_modules/got/source/as-promise.js
 @ ./node_modules/public-ip/node_modules/got/source/create.js
 @ ./node_modules/public-ip/node_modules/got/source/index.js
 @ ./node_modules/public-ip/index.js
 @ ./dist/service/illumenator.service.js
 @ ./dist/service/illumenator.module.js
 @ ./dist/service.module.js
 @ ./dist/main.js

WARNING in ./node_modules/typeorm/platform/PlatformTools.js
Module not found: Error: Can't resolve 'ioredis' in 'c:\Users\Essential\Documents\kai-brs\node_modules\typeorm\platform'
 @ ./node_modules/typeorm/platform/PlatformTools.js
 @ ./node_modules/typeorm/index.js
 @ ./dist/server.module.js
 @ ./dist/main.js

WARNING in ./node_modules/typeorm/platform/PlatformTools.js
Module not found: Error: Can't resolve 'mongodb' in 'c:\Users\Essential\Documents\kai-brs\node_modules\typeorm\platform'
 @ ./node_modules/typeorm/platform/PlatformTools.js
 @ ./node_modules/typeorm/index.js
 @ ./dist/server.module.js
 @ ./dist/main.js

WARNING in ./node_modules/typeorm/platform/PlatformTools.js
Module not found: Error: Can't resolve 'mysql' in 'c:\Users\Essential\Documents\kai-brs\node_modules\typeorm\platform'
 @ ./node_modules/typeorm/platform/PlatformTools.js
 @ ./node_modules/typeorm/index.js
 @ ./dist/server.module.js
 @ ./dist/main.js

WARNING in ./node_modules/typeorm/platform/PlatformTools.js
Module not found: Error: Can't resolve 'mysql2' in 'c:\Users\Essential\Documents\kai-brs\node_modules\typeorm\platform'
 @ ./node_modules/typeorm/platform/PlatformTools.js
 @ ./node_modules/typeorm/index.js
 @ ./dist/server.module.js
 @ ./dist/main.js

WARNING in ./node_modules/typeorm/platform/PlatformTools.js
Module not found: Error: Can't resolve 'oracledb' in 'c:\Users\Essential\Documents\kai-brs\node_modules\typeorm\platform'
 @ ./node_modules/typeorm/platform/PlatformTools.js
 @ ./node_modules/typeorm/index.js
 @ ./dist/server.module.js
 @ ./dist/main.js

WARNING in ./node_modules/typeorm/platform/PlatformTools.js
Module not found: Error: Can't resolve 'pg' in 'c:\Users\Essential\Documents\kai-brs\node_modules\typeorm\platform'
 @ ./node_modules/typeorm/platform/PlatformTools.js
 @ ./node_modules/typeorm/index.js
 @ ./dist/server.module.js
 @ ./dist/main.js

WARNING in ./node_modules/typeorm/platform/PlatformTools.js
Module not found: Error: Can't resolve 'pg-native' in 'c:\Users\Essential\Documents\kai-brs\node_modules\typeorm\platform'
 @ ./node_modules/typeorm/platform/PlatformTools.js
 @ ./node_modules/typeorm/index.js
 @ ./dist/server.module.js
 @ ./dist/main.js

WARNING in ./node_modules/typeorm/platform/PlatformTools.js
Module not found: Error: Can't resolve 'pg-query-stream' in 'c:\Users\Essential\Documents\kai-brs\node_modules\typeorm\platform'
 @ ./node_modules/typeorm/platform/PlatformTools.js
 @ ./node_modules/typeorm/index.js
 @ ./dist/server.module.js
 @ ./dist/main.js

WARNING in ./node_modules/typeorm/driver/react-native/ReactNativeDriver.js
Module not found: Error: Can't resolve 'react-native-sqlite-storage' in 'c:\Users\Essential\Documents\kai-brs\node_modules\typeorm\driver\react-native'
 @ ./node_modules/typeorm/driver/react-native/ReactNativeDriver.js
 @ ./node_modules/typeorm/driver/DriverFactory.js
 @ ./node_modules/typeorm/connection/Connection.js
 @ ./node_modules/typeorm/connection/ConnectionManager.js
 @ ./node_modules/typeorm/index.js
 @ ./dist/server.module.js
 @ ./dist/main.js

WARNING in ./node_modules/typeorm/platform/PlatformTools.js
Module not found: Error: Can't resolve 'redis' in 'c:\Users\Essential\Documents\kai-brs\node_modules\typeorm\platform'
 @ ./node_modules/typeorm/platform/PlatformTools.js
 @ ./node_modules/typeorm/index.js
 @ ./dist/server.module.js
 @ ./dist/main.js

WARNING in ./node_modules/typeorm/platform/PlatformTools.js
Module not found: Error: Can't resolve 'sql.js' in 'c:\Users\Essential\Documents\kai-brs\node_modules\typeorm\platform'
 @ ./node_modules/typeorm/platform/PlatformTools.js
 @ ./node_modules/typeorm/index.js
 @ ./dist/server.module.js
 @ ./dist/main.js

WARNING in ./node_modules/typeorm/platform/PlatformTools.js
Module not found: Error: Can't resolve 'sqlite3' in 'c:\Users\Essential\Documents\kai-brs\node_modules\typeorm\platform'
 @ ./node_modules/typeorm/platform/PlatformTools.js
 @ ./node_modules/typeorm/index.js
 @ ./dist/server.module.js
 @ ./dist/main.js

ERROR in ./node_modules/@nestjs/core/nest-factory.js
Module not found: Error: Can't resolve '@nestjs/microservices' in 'c:\Users\Essential\Documents\kai-brs\node_modules\@nestjs\core'
 @ ./node_modules/@nestjs/core/nest-factory.js 41:115-147
 @ ./node_modules/@nestjs/core/index.js
 @ ./dist/main.js

ERROR in ./node_modules/@nestjs/core/nest-application.js
Module not found: Error: Can't resolve '@nestjs/microservices' in 'c:\Users\Essential\Documents\kai-brs\node_modules\@nestjs\core'
 @ ./node_modules/@nestjs/core/nest-application.js 101:115-147
 @ ./node_modules/@nestjs/core/index.js
 @ ./dist/main.js

ERROR in ./node_modules/@nestjs/common/cache/cache.providers.js
Module not found: Error: Can't resolve 'cache-manager' in 'c:\Users\Essential\Documents\kai-brs\node_modules\@nestjs\common\cache'
 @ ./node_modules/@nestjs/common/cache/cache.providers.js 10:103-127
 @ ./node_modules/@nestjs/common/cache/cache.module.js
 @ ./node_modules/@nestjs/common/cache/index.js
 @ ./node_modules/@nestjs/common/index.js
 @ ./dist/service.module.js
 @ ./dist/main.js

ERROR in ./node_modules/@nestjs/common/pipes/validation.pipe.js
Module not found: Error: Can't resolve 'class-transformer' in 'c:\Users\Essential\Documents\kai-brs\node_modules\@nestjs\common\pipes'
 @ ./node_modules/@nestjs/common/pipes/validation.pipe.js 43:104-132
 @ ./node_modules/@nestjs/common/pipes/index.js
 @ ./node_modules/@nestjs/common/index.js
 @ ./dist/service.module.js
 @ ./dist/main.js

ERROR in ./node_modules/@nestjs/common/serializer/class-serializer.interceptor.js
Module not found: Error: Can't resolve 'class-transformer' in 'c:\Users\Essential\Documents\kai-brs\node_modules\@nestjs\common\serializer'
 @ ./node_modules/@nestjs/common/serializer/class-serializer.interceptor.js 28:116-144 29:8-36
 @ ./node_modules/@nestjs/common/serializer/index.js
 @ ./node_modules/@nestjs/common/index.js
 @ ./dist/service.module.js
 @ ./dist/main.js

ERROR in ./node_modules/@nestjs/common/pipes/validation.pipe.js
Module not found: Error: Can't resolve 'class-validator' in 'c:\Users\Essential\Documents\kai-brs\node_modules\@nestjs\common\pipes'
 @ ./node_modules/@nestjs/common/pipes/validation.pipe.js 42:100-126
 @ ./node_modules/@nestjs/common/pipes/index.js
 @ ./node_modules/@nestjs/common/index.js
 @ ./dist/service.module.js
 @ ./dist/main.js
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! kai-brs@0.9.1 build:webpack: `rimraf dist && tsc -p tsconfig.build.json && webpack dist/main.js -o dist/main.bundle.js --mode=production`
npm ERR! Exit status 2
npm ERR!
npm ERR! Failed at the kai-brs@0.9.1 build:webpack script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\Essential\AppData\Roaming\npm-cache\_logs\2019-04-09T09_19_07_825Z-debug.log
The terminal process terminated with exit code: 2

或者告诉我一个用于在 node.js 上开发 windows 服务的好框架,它具有脚手架并构建到单个文件中。 (程序集必须包含所有依赖项,即整个 node_modules 文件夹,因为将安装此服务的 PC 没有 Internet 使用npm

【问题讨论】:

嘿嘿,我也有同样的问题。我想用它的所有依赖项构建我的应用程序。你找到答案了吗? 【参考方案1】:

我让它与以下webpack.config.js 一起工作:

const path = require("path");
const webpack = require('webpack');
const  CleanWebpackPlugin  = require('clean-webpack-plugin');

const WebPackIgnorePlugin =

  checkResource: function(resource)
  
    const lazyImports =
    [
        '@nestjs/microservices',
        '@nestjs/microservices/microservices-module',
        'cache-manager',
        'class-transformer',
        'class-validator',
        'fastify-static',
    ];
  
    if (!lazyImports.includes(resource))
      return false;

    try
    
      require.resolve(resource);
    
    catch (err)
    
      return true;
    
  
    return false;
  
;

module.exports =

  mode: 'production',
  target: 'node',
  entry:
  
    server: './src/main.ts',
  ,
  devtool: 'source-map',
  module:
  
    rules:
    [
      
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      ,
    ],
  ,
  resolve:
  
    extensions: [ '.tsx', '.ts', '.js' ],
  ,
  node: 
    __dirname: false,
  ,
  plugins:
  [
    new CleanWebpackPlugin(),
    new webpack.IgnorePlugin(WebPackIgnorePlugin),
  ],
  optimization:
  
    minimize: false
  ,
  performance:
  
    maxEntrypointSize: 1000000000,
    maxAssetSize: 1000000000
  ,
  output:
  
    filename: '[name].js',
    path: path.resolve(__dirname, 'prod'),
  ,
;

这里需要注意的部分是IgnorePlugin。 Nest 对某些模块使用了延迟加载,而 webpack 无法分辨是哪些模块。 checkResource() 对那些在尝试捆绑代码时可能会产生错误的模块进行必要的检查。

您还需要将target: node 选项放在您的配置中,以便webpack 知道一些模块,如fsnet 在Node 中是本机支持的(目标是浏览器时不是这种情况)。

【讨论】:

【参考方案2】:

@SergeySovgut:我不确定你是否已经设法使用 webpack 添加了自定义配置。但这是我目前在我的项目中使用的一个

const nodeExternals = require('webpack-node-externals');
var terserPlugin = require('terser-webpack-plugin');
var uglifyJsPlugin = require('uglifyjs-webpack-plugin');
var dotEnvPlugin = require('dotenv-webpack');

module.exports = function(options) 
    return 
        ...options,
        entry: [ './src/main.ts'],
        watch: false,
        resolve: 
            extensions: ['.ts', '.js', '.jade']
        ,
        externals: [
            nodeExternals(),
        ],
        module: 
            rules: [
                ...options.module.rules,
                
                    test: /\.handlebars$/,
                    loader: 'handlebars-loader',
                    options: 
                        knownHelpersOnly: false,
                        inlineRequires: /\/assets\/(:?images|audio|video)\//ig,
                        partialDirs: [path.join(__dirname, './src/views/email/partials')],
                    ,
                
            ]
        ,
        plugins: [
            ...options.plugins,
            new webpack.HotModuleReplacementPlugin(),
            new webpack.WatchIgnorePlugin([/\.js$/, /\.d\.ts$/]),
            new dotEnvPlugin(
                path: './config/development/.env',
                safe: true,
                systemvars: true,
                silent: true,
                defaults: false
            ), new webpack.DefinePlugin(
                'process.env.NODE_ENV': 'dev',
                'process.env.DEBUG': 'debug'
            ),new webpack.WatchIgnorePlugin([/\.js$/, /\.d\.ts$/]),
        ],
    ;
;

简而言之,nest 包含了 webpack。一些规则已经预设,例如,ts-loader 已被自动配置为将您的 .ts 转换为 .js 文件。所以我们需要做的就是扩展nestjs已经提供的选项,然后在上面编写我们的自定义配置。

我相信大多数配置都很简单,可以通过 webpack 文档轻松获得

要运行该文件,请配置如下脚本 -> `"build:webpack:dev": "rimraf dist && nest build --watch --webpack webpack.dev.config.js"

然后运行npm run build:webpack:dev

更多详情here from official docs

希望对你有帮助

【讨论】:

以上是关于带有 NestJS + Typescript + Webpack + node_modules 的单个文件包的主要内容,如果未能解决你的问题,请参考以下文章

为 TSLint (NestJs) 和 ESLint (VueJs) 设置 VS Code linting

在 NestJS 中使用依赖注入导入 TypeScript 模块

如何在 NestJs 和 typescript 中使用 `mongoose-delete` 插件?

您可以将带有装饰器的 Typescript 类导出为普通类(没有装饰器)吗?

从使用 nestjs API 应用程序调试 npm 库(使用 noidejs、nestjs 和 typescript 构建)

基于typescript 强大的 nestjs 框架试用