'Error when trying to run dev server | React, SSR

I got this error when I'm trying to run server:

E:...\node_modules\ts-loader\dist\watch-run.js:29 for (const [filePath, date] of times) { ^

TypeError: times is not iterable at E:...\node_modules\ts-loader\dist\watch-run.js:29:44 at Hook.eval [as callAsync] (eval at create (E:...\node_modules\tapable\lib\HookCodeFactory .js:33:10), :7:1) at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (E:...\node_modules\tapable\lib\Hook.js:18:14) at run (E:...\node_modules\webpack\lib\Watching.js:138:33) at E:...\node_modules\webpack\lib\Watching.js:120:6 at Compiler.readRecords (E:...\node_modules\webpack\lib\Compiler.js:908:11) at run (E:...\node_modules\webpack\lib\Watching.js:116:26) at E:...\node_modules\webpack\lib\Watching.js:112:6 at E:...\node_modules\webpack\lib\HookWebpackError.js:69:3 at E:...Hook.eval [as callAsync] (eval at create (\node_modules\tapable\lib\HookCodeFactory .js:33:10), :6:1)

-- package.json --

 {
  "name": "",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack",
    "dev": "webpack serve"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/react": "^17.0.7",
    "@types/react-dom": "^17.0.5",
    "ts-loader": "^9.2.2",
    "typescript": "^4.2.4",
    "webpack": "^5.37.1",
    "webpack-cli": "^4.7.0",
    "webpack-dev-server": "^3.11.2",
    "webpack-node-externals": "^3.0.0"
  },
  "dependencies": {
    "express": "^4.17.1",
    "nodemon": "^2.0.7",
    "react": "^17.0.2",
    "react-dom": "^17.0.2"
  }
}

-- dev.js --

const webpack = require('webpack');
const webpackConfig = require('../webpack.config');
const nodemon = require('nodemon');
const path = require('path');

const compiler = webpack(webpackConfig);

compiler.run((err) => {
  if(err) {
    console.log('Compilation failed: ', err)
  }

  compiler.watch({}, (err) => {
    if(err) {
      console.log('Compilation failed: ', err);
    }
    console.log('Compilation was successfully');
  });

  nodemon({
    script: path.resolve(__dirname, '../dist/server/server.js'),
    watch: [
      path.resolve(__dirname, '../dist/server'),
      path.resolve(__dirname, '../dist/client')
    ]
  })

});

-- webpack.server.config.js --

const path = require('path');

const nodeExternals = require('webpack-node-externals');

const NODE_ENV = process.env.NODE_ENV;

module.exports = {
  
  target: 'node',
  mode: NODE_ENV ? NODE_ENV : 'production',
  entry: path.resolve(__dirname, '../src/server/server.js'),
  output: {
    path: path.resolve(__dirname, '../dist/server'),
    filename: 'server.js'
  },
  resolve: {
    extensions: ['.ts', '.tsx', '.js']
  },
  externals: [nodeExternals()],
  module: {
    rules: [{
      test: /\.[jt]sx?$/,
      loader: 'ts-loader',
      exclude: /node_modules/
    }]
  },
  optimization: {
    minimize: false
  }
};

-- webpack.client.config.js --

const path = require('path');

const NODE_ENV = process.env.NODE_ENV;
    
module.exports = {

  mode: NODE_ENV ? NODE_ENV : 'production',

  entry: path.resolve(__dirname, '../src/client/index.tsx'),

  output: {
    path:  path.resolve(__dirname, '../dist/client'),
    filename: 'client.js'
  },

  resolve: {
    extensions: ['.ts', '.tsx', '.js']
  },

  module: {
    rules: [{
      test: /\.[jt]sx?$/,
      loader: 'ts-loader',
      exclude: /node_modules/
    }]
  }

}; // module.exports

-- webpack.config.js --

const clientConfig = require('./configs/webpack.client.config');
const serverConfig = require('./configs/webpack.server.config');

module.exports = [
  clientConfig,
  serverConfig
];

-- server.js --

import express from 'express';
import ReactDOM from 'react-dom/server';
import { Header } from "../shared/Header";

const app = express();

app.get('/', (req, res) => {
  res.send(
    ReactDOM.renderToString(Header())
  );
});

app.listen(4000, () => {
  console.log('Server started on port http://localhost:4000');
});

-- Folder structure --



Solution 1:[1]

This trouble from the ts-loader. You can see pull request here.

Instead of using ts-loader you should use babel. You need change handlers .ts and .js in webpack config.

{
            test: /\.[tj]sx?$/,
            use: {
                loader: 'babel-loader',
                options: {
                    presets: ['@babel/preset-env', '@babel/preset-react']
                }
            }
        }

Also add .babelrc with this:

{"presets": ["@babel/react", "@babel/typescript", ["@babel/env", { "modules": false }]]}

Solution 2:[2]

TypeError: times is not iterable

Other than the fact that I'm confused as to why you're using serverside react rendering (unless you are trying out the experimental serverside react components), then you either need to modify your code in accordance with the above error or make times iterable.

ES2015.Iterable defines that as

interface Array<T> {
    /** Iterator */
    [Symbol.iterator](): IterableIterator<T>;

    /**
     * Returns an iterable of key, value pairs for every entry in the array
     */
    entries(): IterableIterator<[number, T]>;

    /**
     * Returns an iterable of keys in the array
     */
    keys(): IterableIterator<number>;

    /**
     * Returns an iterable of values in the array
     */
    values(): IterableIterator<T>;
}

Where this will likely be of most use to you:

const times = 'StackOverflow'
const iterable = [...Array(...times).values()]
console.log(iterable);

This outputs each subcharacter as follows:

[LOG]: ["S", "t", "a", "c", "k", "O", "v", "e", "r", "f", "l", "o", "w"] 

if you don't spread ...times and instead use times it outputs the string as it's defined by const times. Alternatively, you could use a number in place of a string, such as 100. Then, it would return

[LOG]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99] 

if you want a countdown, then write

const times = 101
const iterable = [...Array(times).keys()].reverse();

The above outputs a countdown from 100:

[LOG]: [100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Anyway, you could make whatever times is Iterable, but it is worth noting that you're missing ts-node as a dependency and that should be used if you're using an express server.

Solution 3:[3]

I had the same problem using ts-loader and webpack 5. It was resolved like this:

  1. win+r -> %temp% and cleared this folder
  2. Created a new folder for the project where I moved the sources and package.json
  3. In the new folder, I installed all the dependencies from package.json via "npm i" (without arguments)

Below is my package.the json on which this was done.

{
  "name": "prj-dev-1",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build:dev": "cross-env NODE_ENV=development webpack --config webpack.config.js",
    "build:prod": "cross-env NODE_ENV=production webpack --config webpack.config.js",
    "dev": "cross-env NODE_ENV=development webpack-dev-server"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^17.0.2",
    "react-dom": "^17.0.2"
  },
  "devDependencies": {
    "cross-env": "^7.0.3",
    "html-webpack-plugin": "^5.5.0",
    "ts-loader": "^9.2.6",
    "typescript": "^4.5.5",
    "webpack": "^5.69.0",
    "webpack-cli": "^4.9.2",
    "webpack-dev-server": "^4.7.4"
  }
}

If you start the server via node bin\dev.js and this error persists, then try to do so:

  1. Install npm i -D nodemon-webpack-plugin

  2. Add settings for it in webpack.server.config.js

     watch: true,
     plugins: [
         new NodemonPlugin({
             watch: path.resolve(__dirname, '../dist/server/server.js')
         }), // Dong
     ],
    
  3. run "npx webpack --config webpack.config.js" ("node bin\dev.js" instead)

Solution 4:[4]

Just update version ts-loader to 9.2.8

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Aw3same
Solution 2 Andrew Ross
Solution 3
Solution 4 ??????? ???????