0

我在执行命令时使用的是 Webpack 5 和 Angular 11 ng build --prod && ng run test-app:server:production

在控制台中,它给了我一条错误消息:

Error: ./node_modules/msnodesqlv8/build/Release/sqlserverv8.node 1:2
Module parse failed: Unexpected character '�' (1:2)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders

并且目录没有被构建:dist/test-app/server/main.js 它只创建自己:dist/test-app/browser/

我不知道我在哪里配置了错误的文件。请帮忙。我不知道我做错了什么。

包.json

{
  "name": "test-app",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "dev:ssr": "ng run test-app:serve-ssr",
    "serve:ssr": "node dist/test-app/server/main.js",
    "build:ssr": "ng build --prod && ng run test-app:server:production",
    "prerender": "ng run test-app:prerender",
    "start-webpack:server": "webpack --config webpack.server.config.js "
  },
  "private": true,
  "resolution": {
    "webpack": "^5.0.0"
  },
  "dependencies": {
    "@angular/animations": "~11.0.5",
    "@angular/common": "~11.0.5",
    "@angular/compiler": "~11.0.5",
    "@angular/core": "~11.0.5",
    "@angular/forms": "~11.0.5",
    "@angular/platform-browser": "~11.0.5",
    "@angular/platform-browser-dynamic": "~11.0.5",
    "@angular/platform-server": "^11.0.7",
    "@angular/router": "~11.0.5",
    "@nguniversal/express-engine": "^11.0.1",
    "express": "^4.17.1",
    "msnodesqlv8": "^2.0.8",
    "mssql": "^6.3.1",
    "rxjs": "~6.6.0",
    "tslib": "^2.0.0",
    "zone.js": "~0.10.2"
  },

  "devDependencies": {
    "@angular-devkit/build-angular": "~0.1100.5",
    "@angular/cli": "~11.0.5",
    "@angular/compiler-cli": "~11.0.5",
    "@nguniversal/builders": "^11.0.1",
    "@types/express": "^4.17.9",
    "@types/jasmine": "~3.6.0",
    "@types/node": "^12.11.1",
    "codelyzer": "^6.0.0",
    "jasmine-core": "~3.6.0",
    "jasmine-spec-reporter": "~5.0.0",
    "karma": "~5.1.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage": "~2.0.3",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "^1.5.0",
    "protractor": "~7.0.0",
    "ts-loader": "^8.0.14",
    "ts-node": "^8.3.0",
    "tslint": "~6.1.0",
    "typescript": "~4.0.2",
    "webpack-cli": "^4.3.1"
  },

  "description": "This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 11.0.5.",
  "main": "karma.conf.js",
  "keywords": [],
  "author": "",
  "license": "ISC"
}

角.json:

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "test-app": {
      "projectType": "application",
      "schematics": {
        "@schematics/angular:component": {
          "style": "scss"
        },
        "@schematics/angular:application": {
          "strict": true
        }
      },
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/test-app/browser",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "aot": true,
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.scss"
            ],
            "scripts": []
          },
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "namedChunks": false,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "2mb",
                  "maximumError": "5mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "6kb",
                  "maximumError": "10kb"
                }
              ]
            }
          }
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "test-app:build"
          },
          "configurations": {
            "production": {
              "browserTarget": "test-app:build:production"
            }
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "test-app:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "src/test.ts",

            "polyfills": "src/polyfills.ts",

            "tsConfig": "tsconfig.spec.json",
            "karmaConfig": "karma.conf.js",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.scss"
            ],
            "scripts": []
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "tsconfig.app.json",
              "tsconfig.spec.json",
              "e2e/tsconfig.json",
              "tsconfig.server.json"
            ],
            "exclude": [
              "**/node_modules/**"
            ]
          }
        },
        "e2e": {
          "builder": "@angular-devkit/build-angular:protractor",
          "options": {
            "protractorConfig": "e2e/protractor.conf.js",
            "devServerTarget": "test-app:serve"
          },
          "configurations": {
            "production": {
              "devServerTarget": "test-app:serve:production"
            }
          }
        },
        "server": {
          "builder": "@angular-devkit/build-angular:server",
          "options": {
            "outputPath": "dist/test-app/server",
            "main": "server.ts",
            "tsConfig": "tsconfig.server.json"
          },
          "configurations": {
            "production": {
              "outputHashing": "media",
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "sourceMap": false,
              "optimization": true
            }
          }
        },

        "serve-ssr": {
          "builder": "@nguniversal/builders:ssr-dev-server",
          "options": {
            "browserTarget": "test-app:build",
            "serverTarget": "test-app:server"
          },
          "configurations": {
            "production": {
              "browserTarget": "test-app:build:production",
              "serverTarget": "test-app:server:production"
            }
          }
        },
        "prerender": {
          "builder": "@nguniversal/builders:prerender",
          "options": {
            "browserTarget": "test-app:build:production",
            "serverTarget": "test-app:server:production",
            "routes": [
              "/"
            ]
          },
          "configurations": {
            "production": {}
          }
        }
      }
    }
  },
  "defaultProject": "test-app",
  "cli": {
    "analytics": "e9a52f4c-af8d-4030-8d24-ba3f4b17ec39"
  }
}

服务器.ts:

import 'zone.js/dist/zone-node';
import { ngExpressEngine } from '@nguniversal/express-engine';
import * as express from 'express';
import { join } from 'path';
import { AppServerModule } from './src/main.server';
import { APP_BASE_HREF } from '@angular/common';
import { existsSync } from 'fs';
import { TestRoute } from './server/router/test';

const testRoute: TestRoute = new TestRoute();

export function app(): express.Express {

  const server = express();
  const distFolder = join(process.cwd(), 'dist/test-app/browser');
  const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';

  server.engine('html', ngExpressEngine({
    bootstrap: AppServerModule,
  }));
  server.set('view engine', 'html');
  server.set('views', distFolder);

  server.get('*.*', express.static(distFolder, {
    maxAge: '1y'
  }));

  server.get('*', (req, res) => {
    res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
  });
  return server;
}

function run(): void {
  const port = process.env.PORT || 4000;
  const server = app();
  server.listen(port, () => {
   console.log(`Node Express server listening on http://localhost:${port}`);
  });
}


// Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
// The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main;
const moduleFilename = mainModule && mainModule.filename || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
  run();
}
export * from './src/main.server';

注释掉这行代码:

const testRoute: TestRoute = new TestRoute();

并执行命令 ng build --prod && ng run test-app: server: production 不显示错误。

TestRoute 类包含对库的引用并连接到数据库:

import { Request, Response, NextFunction, response } from 'express';

export class TestRoute {
    contractorRoute(app: any): void {
        app.route('/api/get-test').get((req: Request, res: Response, next: NextFunction) => {
            var sql = require("mssql/msnodesqlv8");
             let config = {
                server: 'SQLDXXX\\XXX',
                database: 'XXX',
                driver: "msnodesqlv8",
                options: {
                    trustedConnection: true
                }
            };
            let connect = new sql.ConnectionPool(config);
            connect.connect().then(() => {
                connect.request().query('select * from [test].[dbo].[test]', (err: TypeError, recordset: any) => {
                    if (err) {                     
                        console.error(" Error: " + err );
                        return;
                    } else {
                        res.send(recordset);             
                    }
                    connect.close();
                })
            }).catch((err: any) => {
                console.error(" Error: " + err );
            });
        })
    }
}

tsconfig.app.json

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./out-tsc/app",
    "types": [
      "node"
    ]
  },
  "files": [
    "src/main.ts",
    "src/polyfills.ts"
  ],
  "include": [
    "src/**/*.d.ts"
  ]
}

tsconfig.json

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "target": "es2015",
    "module": "es2020",
    "lib": [
      "es2018",
      "dom"
    ]
  },
  "angularCompilerOptions": {
    "strictInjectionParameters": true,
    "strictInputAccessModifiers": true,
    "strictTemplates": true
  }
}

tsconfig.server.json

{
  "extends": "./tsconfig.app.json",
  "compilerOptions": {
    "outDir": "./out-tsc/app",
    "target": "es2020",
    "module": "commonjs",
    "types": [
      "node"
    ]
  },
  "files": [
    "src/main.server.ts",
    "server.ts"
  ],
  "angularCompilerOptions": {
    "entryModule": "./src/app/app.server.module#AppServerModule"
  }
}

webpack.server.config.js

const path = require("path");
const webpack = require("webpack");

module.exports = {
  entry: { server: "./server.ts" },
  resolve: { extensions: [".js", ".ts"] },
  target: "node",
  mode: "none",
  // this makes sure we include node_modules and other 3rd party libraries
  externals: [/node_modules/],
  output: {
    path: path.join(__dirname, "dist"),
    filename: "[name].js"
  },
  module: {
    rules: [
     { test: /\.ts$/, loader: "ts-loader" },
     { test: /\.node$/, use: "node-loader" },
    ]
  },
  plugins: [
    // Temporary Fix for issue: https://github.com/angular/angular/issues/11580
    // for 'WARNING Critical dependency: the request of a dependency is an expression'
    new webpack.ContextReplacementPlugin(
      /(.+)?angular(\\|\/)core(.+)?/,
      path.join(__dirname, "src"), // location of your src
      {} // a map of your routes
    ),
    new webpack.ContextReplacementPlugin(
      /(.+)?express(\\|\/)(.+)?/,
      path.join(__dirname, "src"),
      {}
    )
  ]
};

文档https://www.npmjs.com/package/msnodesqlv8说我添加了一行:

{ test: /\.node$/, use: 'node-loader' }

但错误仍然存​​在:

Error: ./node_modules/msnodesqlv8/build/Release/sqlserverv8.node 1:2
Module parse failed: Unexpected character '�' (1:2)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders

我不知道我还应该改进什么。

谢谢您的帮助

应用示例基于: https ://www.ganatan.com/tutorials/server-side-rendering-with-angular-universal

4

0 回答 0