我最近将构建过程转换为使用Typescript和Webpack。现在,在解决了大多数TS错误之后,我终于开始尝试运行我的网站。
加载网站时,我从我的expressjs静态服务器上获得了TypeError: res.send is not a function
。这段代码没有改变,即使我使用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的输出)
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
有效)
{
"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');
});
答案 0 :(得分:1)
正如@ num8er在评论中所写,您需要更正传递给express.use()
的处理程序的签名。您的代码失败,因为该函数中的第一个参数是请求对象,而不是响应对象。请求对象没有send()
方法,因此,如果您要发送响应,则需要至少添加两个参数:
import express from 'express'
const app = express();
app.use((req, res) => {
res.send()
})
Typescript未能捕获此错误的原因是因为您使用的是any
类型。要真正进行类型检查,请确保不要将这两个参数的类型指定为any
。而是:
any
来正确推断类型;或import express from 'express'
const app = express();
app.use((req: express.Request, res: express.Response) => {
})
最后,确保已安装@types/express
。
您可以在此处查看: