TypeError: res.send не является функцией при попытке загрузить сайт - PullRequest
1 голос
/ 03 августа 2020

Недавно я преобразовал свой процесс сборки на использование машинописного текста и веб-пакета. Теперь, после устранения большинства ошибок TS, я наконец пытаюсь запустить свой сайт.

Когда я загружаю сайт, я получаю TypeError: res.send is not a function с моего expressjs stati c сервера . Этот код не изменился, он всегда был таким же, даже когда я использовал gulp и работал нормально, но по какой-то причине теперь, после использования webpack и TS, он теперь выдает мне эту ошибку.

Сервер действительно запускается на порт 8080 и слушает запросы. Я начинаю с "start": "node --trace-warnings dist/server/server.js",

Я не знаю, это потому, что я ввел параметр res с any или что это такое ..

Полная ошибка:

TypeError: res.send is not a function
    at dist/server/api.js:58:9
    at Layer.handle [as handle_request] (/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (/node_modules/express/lib/router/index.js:317:13)

dist (вывод из TS и webpack)

  • TS выводит код папки моего сервера
  • webpack is вывод остального посредством копирования и объединения

введите описание изображения здесь

webpack.config. js

const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const TerserJSPlugin = require('terser-webpack-plugin');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');

const isProduction = process.env.NODE_ENV === 'production';

const html = () => {
  return new HtmlWebPackPlugin({
    template: path.resolve(__dirname, 'src/client', 'index.html'),
    filename: 'index.html',
    hash: true,
  });
};

const copyAllOtherDistFiles = () => {
  return new CopyPlugin({
    patterns: [
      { from: 'src/client/assets', to: 'lib/assets' },
      { from: 'package.json', to: './' },
      { from: 'ext/ink-3.1.10/js/ink-all.min.js', to: 'lib/js' },
      { from: 'ext/ink-3.1.10/js/autoload.min.js', to: 'lib/js' },
      { from: 'ext/js/jquery-2.2.3.min.js', to: 'lib/js' },
      { from: 'ext/ink-3.1.10/css/ink.min.css', to: 'lib/css/ink.min.css' },
      { from: 'feed.xml', to: './' },
      {
        from: 'src/shared',
        to: './shared',
        globOptions: {
          ignore: ['**/*suppressed.json'],
        },
      },
    ],
  });
};

module.exports = {
  entry: './src/client/index.tsx',
  output: {
    filename: 'scripts/app.[hash].bundle.js',
    publicPath: '/',
    path: path.resolve(__dirname, 'dist'),
  },
  resolve: {
    extensions: ['.ts', '.tsx', '.js'],
  },
  devtool: isProduction ? '' : 'inline-source-map',
  devServer: {
    writeToDisk: true,
    port: 8080,
  },
  optimization: {
    minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
    splitChunks: {
      cacheGroups: {
        styles: {
          name: 'styles',
          test: /\.css$/,
          chunks: 'all',
          enforce: true,
        },
      },
    },
  },
  module: {
    rules: [
      {
        test: /\.(js)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
        },
      },
      {
        test: /\.(tsx|ts)?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
      {
        test: /\.html$/,
        use: [
          {
            loader: 'html-loader',
          },
        ],
      },
      {
        test: /\.less$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader'],
      },
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              hmr: process.env.NODE_ENV === 'development',
            },
          },
          'css-loader',
        ],
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        loader: 'file-loader',
        options: {
          outputPath: 'lib/assets/fonts',
        },
      },
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: ['url-loader'],
      },
    ],
  },
  plugins: isProduction
    ? [
        new CleanWebpackPlugin(),
        new MiniCssExtractPlugin({
          filename: isProduction ? 'lib/css/main.[hash].css' : 'main.css',
        }),
        html(),
        copyAllOtherDistFiles(),
      ]
    : [new CleanWebpackPlugin(), html(), copyAllOtherDistFiles()],
};

. / tsconfig. json

{
  "compilerOptions": {
    /* Visit https://aka.ms/tsconfig.json to read more about this file */
    "target": "ES2015",                     /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
    "module": "es2020",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
    "lib": ["es6", "dom"],                      /* Specify library files to be included in the compilation. */
        "moduleResolution": "node",
        "allowJs": true,                     /* Allow javascript files to be compiled. */
        "checkJs": true,                     /* Report errors in .js files. */
    "jsx": "react",
    "noImplicitAny": true,
        "sourceMap": false,                   /* Generates corresponding '.map' file. */
    "rootDir": "./",                     /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
        "removeComments": true,              /* Do not emit comments to output. */
    "strict": true,                      /* Enable all strict type-checking options. */
        "noUnusedLocals": true,                /* Report errors on unused locals. */
        "noUnusedParameters": true,            /* Report errors on unused parameters. */
//    "rootDirs": ["."],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
    "typeRoots": [
      "node_modules/@types"
    ],                      /* List of folders to include type definitions from. */
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
        "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
//      "resolveJsonModule": true,
        "skipLibCheck": true,                     /* Skip type checking of declaration files. */
    "forceConsistentCasingInFileNames": true
    },
    "include": [
        "src"
    ],
    "exclude": [
        "/node_modules",
        "/src/server",
        "/src/client/js/ink-config.js",
        "**/test"
  ]
}

. / Client / server / tsconfig. js (где server.ts и api.ts live)

{
    "extends": "../../tsconfig",
    "compilerOptions": {
        "outDir": "../../dist/server",                        
        "rootDir": "."                        
    },
    "include": ["./*.ts"]
}

. / Src / server / api .ts (api.js выводится на dist / server)

const compression = require('compression'),
  express = require('express'),
  historyApi = require('connect-history-api-fallback'),
  oneYear = 31536000;

module.exports = express()
  .use(compression())
  .on('error', function (err: string) {
    console.log(err);
  })
  .use(historyApi())
  .use(
    express.static('dist', {
      maxage: oneYear,
    })
  )
  .use((res: any) => {
    res.send('Sorry, Page Not Found');
  });

1 Ответ

0 голосов
/ 03 августа 2020

Как пишет @ num8er в комментарии, вам нужно исправить подпись обработчика, который вы передали на express.use(). Ваш код не работает, потому что первым параметром в этой функции является объект запроса, а не объект ответа. У объекта запроса нет метода send(), поэтому вам нужно добавить как минимум два параметра, если вы пытаетесь отправить ответ:

import express from 'express'

const app = express();

app.use((req, res) => {
    res.send()
})

Причина, по которой Typescript не обнаружил эту ошибку потому что вы используете тип any. Чтобы действительно получить проверку типа, убедитесь, что вы не указали тип любого из этих параметров как any. Вместо этого либо:

  • Разрешить Typescript правильно определять тип, удаляя any; или
  • Укажите тип явно:
import express from 'express'

const app = express();

app.use((req: express.Request, res: express.Response) => { 

})

Наконец, убедитесь, что @types/express установлен.

Вы можете проверить это здесь:

https://www.typescriptlang.org/play/?ssl=1&ssc=1&pln=11&pc=3#code / JYWwDg9gTgLgBAUwB5iggzuuAzKERwDkyqG6hAUBQMYQB268AhmGHALyIpqYAUAlAG4qLMADoArugS9eaAI4AaOD34cAfHALyIpqYAI4AaOD34cAfHADecKg 10 * IAAI4AaOD34cAfHADecKg * 10XBXLXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX5XX5X5XL0J0J0JJ0J0J0J0J0XXXXXXXXXXXXXXXXXXXX5

...