I recently converted my build process over to using typescript and webpack. Now after resolving most the TS errors, I'm trying to run my site finally.
When I load the site, I'm getting TypeError: res.send is not a function from my expressjs static server. This code hasn't changed, it's always been the same even when I used gulp and worked fine but for some reason now after using webpack and TS, it's giving me this error now.
The server does indeed start on port 8080 and listens for requests. I start it with "start": "node --trace-warnings dist/server/server.js",
I don't know if it's because I typed the res param with any or what it is..
Full Error:
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 (output from TS and webpack)
- TS is outputting my server folder code
- webpack is outputting the rest via copy and bundling
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 (where server.ts and api.ts live)
{
"extends": "../../tsconfig",
"compilerOptions": {
"outDir": "../../dist/server",
"rootDir": "."
},
"include": ["./*.ts"]
}
./src/server/api.ts
(api.js is outputted to 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');
});
