Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Thrown Errors have wrong line numbers #882

Closed
nitwhiz opened this issue Dec 14, 2018 · 14 comments
Closed

Thrown Errors have wrong line numbers #882

nitwhiz opened this issue Dec 14, 2018 · 14 comments
Labels

Comments

@nitwhiz
Copy link

nitwhiz commented Dec 14, 2018

Expected Behaviour

any of the source-map options to tell me where errors actually happened (or throwed to be more exact)

Actual Behaviour

the lines on these error messages have some offset to their actual lines. sometimes printed line numbers are even higher than the actual LoC in the file.

tried the settings from README 1:1 and stuff like 'cheap-module-eval-source-map' and what-not as sourcemap, always an offset.

webpack.conf.js

const path = require('path');

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

module.exports = {
	target: 'node',
	entry: './src/client/cli/CLIClient.ts',
	devtool: 'cheap-module-eval-source-map',
	module: {
		rules: [
			{
				test: /\.(ts)$/,
				use: 'ts-loader',
				exclude: /node_modules/
			}
		]
	},
	resolve: {
		extensions: ['.ts', '.js'],
		alias: {
			Assets: path.resolve(__dirname, 'assets/'),
			Source: path.resolve(__dirname, 'src/')
		}
	},
	output: {
		filename: 'cli-client.js',
		path: path.resolve(__dirname, 'dist')
	},
	plugins: [new NodemonPlugin()],
	externals: [nodeExternals()]
};

error output

bildschirmfoto vom 2018-12-14 14-46-54

BattleGen1.ts

bildschirmfoto vom 2018-12-14 14-47-46

@johnnyreilly
Copy link
Member

I believe this is a webpack issue rather than a ts-loader one. If it is a ts-loader one then we'd happily welcome PRs that improve things!

@licg9999
Copy link

licg9999 commented May 7, 2020

But, If you would like to provide help or solution, it will very thankful.

@bonjourjoel
Copy link

I believe it's a ts-loader issue because it doesn't happen with awesome-typescript-loader. Unfortunately the latter is not maintained. Regards.

@Zhen-dot
Copy link

webpack/webpack#12025

Consensus on this thread seems to be pointing towards it being an issue on the ts-loader side, and persists to this day. Could you kindly reopen this issue for visibility's sake?

@johnnyreilly johnnyreilly reopened this Jan 17, 2022
@johnnyreilly
Copy link
Member

Reopened - if someone would like to work on this we'll happily look at a PR

@Zhen-dot
Copy link

Zhen-dot commented Jan 17, 2022

Also in the case that anyone comes across this issue, I managed to find a temporary workaround that compiles the typescript files first and then using webpack on the compiled files, bypassing ts-loader (and also a short script that adds in aliases from tsconfig paths to replace the tsconfig-paths-webpack-plugin, but note that the script is pretty specific to my usecase and you should probably just manually type it out if you have complex path aliases)

webpack.config.js

const path = require('path');
const CopyPlugin = require('copy-webpack-plugin');
const nodeExternals = require('webpack-node-externals');

const paths = require('require-json5')('./tsconfig.json').compilerOptions.paths;
const alias = {};
Object.entries(paths).forEach(([key, value]) => {
    alias[key.replace('/*', '')] = value.map((v) =>
        path.resolve(__dirname, v.replace('/*', '').replace('src', 'build'))
    );
});
console.log(alias);

module.exports = {
    mode: 'production',
    target: 'node',
    devtool: 'inline-source-map',
    entry: './build/app.js',
    externals: [nodeExternals()],
    externalsPresets: { node: true },
    output: {
        clean: true,
        filename: 'app.js',
        path: path.resolve(__dirname, 'dist'),
        devtoolModuleFilenameTemplate: '[resource-path]',
    },
    resolve: {
        extensions: ['.js'],
        alias,
    },
    module: {
        rules: [{ test: /\.js$/, enforce: 'pre', use: ['source-map-loader'] }],
    },
    plugins: [
        new CopyPlugin({
            patterns: [
                {
                    from: '(package.json|ecosystem.config.js|.npmrc)',
                    info: { minimized: true },
                    noErrorOnMissing: true,
                },
            ],
        }),
    ],
};

tsconfig.json

{
  "$schema": "https://json.schemastore.org/tsconfig",
  "display": "Node 16",
  "compilerOptions": {
    /* Basic Options */
    "target": "es2020",
    "module": "commonjs",
    "outDir": "build",
    "inlineSourceMap": true,
    "removeComments": false,
    "lib": ["es2020"],

    /* Strict Type-Checking Options */
    "strict": true,
    "noImplicitOverride": true,
    "useUnknownInCatchVariables": false,

    /* Additional Checks */
    "strictNullChecks": true,

    /* Module Resolution Options */
    "baseUrl": ".",
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "moduleResolution": "node",
    "types": ["node"],
    "paths": {
      "@/*": ["src/*"],
      "~/*": ["src/types/*"]
    },
    "typeRoots": ["node_modules/@types"]
  },
  /* Advanced Options */
  "skipLibCheck": true,
  "forceConsistentCasingInFileNames": true,
  "ts-node": {
    "files": true
  }
}

package.json

{
  "main": "app.js",
  "scripts": {
    "prebuild": "npx tsc",
    "build": "npx webpack",
    "postbuild": "npx rimraf build"
  }
}

Source file structure

.
├── src
│   ├── app.ts
│   ├── util.ts
│   └── @
│   ├──── A.ts
│   └──── B.ts
├── tsconfig.json
├── package.json
└── webpack.config.js

Prebuild file structure

.
├── build
│   ├── app.js
│   ├── util.js
│   └── @
│   ├──── A.js
│   └──── B.js
├── src
│   ├── app.ts
│   ├── util.ts
│   └── @
│   ├──── A.ts
│   └──── B.ts
├── tsconfig.json
├── package.json
└── webpack.config.js

Postbuild file structure

.
├── dist
│   ├── app.js
│   └── package.json
├── src
│   ├── app.ts
│   ├── util.ts
│   └── @
│   ├──── A.ts
│   └──── B.ts
├── tsconfig.json
├── package.json
└── webpack.config.js

@Zhen-dot
Copy link

UPDATE

After alot of tweaking, I've found that by changing inlineSourceMap: true to sourceMap: true in tsconfig.json, the lines are now correctly displayed using ts-loader. Below is the sample configuration I used.

webpack.config.js

const path = require('path');
const CopyPlugin = require('copy-webpack-plugin');
const nodeExternals = require('webpack-node-externals');
const { TsconfigPathsPlugin } = require('tsconfig-paths-webpack-plugin');

module.exports = {
    mode: 'production',
    target: 'node',
    devtool: 'inline-source-map',
    entry: 'src/app.ts',
    externals: [nodeExternals()],
    externalsPresets: { node: true },
    output: {
        clean: true,
        filename: 'app.js',
        path: path.resolve(__dirname, 'dist'),
        devtoolModuleFilenameTemplate: '[resource-path]',
    },
    resolve: {
        extensions: ['.ts', '.js'],
        plugins: [new TsconfigPathsPlugin({ extensions: ['.ts'] })],
    },
    module: {
        rules: [
            {
                use: 'ts-loader',
                exclude: /node_modules/,
            },
        ],
    },
    plugins: [
        new CopyPlugin({
            patterns: [
                {
                    from: '(package.json|ecosystem.config.js|.npmrc)',
                    info: { minimized: true },
                    noErrorOnMissing: true,
                },
            ],
        }),
    ],
};

tsconfig.json

{
    "$schema": "https://json.schemastore.org/tsconfig",
    "display": "Node 16",
    "compilerOptions": {
        /* Basic Options */
        "target": "es2020",
        "module": "commonjs",
        "outDir": "build",
        "sourceMap": true,
        "removeComments": true,
        "lib": ["es2020"],

        /* Strict Type-Checking Options */
        "strict": true,
        "noImplicitOverride": true,
        "useUnknownInCatchVariables": false,

        /* Additional Checks */
        "strictNullChecks": true,

        /* Module Resolution Options */
        "baseUrl": ".",
        "esModuleInterop": true,
        "resolveJsonModule": true,
        "moduleResolution": "node",
        "types": ["node"],
        "paths": {
            "@/*": ["src/*"],
            "~/*": ["src/types/*"]
        },
        "typeRoots": ["node_modules/@types"]
    },
    /* Advanced Options */
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "ts-node": {
        "files": true
    }
}

package.json

{
  "main": "app.js",
  "scripts": {
    "build": "npx webpack",
    "start": "node ."
  }
}

@johnnyreilly hope this helps with finding a more user-friendly solution to this issue, and perhaps documenting this somewhere in the meantime as a workaround

@johnnyreilly
Copy link
Member

Would you like to submit a docs PR? That'd be super helpful! Thanks for writing up your findings here

@lukepolo
Copy link

I’ll give it a go this morning as well , will make sure it works for us too

@lukepolo
Copy link

we already had sourceMap: true sadly, didnt work for us , here is our implementation of webpack

{
  mode: 'production',
  target: 'node',
  devtool: 'hidden-source-map',
  watchOptions: {
    poll: 1000,
    aggregateTimeout: 200
  },
  stats: {
    hash: false,
    chunks: false,
    modules: false,
    source: false,
    reasons: false,
    version: false,
    timings: false,
    children: false,
    publicPath: false,
    errorDetails: false
  },
  externals: [
    'pg-native',
    'bufferutil',
    'utf-8-validate',
    'consolidate',
    'handlebars',
    'handlebars-layouts'
  ],
  node: {
    __dirname: true,
    __filename: true
  },
  output: {
    path: 'dist',
    filename: '[name].js',
    libraryTarget: 'commonjs2'
  },
  resolve: {
    symlinks: true,
    alias: {
      '@logger': 'node_modules/qx-arch/lib/utilities/logger',
      '@': '',
      '@jobs': 'app/jobs',
      '@http': 'app/http',
      '@config': 'app/config',
      '@metrics': 'app/metrics'
    },
    extensions: [
      '.js',
      '.jsx',
      '.mjs',
      '.ts',
      '.tsx',
      '.json',
      '.node'
    ]
  },
  module: {
    rules: [
      /* config.module.rule('node') */
      {
        test: /\.node$/,
        use: [
          /* config.module.rule('node').use('node-loader') */
          {
            options: {
              name() {
                  return "[name].[ext]";
              }
            }
          }
        ]
      },
      /* config.module.rule('logger-ts') */
      {
        test: /\.ts$/,
        exclude: [
          /node_modules/
        ],
        use: [
          /* config.module.rule('logger-ts').use('string-replace-loader') */
          {
            loader: 'string-replace-loader',
            options: {
              search: '^',
              replace: 'const logger = require("@logger").getLogger(__filename);',
              flags: ''
            }
          }
        ]
      },
      /* config.module.rule('logger-js') */
      {
        test: /\.js$/,
        include: [
          /qx-arch\/lib.*/
        ],
        exclude: [
          /logger/
        ],
        use: [
          /* config.module.rule('logger-js').use('string-replace-loader') */
          {
            loader: 'string-replace-loader',
            options: {
              search: '^',
              replace: 'const logger = require("@logger").getLogger(__filename);',
              flags: ''
            }
          }
        ]
      },
      /* config.module.rule('js') */
      {
        test: /\.js$/
      },
      /* config.module.rule('mjs') */
      {
        test: /\.mjs$/,
        resolve: {
          fullySpecified: false
        }
      },
      /* config.module.rule('typescript') */
      {
        test: /\.tsx?$/,
        exclude: [
          /node_modules/
        ],
        use: [
          /* config.module.rule('typescript').use('ts-loader') */
          {
            loader: 'ts-loader',
            options: {
              transpileOnly: true
            }
          }
        ]
      }
    ]
  },
  optimization: {
    minimize: true,
    minimizer: [
      /* config.optimization.minimizer('minify') */
      new TerserPlugin(
        {
          parallel: true,
          terserOptions: {
            keep_fnames: true,
            keep_classnames: true
          }
        }
      )
    ]
  },
  plugins: [
    /* config.plugin('clean') */
    new CleanWebpackPlugin(
      {
        cleanOnceBeforeBuildPatterns: [
          '**/*'
        ]
      }
    ),
    /* config.plugin('build-info') */
    new BuildInfoWebpackPlugin(),
    /* config.plugin('variables') */
    new DefinePlugin(
      {
        DEV: false,
        __ENV_VARIABLES__: {
          app: {
            env: '"production"'
          }
        }
      }
    ),
    /* config.plugin('copy') */
    new CopyPlugin(
      {
        patterns: [
          {
            from: 'resources/mail',
            to: 'dist/resources/mail'
          },
          {
            from: 'node_modules/consolidate',
            to: 'dist/node_modules/consolidate'
          },
          {
            from: 'node_modules/bluebird',
            to: 'dist/node_modules/bluebird'
          },
          {
            from: 'node_modules/handlebars',
            to: 'dist/node_modules/handlebars'
          },
          {
            from: 'node_modules/handlebars-layouts',
            to: 'dist/node_modules/handlebars-layouts'
          },
          {
            from: 'node_modules/bullmq/dist/commands/**/*.lua',
            to: 'dist'
          },
          {
            from: 'node_modules/@bull-board/ui/dist',
            to: 'dist/node_modules/@bull-board/ui/dist'
          },
          {
            from: 'node_modules/@bull-board/ui/package.json',
            to: 'dist/node_modules/@bull-board/ui/package.json'
          },
          {
            from: 'hasura',
            to: 'dist/hasura'
          },
          {
            from: 'node_modules/ffi-napi/prebuilds/linux-x64',
            to: 'dist/node_modules/ffi-napi/prebuilds/linux-x64'
          },
          {
            from: 'node_modules/ref-napi/prebuilds/linux-x64',
            to: 'dist/node_modules/ref-napi/prebuilds/linux-x64'
          },
          {
            from: 'node_modules/ref-struct-napi',
            to: 'dist/node_modules/ref-struct-napi'
          },
          {
            from: 'node_modules/pg-escape/reserved.txt',
            to: 'dist/node_modules/pg-escape/reserved.txt'
          }
        ]
      }
    )
  ],
  entry: {
    main: [
      'app'
    ]
  }
}

with tsconfig

{
  "compilerOptions": {
    "incremental": true,
    "module": "commonjs",
    "esModuleInterop": true,
    "target": "es2019",
    "moduleResolution": "node",
    "sourceMap": true,
    "outDir": "dist",
    "baseUrl": ".",
    "isolatedModules": true,
    "importHelpers": true,
    "resolveJsonModule": true,
    "allowSyntheticDefaultImports": true,
    "skipLibCheck": true,
    "paths": {
      "@/*": ["*"],
      "@jobs": ["app/jobs"],
      "@http": ["app/http"],
      "@config": ["app/config"],
      "@metrics": ["app/metrics"]
    },
    "types": ["node", "reflect-metadata"],
    "lib": ["es2020"],
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true
  },
  "include": ["**/*.ts", "node_modules/qx-arch/**.*"]
}

@Zhen-dot
Copy link

@lukepolo could you try changing devtool: hidden-source-map to devtool: inline-source-map to see if it helps?

@lukepolo
Copy link

yup that will work for development!

Production still wont work as we cannot release our source map along with the app.

@stale
Copy link

stale bot commented Apr 17, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Apr 17, 2022
@stale
Copy link

stale bot commented Apr 28, 2022

Closing as stale. Please reopen if you'd like to work on this further.

@stale stale bot closed this as completed Apr 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants