javascript - TypeError: res.send är inte en funktion när man försöker ladda sidan


Jag har nyligen övergått mitt byggprocess till att använda TypeScript och Webpack. Nu, efter att ha löst de flesta TS-felen, försöker jag äntligen köra min webbplats.

När jag laddar sidan får jag TypeError: res.send är inte en funktion från min expressjs statiska server. Denna kod har inte ändrats, den har alltid varit densamma även när jag använde gulp och det fungerade bra, men av någon anledning ger det mig nu detta fel efter att ha använt webpack och TS.

Servern startar faktiskt på port 8080 och lyssnar efter förfrågningar. Jag startar den med "start": "node --trace-warnings dist/server/server.js",

Jag vet inte om det är för att jag skrev res-parametern med any eller vad det är..

Fullständig fel:

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 (utdata från TS och webpack)

  • TS exporterar min servermappkod
  • webpack genererar resten via kopiering och paketering

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 (där server.ts och api.ts finns)

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

./src/server/api.ts (api.js genereras i 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');
  });

Svar #1

Som @num8er skriver i kommentaren, måste du korrigera signaturen på den handler du skickade till express.use(). Din kod misslyckas eftersom den första parametern i den funktionen är request-objektet, inte response-objektet. Request-objektet har inte en send()-metod, så du behöver lägga till minst två parametrar om du försöker skicka ett svar:

import express from 'express'

const app = express();

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

Anledningen till att Typescript inte fångade detta fel är att du använder typen any. För att faktiskt få typkontroll, se till att du inte anger typen på någon av dessa parametrar som any. Istället, antingen:

  • Tillåt Typescript att korrekt härleda typen genom att ta bort any; eller
  • Ange typen uttryckligen:
import express from 'express'

const app = express();

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

})

Slutligen, se till att @types/express är installerad.

Du kan kolla in det här:

https://www.typescriptlang.org/play/?ssl=1&ssc=1&pln=11&pc=3#code/JYWwDg9gTgLgBAUwB5iggzuuAzKERwDkyqG6hAUBQMYQB268AhmGHALyIpqYAUAlAG4qLMADoArugS9eaAI4AaOD34cAfHADecKgF9+I1pOmyFALi6lMYgEoJ5EjDGU9LJHujsZIDBGvZNHX1+IA

Svar #2

I mitt fall där jag har skapat en express-server för min nuxtjs api,

res.end({})

verk

Relaterade artiklar